diff --git a/.backportrc.json b/.backportrc.json index 77456cf33f625..2603eb2e2d444 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -1,5 +1,5 @@ { "upstream": "elastic/kibana", - "branches": [{ "name": "7.x", "checked": true }, "7.6", "7.5", "7.4", "7.3", "7.2", "7.1", "7.0", "6.8", "6.7", "6.6", "6.5", "6.4", "6.3", "6.2", "6.1", "6.0", "5.6"], + "branches": [{ "name": "7.x", "checked": true }, "7.7", "7.6", "7.5", "7.4", "7.3", "7.2", "7.1", "7.0", "6.8", "6.7", "6.6", "6.5", "6.4", "6.3", "6.2", "6.1", "6.0", "5.6"], "labels": ["backport"] } diff --git a/.eslintrc.js b/.eslintrc.js index af05af0f6e402..e66331594b4ae 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -491,6 +491,7 @@ module.exports = { 'x-pack/dev-tools/mocha/setup_mocha.js', 'x-pack/scripts/*.js', ], + excludedFiles: ['**/integration_tests/**/*'], rules: { 'import/no-commonjs': 'off', 'prefer-object-spread/prefer-object-spread': 'off', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6519bf9c493f9..f327206464090 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,7 +3,6 @@ # For more info, see https://help.github.com/articles/about-codeowners/ # App -/x-pack/legacy/plugins/dashboard_enhanced/ @elastic/kibana-app /x-pack/legacy/plugins/lens/ @elastic/kibana-app /x-pack/legacy/plugins/graph/ @elastic/kibana-app /src/legacy/server/url_shortening/ @elastic/kibana-app @@ -132,6 +131,7 @@ /src/legacy/server/saved_objects/ @elastic/kibana-platform /src/legacy/server/status/ @elastic/kibana-platform /src/plugins/status_page/ @elastic/kibana-platform +/src/plugins/saved_objects_management/ @elastic/kibana-platform /src/dev/run_check_published_api_changes.ts @elastic/kibana-platform # Security diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 694d1a2f67e2b..4a498af6b1c88 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -1,3 +1,19 @@ --- + - "Team:AppArch": + - "src/plugins/bfetch/**/*.*" + - "src/plugins/dashboard_embeddable_container/**/*.*" + - "src/plugins/data/**/*.*" + - "src/plugins/embeddable/**/*.*" + - "src/plugins/expressions/**/*.*" + - "src/plugins/inspector/**/*.*" + - "src/plugins/ui_actions/**/*.*" + - "src/plugins/visualizations/**/*.*" + - "Feature:Embedding": + - "src/plugins/embeddable/**/*.*" + - "src/plugins/dashboard_embeddable_container/**/*.*" - "Feature:Drilldowns": - "x-pack/plugins/drilldowns/**/*.*" + - "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/**/*.*" + - "Feature:ExpressionLanguage": + - "src/plugins/expressions/**/*.*" + - "src/plugins/bfetch/**/*.*" diff --git a/.gitignore b/.gitignore index efb5c57774633..bd7a954f950e9 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ package-lock.json *.sublime-* npm-debug.log* .tern-project +x-pack/legacy/plugins/apm/tsconfig.json +apm.tsconfig.json +/x-pack/legacy/plugins/apm/e2e/snapshots.js diff --git a/.i18nrc.json b/.i18nrc.json index 78c4be6f4a356..c293b3103a39c 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -33,6 +33,7 @@ "newsfeed": "src/plugins/newsfeed", "regionMap": "src/legacy/core_plugins/region_map", "savedObjects": "src/plugins/saved_objects", + "savedObjectsManagement": "src/plugins/saved_objects_management", "server": "src/legacy/server", "statusPage": "src/legacy/core_plugins/status_page", "telemetry": [ @@ -51,10 +52,7 @@ "visTypeVega": "src/legacy/core_plugins/vis_type_vega", "visTypeVislib": "src/legacy/core_plugins/vis_type_vislib", "visTypeXy": "src/legacy/core_plugins/vis_type_xy", - "visualizations": [ - "src/plugins/visualizations", - "src/legacy/core_plugins/visualizations" - ] + "visualizations": "src/plugins/visualizations" }, "exclude": [ "src/legacy/ui/ui_render/ui_render_mixin.js" diff --git a/docs/apm/custom-links.asciidoc b/docs/apm/custom-links.asciidoc new file mode 100644 index 0000000000000..75c1c9d0009a2 --- /dev/null +++ b/docs/apm/custom-links.asciidoc @@ -0,0 +1,218 @@ +[[custom-links]] +=== Custom links + +Elastic's custom link feature allows you to easily create up to 500 dynamic links +based on your specific APM data. +Custom links can be filtered to only appear in the APM app for relevant services, +environments, transaction types, or transaction names. + +Ready to dive in? Jump straight to the <>. + +[float] +[[custom-links-create]] +=== Create a link + +Each custom link consists of a label, url, and optional filter. +The easiest way to create a custom link is from within the actions dropdown in the transaction detail page. +This method will automatically apply filters, scoping the link to that specific service, +environment, transaction type, and transaction name. + +Alternatively, you can create a custom link in the APM app by navigating to **Settings** > **Customize UI**, +and selecting **Create custom link**. + +[float] +[[custom-links-label]] +==== Label + +The name of your custom link. +This text will be shown in the actions context menu, +so keep it as short as possible. + +TIP: Custom links are displayed alphabetically in the actions menu. + +[float] +[[custom-links-url]] +==== URL + +The URL your link points to. +URLs support dynamic field name variables, encapsulated in double curly brackets: `{{field.name}}`. +These variables will be replaced with transaction metadata when the link is clicked. + +Because everyone's data is different, +you'll need to examine your own traces to see what metadata is available for use. +The easiest way to do this is to select a trace in the APM app, and click **Metadata** in the **Trace Sample** table. + +[role="screenshot"] +image::apm/images/example-metadata.png[Example metadata] + +[float] +[[custom-links-filters]] +==== Filters + +Filter each link to only appear so it only appears for specific services or transactions. +You can filter on the following fields: + +* `service.name` +* `service.env` +* `transaction.type` +* `transaction.name` + +Multiple values are allowed when comma separated. + +[float] +[[custom-links-examples]] +=== Custom link examples + +// Relevant documentation links +:jira-query-params: https://confluence.atlassian.com/jirakb/how-to-create-issues-using-direct-html-links-in-jira-server-159474.html +:github-query-params: https://help.github.com/en/github/managing-your-work-on-github/about-automation-for-issues-and-pull-requests-with-query-parameters + +Not sure where to start with custom links? +Take a look at the examples below, and customize them to your liking! + +[float] +[[custom-links-examples-email]] +==== Email + +Email the owner of a service. + +|==== +|Label |`Email engineer` +|Link |`mailto:@.com` +|Filters |`service.name:` +|==== + +**Example** + +This link opens an email addressed to the team or owner of `python-backend`. +It will only appear on services with the name `python-backend`. + +|==== +|Label |`Email python-backend engineers` +|Link |`mailto:python_team@elastic.co` +|Filters |`service.name:python-backend` +|==== + +[float] +[[custom-links-examples-gh]] +==== GitHub issue + +Open a GitHub issue with pre-populated metadata from the selected trace sample. + +|==== +|Label |`Open an issue in ` +|Link |`https://github.com///issues/new?title=&body=<BODY>` +|Filters |`service.name:client` +|==== + +**Example** + +This link opens a new GitHub issue in the apm-agent-rum repository. +It populates the issue body with relevant metadata from the currently active trace. +Clicking this link results in the following issue being created: + +[role="screenshot"] +image::apm/images/create-github-issue.png[Example github issue] + +|==== +|Label |`Open an issue in apm-rum-js` +|Link |`https://github.com/elastic/apm-agent-rum-js/issues/new?title=Investigate+APM+trace&body=Investigate+the+following+APM+trace%3A%0D%0A%0D%0Aservice.name%3A+{{service.name}}%0D%0Atransaction.id%3A+{{transaction.id}}%0D%0Acontainer.id%3A+{{container.id}}%0D%0Aurl.full%3A+{{url.full}}` +|Filters |`service.name:client` +|==== + +See the {github-query-params}[GitHub automation documentation] for a full list of supported query parameters. + +[float] +[[custom-links-examples-jira]] +==== Jira task + +Create a Jira task with pre-populated metadata from the selected trace sample. + +|==== +|Label |`Open an issue in Jira` +|Link |`https://<JIRA_BASE_URL>/secure/CreateIssueDetails!init.jspa?<ARGUMENTS>` +|==== + +**Example** + +This link creates a new task on the Engineering board in Jira. +It populates the issue body with relevant metadata from the currently active trace. +Clicking this link results in the following task being created in Jira: + +[role="screenshot"] +image::apm/images/create-jira-issue.png[Example jira issue] + +|==== +|Label |`Open a task in Jira` +|Link |`https://test-site-33.atlassian.net/secure/CreateIssueDetails!init.jspa?pid=10000&issuetype=10001&summary=Created+via+APM&description=Investigate+the+following+APM+trace%3A%0D%0A%0D%0Aservice.name%3A+{{service.name}}%0D%0Atransaction.id%3A+{{transaction.id}}%0D%0Acontainer.id%3A+{{container.id}}%0D%0Aurl.full%3A+{{url.full}}` +|==== + +See the {jira-query-params}[Jira application administration knowledge base] +for a full list of supported query parameters. + +[float] +[[custom-links-examples-kib]] +==== Kibana dashboards + +Link to a custom dashboard in Kibana. + +|==== +|Label |`Open transaction in custom visualization` +|Link |`https://kibana-instance/app/kibana#/dashboard?_g=query:(language:kuery,query:'transaction.id:{{transaction.id}}'...` +|==== + +**Example** + +This link opens the current `transaction.id` in a custom kibana dashboard. +There are no filters set. + +|==== +|Label |`Open transaction in Python drilldown viz` +|URL |`https://kibana-instance/app/kibana#/dashboard?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-24h,to:now))&_a=(description:'',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(),gridData:(h:15,i:cb79c1c0-1af8-472c-aaf7-d158a76946fb,w:24,x:0,y:0),id:c8c74b20-6a30-11ea-92ab-b5d3feff11df,panelIndex:cb79c1c0-1af8-472c-aaf7-d158a76946fb,type:visualization,version:'7.7')),query:(language:kuery,query:'transaction.id:{{transaction.id}}'),timeRestore:!f,title:'',viewMode:edit)` +|==== + +[float] +[[custom-links-examples-slack]] +==== Slack channel + +Open a specified slack channel. + +|==== +|Label |`Open SLACK_CHANNEL` +|Link |`https://COMPANY_SLACK.slack.com/archives/SLACK_CHANNEL` +|Filters |`service.name` : `SERVICE_NAME` +|==== + +**Example** + +This link opens a company slack channel, #apm-support. +It only appears when `transaction.name` is `GET user/login`. + +|==== +|Label |`Open #apm-user-support` +|Link |`https://microsoft.slack.com/archives/efk52kt23k` +|Filters |`transaction.name:GET user/login` +|==== + +[float] +[[custom-links-examples-web]] +==== Website + +Open an internal or external website. + +|==== +|Label |`Open <WEBSITE>` +|Link |`https://<COMPANY_SLACK>.slack.com/archives/<SLACK_CHANNEL>` +|Filters |`service.name:<SERVICE_NAME>` +|==== + +**Example** + +This link opens more data on a specific `user.email`. +It only appears on front-end transactions. + +|==== +|Label |`View user internally` +|Link |`https://internal-site.company.com/user/{{user.email}}` +|Filters |`service.name:client` +|==== diff --git a/docs/apm/images/create-github-issue.png b/docs/apm/images/create-github-issue.png new file mode 100644 index 0000000000000..81ea4e5e78c27 Binary files /dev/null and b/docs/apm/images/create-github-issue.png differ diff --git a/docs/apm/images/create-jira-issue.png b/docs/apm/images/create-jira-issue.png new file mode 100644 index 0000000000000..962c98df3f6c6 Binary files /dev/null and b/docs/apm/images/create-jira-issue.png differ diff --git a/docs/apm/images/example-metadata.png b/docs/apm/images/example-metadata.png new file mode 100644 index 0000000000000..0e35f90691723 Binary files /dev/null and b/docs/apm/images/example-metadata.png differ diff --git a/docs/apm/using-the-apm-ui.asciidoc b/docs/apm/using-the-apm-ui.asciidoc index 95ec41cf8a403..1361dc046e3b1 100644 --- a/docs/apm/using-the-apm-ui.asciidoc +++ b/docs/apm/using-the-apm-ui.asciidoc @@ -37,6 +37,8 @@ include::metrics.asciidoc[] include::agent-configuration.asciidoc[] +include::custom-links.asciidoc[] + include::advanced-queries.asciidoc[] include::settings.asciidoc[] diff --git a/docs/canvas/canvas-elements.asciidoc b/docs/canvas/canvas-elements.asciidoc index 1160b735154dc..85f0ee1150ba0 100644 --- a/docs/canvas/canvas-elements.asciidoc +++ b/docs/canvas/canvas-elements.asciidoc @@ -1,132 +1,132 @@ [role="xpack"] -[[element-intro]] -== Showcase your data with elements +[[add-canvas-elements]] +=== Add elements -Canvas _elements_ are the building blocks of your workpad. With elements, you can combine images, text, and visualizations to tell a story about your data. +Create a story about your data by adding elements to your workpad that include images, text, charts, and more. You can create your own elements and connect them to your data sources, add saved objects, and add your own images. -When you add elements to your workpad, you can: - -* <<connect-element-data,Connect the elements to your live data>> - -* <<configure-display-options,Choose how you want the element to appear on your workpad>> - -* <<configure-auto-refresh-interval,Change the data refresh interval>> +[float] +[[create-canvas-element]] +==== Create an element -* <<organize-element,Move and arrange elements on your workpad>> +Choose the type of element you want to use, then connect it to your own data. -* <<element-save,Save your elements>> +. Click *Add element*, then select the element you want to use. ++ +[role="screenshot"] +image::images/canvas-element-select.gif[Canvas elements] -[float] -[[add-canvas-element]] -=== Add elements to your workpad +. To familiarize yourself with the element, use the preconfigured data demo data. ++ +By default, most of the elements you create use demo data until you change the data source. The demo data includes a small data set that you can use to experiment with your element. -Choose the elements to display on your workpad, then familiarize yourself with the element using the preconfigured demo data. By default, most elements use demo data until you change the data source. The demo data includes a small sample data set that you can use to experiment with your element. +. To connect the element to your data, select *Data*, then select one of the following data sources: -To add a Canvas element: +* *{es} SQL* — Access your data in {es} using SQL syntax. For information about SQL syntax, refer to {ref}/sql-spec.html[SQL language]. -. Click *Add element*. +* *{es} raw data* — Access your raw data in {es} without the use of aggregations. Use {es} raw data when you have low volume datasets, or to plot exact, non-aggregated values. -. In the *Elements* window, select the element you want to use. -+ -[role="screenshot"] -image::images/canvas-element-select.gif[Canvas elements] +* *Timelion* — Access your time series data using <<timelion,Timelion>> queries. To use Timelion queries, you can enter a query using the <<lucene-query,Lucene Query Syntax>>. -. Play around with the default settings and see what the element can do. +[float] +[[canvas-add-object]] +==== Add a saved object -To add a map: +Add a <<managing-saved-objects,saved object>>, such as a map or Lens visualization, then customize it to fit your display needs. . Click *Embed object*. -. Select the map you want to add to the workpad. +. Select the object you want to add. + [role="screenshot"] image::images/canvas-map-embed.gif[] -NOTE: Demo data is only supported on Canvas elements. Maps do not support demo data. +. To use the customization options, click the panel menu, then select one of the following options: + +* *Edit map* — Opens <<maps,Maps>> so that you can edit the original map. + +* *Customize panel* — Specifies the object title options. -Want to use a different element? You can delete the element by selecting it, clicking the *Element options* icon in the top right, then selecting *Delete*. +* *Inspect* — Allows you to drill down into the element data. + +* *Customize time range* — Exposes a time filter dedicated to the map. [float] -[[connect-element-data]] -=== Connect the Canvas element to your data +[[canvas-add-image]] +==== Add your own image -When you have finished using the demo data, connect the Canvas element to a data source. +To personalize your workpad, add your own logos and graphics. -NOTE: Maps do not support data sources. To change the map data, refer to <<maps, Elastic Maps>>. +. Click *Manage assets*. -. Make sure that the element is selected, then select *Data*. +. On the *Manage workpad assets* window, drag and drop your images. -. Click *Change your data source*. +. To add the image to the workpad, click the *Create image element* icon. ++ +[role="screenshot"] +image::images/canvas-add-image.gif[] [float] -[[elasticsearch-sql-data-source]] -==== Connect to {es} SQL +[[move-canvas-elements]] +==== Organize elements + +Move and resize your elements to meet your design needs. -Access your data in {es} using SQL syntax. For information about SQL syntax, refer to {ref}/sql-spec.html[SQL language]. +* To move, click and hold the element, then drag to the new location. -. Click *{es} SQL*. +* To move by 1 pixel, select the element, press and hold Shift, then use your arrow keys. -. In the *{es} SQL query* box, enter your query, then *Preview* it. +* To move by 10 pixels, select the element, then use your arrow keys. -. If everything looks correct, *Save* it. +* To resize, click and drag the resize handles to the new dimensions. [float] -[[elasticsearch-raw-doc-data-source]] -==== Connect to {es} raw data +[[format-canvas-elements]] +==== Format elements -Access your raw data in {es} without the use of aggregations. Use {es} raw data when you have low volume datasets, or to plot exact, non-aggregated values. +Align, distribute, and reorder elements for consistency and readability across your workpad pages. -To use targeted queries, you can enter a query using the <<lucene-query,Lucene Query Syntax>>. +Access the align, distribute, and reorder options by clicking the *Element options* icon. -. Click *{es} raw documents*. +[role="screenshot"] +image::images/canvas_element_options.png[] -. In the *Index* field, enter the index pattern that you want to display. +To align elements: -. From the *Fields* dropdown, select the associated fields you want to display. +. Press and hold Shift, then select the elements you want to align. -. To sort the data, select an option from the *Sort Field* and *Sort Order* dropdowns. +. Click the , then select *Group*. -. For more targeted queries, enter a *Query* using the Lucene query string syntax. +. Click the *Element options* icon, then select *Alignment*. -. *Preview* the query. +. Select the alignment option. -. If your query looks correct, *Save* it. +To distribute elements: -[float] -[[timelion-data-source]] -==== Connect to Timelion +. Press and hold Shift, then select the elements you want to distribute. -Access your time series data using <<timelion,Timelion>> queries. To use Timelion queries, you can enter a query using the <<lucene-query,Lucene Query Syntax>>. +. Click the *Element options* icon, then select *Group*. -. Click *Timelion*. +. Click the *Element options* icon, then select *Distribution*. -. Enter a *Query* using the Lucene query string syntax. +. Select the distribution option. -. Enter the *Interval*, then *Preview* the query. +To reorder elements: -. If your query looks correct, *Save* it. +. Select the element you want to reorder. -[float] -[[configure-display-options]] -=== Choose the display options +. Click the *Element options* icon, then select *Order*. -Choose how you want the elements to appear on your workpad. +. Select the order option. [float] [[data-display]] -==== Specify how to display the data - -When you connect your element to a data source, the element often appears as a warning. To remove the error, specify the display options. +==== Change the element display options -. Click *Display* +Each element has its own display options to fit your design needs. -. Change the display options for the element. +To choose the display options, click *Display*, then make your changes. -[float] -[[element-display-container]] -==== Change the appearance of the element container - -Further define the appearance of the element container and border. +To define the appearance of the container and border: . Next to *Element style*, click *+*, then select *Container style*. @@ -134,17 +134,13 @@ Further define the appearance of the element container and border. . Change the *Appearance* and *Border* options. -[float] -[[apply-element-styles]] -==== Apply a set of styles - -To make your element look exactly the way you want, apply CSS overrides. +To apply CSS overrides: . Next to *Element style*, click *+*, then select *CSS*. . Enter the *CSS*. For example, to center the Markdown element, enter: + -[source,js] +[source,text] -------------------------------------------------- .canvasRenderEl h1 { text.align: center; @@ -154,137 +150,31 @@ text.align: center; . Click *Apply stylesheet*. [float] -[[configure-auto-refresh-interval]] -==== Change the data auto-refresh interval - -Increase or decrease how often your Canvas element data refreshes on your workpad. - -. In the top left corner, click the *Control settings* icon. - -. Under *Change auto-refresh interval*, select the interval you want to use. -+ -[role="screenshot"] -image::images/canvas-refresh-interval.png[Element data refresh interval] - -TIP: To manually refresh the data, click the *Refresh data* icon. - -[float] -[[canvas-time-range]] -==== Customize map time ranges - -Configure the maps on your workpad for a specific time range. - -From the panel menu, select *Customize time range* to expose a time filter dedicated to the map. - -[role="screenshot"] -image::images/canvas_map-time-filter.gif[] - -[float] -[[organize-element]] -=== Organize the elements on your workpad - -Choose where you want the elements to appear on your workpad. - -[float] -[[move-canvas-elements]] -==== Move elements - -Move the element to a preferred location on your workpad. As you move the element, notice the alignment lines that appear to help you place the element exactly where you want it. - -* Click and drag the element to your preferred location. - -* To move the element by 1 pixel, select the element, press and hold Shift, then use your arrow keys. - -* To move the element by 10 pixels, select the element, then use your arrow keys. - -[float] -[[resize-canvas-elements]] -==== Resize elements +[[save-elements]] +==== Save elements -Make your elements bigger or smaller than the default size. +To use the elements across all workpads, save the elements. -. Select the element. - -. Click and drag the resize handles to the size you want. - -[float] -[[align-canvas-elements]] -==== Align elements +When you're ready to save your element, select the element, then click the *Save as new element* icon. -Align two or more elements on your workpad. - -. Press and hold Shift, then select the elements you want to align. - -. Click the *Element options* icon in the top right corner, then select *Align elements*. - -. From the *Alignment* menu, select how you want to align the elements on the workpad. -+ [role="screenshot"] -image::images/canvas-align-elements.gif[Align elements] - -[float] -[[distribute-canvas-elements]] -==== Distribute elements - -Distribute three or more elements on your workpad. - -. Press and hold Shift, then select the elements you want to distribute. - -. Click the *Element options* icon in the top right corner, then select *Distribute elements*. +image::images/canvas_save_element.png[] -. From the *Distribution* menu, select how you want to distribute the elements on the workpad. -+ -[role="screenshot"] -image::images/canvas-distribute-elements.gif[Distribute elements] - -[float] -[[change-element-order]] -==== Change the element order - -Change the order of how the elements are displayed on your workpad. - -. Select an element. - -. In the top right corder, click the *Element options* icon. - -. Select *Order*, then select the order that you want the element to appear. - -[float] -[[zoom-in-out]] -=== Use the zoom options - -In the upper left corner, click the *Zoom controls* icon, then select one of the options. - -[role="screenshot"] -image::images/canvas-zoom-controls.png[Zoom controls] - -[float] -[[element-save]] -=== Save elements - -After you have made changes to elements, save them so that you can reuse them across all of your workpads. - -. Select the element that you want to save. -+ To save a group of elements, press and hold Shift, then select the elements you want to save. -. Click the *Save as new element* icon. - -. In the *Create new element* window, enter a *Name*. - -. Enter an optional *Description*, then click *Save*. - -. To access the element, click *Add element*, then select *My elements*. +To access your saved elements, click *Add element*, then select *My elements*. [float] -[[add-more-pages]] -=== Add pages +[[delete-elements]] +==== Delete elements -When you have run out of room on your workpad page, add more pages. +When you no longer need an element, delete it from your workpad. -. Click *Page 1*, then click *+*. +. Select the element you want to delete. -. On the *Page* editor panel on the right, select the page transition from the *Transition* dropdown. +. Click the *Element options* icon. + [role="screenshot"] -image::images/canvas-add-pages.gif[Add pages] +image::images/canvas_element_options.png[] + +. Select *Delete*. diff --git a/docs/canvas/canvas-present-workpad.asciidoc b/docs/canvas/canvas-present-workpad.asciidoc index 21b112f68eb69..486686cd857b5 100644 --- a/docs/canvas/canvas-present-workpad.asciidoc +++ b/docs/canvas/canvas-present-workpad.asciidoc @@ -1,12 +1,12 @@ [role="xpack"] [[canvas-present-workpad]] -== Present your workpad +=== Present your workpad When you are ready to present your workpad, use and enable the presentation options. [float] [[view-fullscreen-mode]] -=== View your workpad in fullscreen mode +==== View your workpad in fullscreen mode In the upper left corner, click the *Enter fullscreen mode* icon. @@ -15,7 +15,7 @@ image::images/canvas-fullscreen.png[Fullscreen mode] [float] [[enable-autoplay]] -=== Enable autoplay +==== Enable autoplay Automatically cycle through your workpads pages in fullscreen mode. diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc index c46ba8a980ce2..dbba12865b8ca 100644 --- a/docs/canvas/canvas-share-workpad.asciidoc +++ b/docs/canvas/canvas-share-workpad.asciidoc @@ -1,12 +1,12 @@ [role="xpack"] [[workpad-share-options]] -== Share your workpad +=== Share your workpad When you've finished your workpad, you can share it outside of {kib}. [float] [[export-single-workpad]] -=== Export workpads +==== Export workpads Create a JSON file of your workpad that you can export outside of {kib}. @@ -21,7 +21,7 @@ Want to export multiple workpads? Go to the *Canvas workpads* view, select the w [float] [[create-workpad-pdf]] -=== Create a PDF +==== Create a PDF If you have a license that supports the {report-features}, you can create a PDF copy of your workpad that you can save and share outside {kib}. @@ -36,7 +36,7 @@ image::images/canvas-generate-pdf.gif[Generate PDF] [float] [[create-workpad-URL]] -=== Create a POST URL +==== Create a POST URL If you have a license that supports the {report-features}, you can create a POST URL that you can use to automatically generate PDF reports using Watcher or a script. @@ -51,7 +51,7 @@ image::images/canvas-create-URL.gif[Create POST URL] [float] [[add-workpad-website]] -=== Share the workpad on a website +==== Share the workpad on a website beta[] Canvas allows you to create _shareables_, which are workpads that you download and securely share on any website. To customize the behavior of the workpad on your website, you can choose to autoplay the pages or hide the workpad toolbar. @@ -70,13 +70,11 @@ NOTE: Shareable workpads encode the current state of the workpad in a JSON file. [float] [[change-the-workpad-settings]] -=== Change the settings +==== Change the settings After you've added the workpad to your website, you can change the autoplay and toolbar settings. -[float] -[[shareable-workpad-enable-autoplay]] -==== Change the autoplay settings +To change the autoplay settings: . In the lower right corner of the shareable workpad, click the settings icon. @@ -85,9 +83,7 @@ After you've added the workpad to your website, you can change the autoplay and [role="screenshot"] image::images/canvas_share_autoplay_480.gif[Autoplay settings] -[float] -[[hide-workpad-toolbar]] -==== Change the toolbar settings +To change the toolbar settings: . In the lower right corner, click the settings icon. diff --git a/docs/canvas/canvas-tutorial.asciidoc b/docs/canvas/canvas-tutorial.asciidoc index efc03f1c6c494..b6d684bdf5dde 100644 --- a/docs/canvas/canvas-tutorial.asciidoc +++ b/docs/canvas/canvas-tutorial.asciidoc @@ -12,7 +12,7 @@ For this tutorial, you'll need to add the <<add-sample-data, Sample eCommerce or [float] === Create and personalize your workpad -Your first step to working with Canvas is to create a workpad. +Your first step to working with Canvas is to create a workpad. . Open *Canvas*. @@ -43,7 +43,7 @@ You'll notice that the image is tagged as an asset, which allows you to reuse th Customize your data by connecting it to the Sample eCommerce orders data. -. Click *Add element*, then click *Metric*. +. Click *Add element*, then click *Metric*. + By default, the *Metric* element is connected to a demo data source, which enables you to experiment with the element before you connect it to your own data source. @@ -89,7 +89,7 @@ image::images/canvas-metric-element.png[] To show what your data can do, add charts, graphs, progress monitors, and more to your workpad. -. Click *Add element*, then click *Area chart*. +. Click *Add element*, then click *Area chart*. . To connect the element to your own data source, make sure that the element is selected, then click *Data*. @@ -117,7 +117,7 @@ image::images/canvas-chart-element.png[] [float] === Show how your data changes over time -To focus your data on a specific time range, add a time filter to your workpad. +To focus your data on a specific time range, add a time filter to your workpad. . Click *Add element*, then click *Time filter*. @@ -132,26 +132,30 @@ image::images/canvas-timefilter-element.png[] To see how the data changes, set the time filter to *Last 7 days*. As you change the time filter options, the metrics dynamically update. -Your workpad is now complete! Use the icons in the upper left corner to: +Your workpad is now complete! From the workpad menu, use the icons to: -* Display your workpad in fullscreen mode +* Configure the refresh rate for your data -* Download your workpad as a PDF report or JSON object +* Refresh the data that displays on your workpad -* Configure the refresh rate for your data +* Display your workpad in fullscreen mode + +* Control the zoom options * Share your workpad +* Hide the editing controls + [float] === Next steps -Now that you know the Canvas basics, you're ready to explore on your own. +Now that you know the Canvas basics, you're ready to explore on your own. Here are some things to try: -* Play with the {kibana-ref}/add-sample-data.html[sample Canvas workpads]. +* Play with the {kibana-ref}/add-sample-data.html[sample Canvas workpads]. -* Learn more about <<create-canvas-workpad,Workpads>>. +* Build presentations of your own live data with <<create-canvas-workpad,workpads>>. -* Learn more about <<element-intro,Elements>>. +* Learn more about <<add-canvas-elements,elements>> — the building blocks of your workpad. * Deep dive into the {kibana-ref}/canvas-function-reference.html[expression language and functions] that drive Canvas. diff --git a/docs/canvas/canvas-workpad.asciidoc b/docs/canvas/canvas-workpad.asciidoc index f833bd903b0bc..c5c163441439c 100644 --- a/docs/canvas/canvas-workpad.asciidoc +++ b/docs/canvas/canvas-workpad.asciidoc @@ -4,19 +4,19 @@ A Canvas _workpad_ provides you with a workspace where you can build presentations of your live data. -To create a workpad, you can: +To create a workpad, choose one of the following options: * <<blank-canvas-workpad,Build fully customizable presentations of your own data>> * <<canvas-template-workpad,Choose from a set of preconfigured workpad templates>> -* <<import-canvas-workpad,Import a workpad that someone else has already started>> - * <<sample-data-workpad,Gather inspiration from the {kib} sample data workpads>> +* <<import-canvas-workpad,Import a workpad that someone else has already started>> + [float] [[blank-canvas-workpad]] -=== Start with a blank page +=== Start with a blank workpad To use the background colors, images, and data of your choice, start with a blank workpad. @@ -69,21 +69,21 @@ Each of the sample data sets comes with a Canvas workpad that you can use for yo . Add a {kibana-ref}/add-sample-data.html[sample data set]. -. On the *Add Data to Kibana* page, click the *View data* dropdown list, then select *Canvas*. -+ -Need some more workpad inspiration? Check out the link:https://www.elastic.co/blog/[Elastic Blog]. +. On the *Add Data* page, click *View data*, then select *Canvas*. [float] [[apply-workpad-styles]] -== Apply a set of styles to the entire workpad +=== Apply a set of styles to the entire workpad -To make your workpad look exactly the way you want, use the editor on the right to apply CSS overrides. +To make your workpad look exactly the way you want, use the editor to apply CSS overrides. . Expand *Global CSS overrides*. -. Enter the CSS. For example, to change the background on every page, enter: +. Enter the CSS. ++ +For example, to change the background on every page, enter: + -[source,js] +[source,text] -------------------------------------------------- .canvasPage { background-color: #3990e6; @@ -91,3 +91,46 @@ background-color: #3990e6; -------------------------------------------------- . Click *Apply stylesheet*. + +[float] +[[configure-auto-refresh-interval]] +=== Change the auto-refresh interval + +Increase or decrease how often the data refreshes on your workpad. + +. In the top left corner, click the *Control settings* icon. + +. Under *Change auto-refresh interval*, select the interval you want to use. ++ +[role="screenshot"] +image::images/canvas-refresh-interval.png[Element data refresh interval] + +TIP: To manually refresh the data, click the *Refresh data* icon. + +[float] +[[zoom-in-out]] +=== Use the zoom options + +In the upper left corner, click the *Zoom controls* icon, then select one of the options. + +[role="screenshot"] +image::images/canvas-zoom-controls.png[Zoom controls] + +[float] +[[add-more-pages]] +=== Add pages + +Organize your ideas onto separate pages by adding more pages. + +. Click *Page 1*, then click *+*. + +. On the *Page* editor panel on the right, select the page transition from the *Transition* dropdown. ++ +[role="screenshot"] +image::images/canvas-add-pages.gif[Add pages] + +include::{kib-repo-dir}/canvas/canvas-elements.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-present-workpad.asciidoc[] + +include::{kib-repo-dir}/canvas/canvas-share-workpad.asciidoc[] diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.getstartservices.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.getstartservices.md index e4fec4eae31b1..8664ad0e2a0e5 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.getstartservices.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.getstartservices.md @@ -9,5 +9,5 @@ <b>Signature:</b> ```typescript -getStartServices: StartServicesAccessor<TPluginsStart>; +getStartServices: StartServicesAccessor<TPluginsStart, TStart>; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index c039bc19348cc..870fa33dce900 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -9,7 +9,7 @@ Core services exposed to the `Plugin` setup lifecycle <b>Signature:</b> ```typescript -export interface CoreSetup<TPluginsStart extends object = object> +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> ``` ## Properties @@ -19,7 +19,7 @@ export interface CoreSetup<TPluginsStart extends object = object> | [application](./kibana-plugin-core-public.coresetup.application.md) | <code>ApplicationSetup</code> | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) | | [context](./kibana-plugin-core-public.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-core-public.contextsetup.md) | | [fatalErrors](./kibana-plugin-core-public.coresetup.fatalerrors.md) | <code>FatalErrorsSetup</code> | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | -| [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | <code>StartServicesAccessor<TPluginsStart></code> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) | +| [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | <code>StartServicesAccessor<TPluginsStart, TStart></code> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) | | [http](./kibana-plugin-core-public.coresetup.http.md) | <code>HttpSetup</code> | [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | [injectedMetadata](./kibana-plugin-core-public.coresetup.injectedmetadata.md) | <code>{</code><br/><code> getInjectedVar: (name: string, defaultValue?: any) => unknown;</code><br/><code> }</code> | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. | | [notifications](./kibana-plugin-core-public.coresetup.notifications.md) | <code>NotificationsSetup</code> | [NotificationsSetup](./kibana-plugin-core-public.notificationssetup.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.httpsetup.basepath.md b/docs/development/core/public/kibana-plugin-core-public.httpsetup.basepath.md index 90af143af3539..15206a7ae5e1d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.httpsetup.basepath.md +++ b/docs/development/core/public/kibana-plugin-core-public.httpsetup.basepath.md @@ -4,7 +4,7 @@ ## HttpSetup.basePath property -APIs for manipulating the basePath on URL segments. +APIs for manipulating the basePath on URL segments. See [IBasePath](./kibana-plugin-core-public.ibasepath.md) <b>Signature:</b> diff --git a/docs/development/core/public/kibana-plugin-core-public.httpsetup.md b/docs/development/core/public/kibana-plugin-core-public.httpsetup.md index b7375b724549f..bb43e9f588a72 100644 --- a/docs/development/core/public/kibana-plugin-core-public.httpsetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.httpsetup.md @@ -16,7 +16,7 @@ export interface HttpSetup | Property | Type | Description | | --- | --- | --- | | [anonymousPaths](./kibana-plugin-core-public.httpsetup.anonymouspaths.md) | <code>IAnonymousPaths</code> | APIs for denoting certain paths for not requiring authentication | -| [basePath](./kibana-plugin-core-public.httpsetup.basepath.md) | <code>IBasePath</code> | APIs for manipulating the basePath on URL segments. | +| [basePath](./kibana-plugin-core-public.httpsetup.basepath.md) | <code>IBasePath</code> | APIs for manipulating the basePath on URL segments. See [IBasePath](./kibana-plugin-core-public.ibasepath.md) | | [delete](./kibana-plugin-core-public.httpsetup.delete.md) | <code>HttpHandler</code> | Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-core-public.httphandler.md) for options. | | [fetch](./kibana-plugin-core-public.httpsetup.fetch.md) | <code>HttpHandler</code> | Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-core-public.httphandler.md) for options. | | [get](./kibana-plugin-core-public.httpsetup.get.md) | <code>HttpHandler</code> | Makes an HTTP request with the GET method. See [HttpHandler](./kibana-plugin-core-public.httphandler.md) for options. | diff --git a/docs/development/core/public/kibana-plugin-core-public.legacycoresetup.md b/docs/development/core/public/kibana-plugin-core-public.legacycoresetup.md index 25387ff5ec8c0..26220accbfaf3 100644 --- a/docs/development/core/public/kibana-plugin-core-public.legacycoresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.legacycoresetup.md @@ -13,7 +13,7 @@ Setup interface exposed to the legacy platform via the `ui/new_platform` module. <b>Signature:</b> ```typescript -export interface LegacyCoreSetup extends CoreSetup<any> +export interface LegacyCoreSetup extends CoreSetup<any, any> ``` ## Remarks diff --git a/docs/development/core/public/kibana-plugin-core-public.plugin.setup.md b/docs/development/core/public/kibana-plugin-core-public.plugin.setup.md index 7ed0e056b390f..7fa05588a3301 100644 --- a/docs/development/core/public/kibana-plugin-core-public.plugin.setup.md +++ b/docs/development/core/public/kibana-plugin-core-public.plugin.setup.md @@ -7,14 +7,14 @@ <b>Signature:</b> ```typescript -setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; +setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| core | <code>CoreSetup<TPluginsStart></code> | | +| core | <code>CoreSetup<TPluginsStart, TStart></code> | | | plugins | <code>TPluginsSetup</code> | | <b>Returns:</b> diff --git a/docs/development/core/public/kibana-plugin-core-public.startservicesaccessor.md b/docs/development/core/public/kibana-plugin-core-public.startservicesaccessor.md index 02e896a6b47e5..ad53307d53d69 100644 --- a/docs/development/core/public/kibana-plugin-core-public.startservicesaccessor.md +++ b/docs/development/core/public/kibana-plugin-core-public.startservicesaccessor.md @@ -9,5 +9,5 @@ Allows plugins to get access to APIs available in start inside async handlers, s <b>Signature:</b> ```typescript -export declare type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>; +export declare type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.coresetup.getstartservices.md b/docs/development/core/server/kibana-plugin-core-server.coresetup.getstartservices.md index ea8e610ee56de..1f326449156f0 100644 --- a/docs/development/core/server/kibana-plugin-core-server.coresetup.getstartservices.md +++ b/docs/development/core/server/kibana-plugin-core-server.coresetup.getstartservices.md @@ -9,5 +9,5 @@ <b>Signature:</b> ```typescript -getStartServices: StartServicesAccessor<TPluginsStart>; +getStartServices: StartServicesAccessor<TPluginsStart, TStart>; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.coresetup.md b/docs/development/core/server/kibana-plugin-core-server.coresetup.md index b0eba8ac78063..29fdc37a81176 100644 --- a/docs/development/core/server/kibana-plugin-core-server.coresetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.coresetup.md @@ -9,7 +9,7 @@ Context passed to the plugins `setup` method. <b>Signature:</b> ```typescript -export interface CoreSetup<TPluginsStart extends object = object> +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> ``` ## Properties @@ -19,7 +19,7 @@ export interface CoreSetup<TPluginsStart extends object = object> | [capabilities](./kibana-plugin-core-server.coresetup.capabilities.md) | <code>CapabilitiesSetup</code> | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | | [context](./kibana-plugin-core-server.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | | [elasticsearch](./kibana-plugin-core-server.coresetup.elasticsearch.md) | <code>ElasticsearchServiceSetup</code> | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | -| [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | <code>StartServicesAccessor<TPluginsStart></code> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) | +| [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | <code>StartServicesAccessor<TPluginsStart, TStart></code> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) | | [http](./kibana-plugin-core-server.coresetup.http.md) | <code>HttpServiceSetup</code> | [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) | | [metrics](./kibana-plugin-core-server.coresetup.metrics.md) | <code>MetricsServiceSetup</code> | [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) | | [savedObjects](./kibana-plugin-core-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) | diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index a1158dc853918..793684c1b3796 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -115,8 +115,6 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- --> | [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | | [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | | [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | -| [PluginsServiceSetup](./kibana-plugin-core-server.pluginsservicesetup.md) | | -| [PluginsServiceStart](./kibana-plugin-core-server.pluginsservicestart.md) | | | [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.<!-- -->Provides the following clients and services: - [rendering](./kibana-plugin-core-server.iscopedrenderingclient.md) - Rendering client which uses the data of the incoming request - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.dataClient](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [elasticsearch.adminClient](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch admin client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | | [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. | | [RouteConfigOptions](./kibana-plugin-core-server.routeconfigoptions.md) | Additional route options. | diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.contracts.md b/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.contracts.md deleted file mode 100644 index 5e0543dbaa2d4..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.contracts.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginsServiceSetup](./kibana-plugin-core-server.pluginsservicesetup.md) > [contracts](./kibana-plugin-core-server.pluginsservicesetup.contracts.md) - -## PluginsServiceSetup.contracts property - -<b>Signature:</b> - -```typescript -contracts: Map<PluginName, unknown>; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.md deleted file mode 100644 index 5bfa65f36bda3..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.md +++ /dev/null @@ -1,20 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginsServiceSetup](./kibana-plugin-core-server.pluginsservicesetup.md) - -## PluginsServiceSetup interface - - -<b>Signature:</b> - -```typescript -export interface PluginsServiceSetup -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [contracts](./kibana-plugin-core-server.pluginsservicesetup.contracts.md) | <code>Map<PluginName, unknown></code> | | -| [uiPlugins](./kibana-plugin-core-server.pluginsservicesetup.uiplugins.md) | <code>{</code><br/><code> internal: Map<PluginName, InternalPluginInfo>;</code><br/><code> public: Map<PluginName, DiscoveredPlugin>;</code><br/><code> browserConfigs: Map<PluginName, Observable<unknown>>;</code><br/><code> }</code> | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.uiplugins.md b/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.uiplugins.md deleted file mode 100644 index 7168a360c244d..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.pluginsservicesetup.uiplugins.md +++ /dev/null @@ -1,15 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginsServiceSetup](./kibana-plugin-core-server.pluginsservicesetup.md) > [uiPlugins](./kibana-plugin-core-server.pluginsservicesetup.uiplugins.md) - -## PluginsServiceSetup.uiPlugins property - -<b>Signature:</b> - -```typescript -uiPlugins: { - internal: Map<PluginName, InternalPluginInfo>; - public: Map<PluginName, DiscoveredPlugin>; - browserConfigs: Map<PluginName, Observable<unknown>>; - }; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.contracts.md b/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.contracts.md deleted file mode 100644 index 5c680d9d2d504..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.contracts.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginsServiceStart](./kibana-plugin-core-server.pluginsservicestart.md) > [contracts](./kibana-plugin-core-server.pluginsservicestart.contracts.md) - -## PluginsServiceStart.contracts property - -<b>Signature:</b> - -```typescript -contracts: Map<PluginName, unknown>; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.md b/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.md deleted file mode 100644 index cb450ded47c5b..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.pluginsservicestart.md +++ /dev/null @@ -1,19 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PluginsServiceStart](./kibana-plugin-core-server.pluginsservicestart.md) - -## PluginsServiceStart interface - - -<b>Signature:</b> - -```typescript -export interface PluginsServiceStart -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [contracts](./kibana-plugin-core-server.pluginsservicestart.contracts.md) | <code>Map<PluginName, unknown></code> | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.startservicesaccessor.md b/docs/development/core/server/kibana-plugin-core-server.startservicesaccessor.md index 4de781fc99cc1..7f90060d3ffa8 100644 --- a/docs/development/core/server/kibana-plugin-core-server.startservicesaccessor.md +++ b/docs/development/core/server/kibana-plugin-core-server.startservicesaccessor.md @@ -9,5 +9,5 @@ Allows plugins to get access to APIs available in start inside async handlers. P <b>Signature:</b> ```typescript -export declare type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>; +export declare type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search.md index 7e65ef85c8bec..afb6ea88f9fad 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.search.md @@ -10,7 +10,7 @@ search: { aggs: { AggConfigs: typeof AggConfigs; - aggGroupNamesMap: () => Record<"buckets" | "metrics", string>; + aggGroupNamesMap: () => Record<"metrics" | "buckets", string>; aggTypeFilters: import("./search/aggs/filter/agg_type_filters").AggTypeFilters; CidrMask: typeof CidrMask; convertDateRangeToString: typeof convertDateRangeToString; diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index e756eb9b72905..259d725b3bf0d 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -23,6 +23,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getTotalLoaded({ total, failed, successful })](./kibana-plugin-plugins-data-server.gettotalloaded.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | diff --git a/docs/images/canvas-add-image.gif b/docs/images/canvas-add-image.gif new file mode 100644 index 0000000000000..a2263e22c4c49 Binary files /dev/null and b/docs/images/canvas-add-image.gif differ diff --git a/docs/images/canvas-map-embed.gif b/docs/images/canvas-map-embed.gif index eadf521c3b4d1..59ef97e0ceae8 100644 Binary files a/docs/images/canvas-map-embed.gif and b/docs/images/canvas-map-embed.gif differ diff --git a/docs/images/canvas-refresh-interval.png b/docs/images/canvas-refresh-interval.png index f1c840f503ec4..99006a5b8f12d 100644 Binary files a/docs/images/canvas-refresh-interval.png and b/docs/images/canvas-refresh-interval.png differ diff --git a/docs/images/canvas-zoom-controls.png b/docs/images/canvas-zoom-controls.png index a7d2820a58925..892721b627027 100644 Binary files a/docs/images/canvas-zoom-controls.png and b/docs/images/canvas-zoom-controls.png differ diff --git a/docs/images/canvas_create_image.png b/docs/images/canvas_create_image.png new file mode 100644 index 0000000000000..7b7c38102e4c9 Binary files /dev/null and b/docs/images/canvas_create_image.png differ diff --git a/docs/images/canvas_element_options.png b/docs/images/canvas_element_options.png new file mode 100644 index 0000000000000..191348d919b50 Binary files /dev/null and b/docs/images/canvas_element_options.png differ diff --git a/docs/images/canvas_save_element.png b/docs/images/canvas_save_element.png new file mode 100644 index 0000000000000..a63f5135f2a0e Binary files /dev/null and b/docs/images/canvas_save_element.png differ diff --git a/docs/management/alerting/alert-details.asciidoc b/docs/management/alerting/alert-details.asciidoc new file mode 100644 index 0000000000000..b108f79fe5bad --- /dev/null +++ b/docs/management/alerting/alert-details.asciidoc @@ -0,0 +1,34 @@ +[role="xpack"] +[[alert-details]] +=== Alert details + +beta[] + +The *Alert details* page tells you about the state of the alert and provides granular control over the actions it is taking. + +[role="screenshot"] +image::images/alerts-details-instances-active.png[Alert details page with three alert instances] + +In this example, alerts detect when a site serves more than a threshold number of bytes in a 24 hour period. Three sites are above the threshold. These are called alert instances - occurrences of the condition being detected - and the instance name, status, time of detection, and duration of the condition are shown in this view. + +Upon detection, each instance can trigger one or more actions. If the condition persists, the same actions will trigger either on the next scheduled alert check, or (if defined) after the re-notify period on the alert has passed. To prevent re-notification, you can suppress future actions by clicking on the eye icon to mute an individual alert instance. Muting means that the alert checks continue to run on a schedule, but that instance will not trigger any action. + +[role="screenshot"] +image::images/alerts-details-instance-muting.png[Muting an alert instance] + +Alert instances will come and go from the list depending on whether they meet the alert conditions or not - unless they are muted. If a muted instance no longer meets the alert conditions, it will appear as inactive in the list. This prevents an instance from triggering actions if it reappears in the future. + +[role="screenshot"] +image::images/alerts-details-instances-inactive.png[Alert details page with three inactive alert instances] + +If you want to suppress actions on all current and future instances, you can mute the entire alert. Alert checks continue to run and the instance list will update as instances activate or deactivate, but no actions will be triggered. + +[role="screenshot"] +image::images/alerts-details-muting.png[Use the mute toggle to suppress all action on current and future instances] + +You can also disable an alert altogether. When disabled, the alert stops running checks altogether and will clear any instances it is tracking. You may want to disable alerts that are not currently needed to reduce the load on {kib} and {es}. + +[role="screenshot"] +image::images/alerts-details-disabling.png[Use the disable toggle to turn off alert checks and clear instances tracked] + +* For further information on alerting concepts and examples, see <<alerting-getting-started>>. diff --git a/docs/management/alerting/alert-management.asciidoc b/docs/management/alerting/alert-management.asciidoc new file mode 100644 index 0000000000000..caf260937b7be --- /dev/null +++ b/docs/management/alerting/alert-management.asciidoc @@ -0,0 +1,59 @@ +[role="xpack"] +[[alert-management]] +=== Managing Alerts + +beta[] + +The *Alerts* tab provides a cross-app view of alerting. Different {kib} apps like <<xpack-infra, Metrics>>, <<xpack-apm, APM>>, <<xpack-uptime, Uptime>>, and <<xpack-siem, SIEM>> can offer their own alerts, and the *Alerts* tab provides a central place to: + +* <<create-edit-alerts, Create and edit>> alerts +* <<controlling-alerts, Control alerts>> including enabling/disabling, muting/unmuting, and deleting +* Drill-down to <<alert-details, alert details>> + +[role="screenshot"] +image:management/alerting/images/alerts-and-actions-ui.png[Example alert listing in the Alerts and Actions UI] + +For more information on alerting concepts and the types of alerts and actions available, see <<alerting-getting-started>>. + +[float] +==== Finding alerts + +The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type. + +The *search bar* can be used to quickly find alerts by name or tag. + +[role="screenshot"] +image::images/alerts-filter-by-search.png[Filtering the alerts list using the search bar] + +The *type* dropdown lets you filter to a subset of alert types. + +[role="screenshot"] +image::images/alerts-filter-by-type.png[Filtering the alerts list by types of alert] + +The *Action type* dropdown lets you filter by the type of action used in the alert. + +[role="screenshot"] +image::images/alerts-filter-by-action-type.png[Filtering the alert list by type of action] + +[float] +[[create-edit-alerts]] +==== Creating and editing alerts + +Many alerts must be created within the context of a {kib} app like <<xpack-infra, Metrics>>, <<xpack-apm, APM>>, or <<xpack-uptime, Uptime>>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <<alert-types>> for details on what types of alerts are available and how to configure them. + +After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing. + + +[float] +[[controlling-alerts]] +==== Controlling alerts + +The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button at the right of each row. + +[role="screenshot"] +image:management/alerting/images/individual-mute-disable.png[The actions button allows an individual alert to be muted, disabled, or deleted] + +These operations can also be performed in bulk by multi-selecting alerts and clicking the *Manage alerts* button: + +[role="screenshot"] +image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk] \ No newline at end of file diff --git a/docs/management/alerting/alerts-and-actions-intro.asciidoc b/docs/management/alerting/alerts-and-actions-intro.asciidoc new file mode 100644 index 0000000000000..4674c9ba902be --- /dev/null +++ b/docs/management/alerting/alerts-and-actions-intro.asciidoc @@ -0,0 +1,25 @@ +[role="xpack"] +[[managing-alerts-and-actions]] +== Alerts and Actions + +beta[] + +The *Alerts and Actions* UI lets you <<alert-management, see and control all the alerts>> in a space, and provides tools to <<connector-management, create and manage connectors>> so that alerts can trigger actions like notification, indexing, and ticketing. + +To manage alerting and connectors, go to *Management > {kib} > Alerts and Actions*. + +[role="screenshot"] +image:management/alerting/images/alerts-and-actions-ui.png[Example alert listing in the Alerts and Actions UI] + +[NOTE] +============================================================================ +Similar to dashboards, alerts and connectors reside in a <<xpack-spaces, space>>. +The *Alerts and Actions* UI only shows alerts and connectors for the current space. +============================================================================ + +[NOTE] +============================================================================ +{es} also offers alerting capabilities through Watcher, which +can be managed through the <<watcher-ui, Watcher UI>>. See +<<alerting-concepts-differences>> for more information. +============================================================================ \ No newline at end of file diff --git a/docs/management/alerting/connector-management.asciidoc b/docs/management/alerting/connector-management.asciidoc new file mode 100644 index 0000000000000..1002a372f9460 --- /dev/null +++ b/docs/management/alerting/connector-management.asciidoc @@ -0,0 +1,47 @@ +[role="xpack"] +[[connector-management]] +=== Managing Connectors + +beta[] + +Alerts use *Connectors* to route actions to different destinations like log files, ticketing systems, and messaging tools. While each {kib} app can offer their own types of alerts, they typically share connectors. The *Connectors* tab offers a central place to view and manage all the connectors in the current space. + +For more information on connectors and the types of actions available see <<action-types>>. + +[role="screenshot"] +image::images/connector-listing.png[Example connector listing in the Alerts and Actions UI] + + +[float] +==== Connector list + +The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type. + +[role="screenshot"] +image::images/connector-filter-by-search.png[Filtering the connector list using the search bar] + + +The *type* dropdown also lets you filter to a subset of action types. + +[role="screenshot"] +image::images/connector-filter-by-type.png[Filtering the connector list by types of actions] + +The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified. + +[role="screenshot"] +image::images/connector-action-count.png[Filtering the connector list by types of actions] + +You can delete individual connectors using the trash icon on the right of each row. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box. + +[role="screenshot"] +image::images/connector-delete.png[Deleting connectors individually or in bulk] + +[NOTE] +============================================================================ +You can delete a connector even if there are still actions referencing it. +When this happens the action will fail to execute, and appear as errors in the {kib} logs. +============================================================================ + +==== Creating a new connector + +New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <<action-types>> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space. \ No newline at end of file diff --git a/docs/management/alerting/images/alerts-and-actions-ui.png b/docs/management/alerting/images/alerts-and-actions-ui.png new file mode 100644 index 0000000000000..acf3f3b1f0be9 Binary files /dev/null and b/docs/management/alerting/images/alerts-and-actions-ui.png differ diff --git a/docs/management/alerting/images/alerts-details-disabling.png b/docs/management/alerting/images/alerts-details-disabling.png new file mode 100644 index 0000000000000..7057afc8ad07d Binary files /dev/null and b/docs/management/alerting/images/alerts-details-disabling.png differ diff --git a/docs/management/alerting/images/alerts-details-instance-muting.png b/docs/management/alerting/images/alerts-details-instance-muting.png new file mode 100644 index 0000000000000..9d26fad419e4f Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instance-muting.png differ diff --git a/docs/management/alerting/images/alerts-details-instances-active.png b/docs/management/alerting/images/alerts-details-instances-active.png new file mode 100644 index 0000000000000..d6895bd4952b8 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instances-active.png differ diff --git a/docs/management/alerting/images/alerts-details-instances-inactive.png b/docs/management/alerting/images/alerts-details-instances-inactive.png new file mode 100644 index 0000000000000..b049b4ba082f6 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-instances-inactive.png differ diff --git a/docs/management/alerting/images/alerts-details-muting.png b/docs/management/alerting/images/alerts-details-muting.png new file mode 100644 index 0000000000000..9b47d82a74639 Binary files /dev/null and b/docs/management/alerting/images/alerts-details-muting.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-action-type.png b/docs/management/alerting/images/alerts-filter-by-action-type.png new file mode 100644 index 0000000000000..94336a20e1d6c Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-action-type.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-search.png b/docs/management/alerting/images/alerts-filter-by-search.png new file mode 100644 index 0000000000000..df4b6d7d9d9aa Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-search.png differ diff --git a/docs/management/alerting/images/alerts-filter-by-type.png b/docs/management/alerting/images/alerts-filter-by-type.png new file mode 100644 index 0000000000000..75ffb3ff69bab Binary files /dev/null and b/docs/management/alerting/images/alerts-filter-by-type.png differ diff --git a/docs/management/alerting/images/bulk-mute-disable.png b/docs/management/alerting/images/bulk-mute-disable.png new file mode 100644 index 0000000000000..04cdc3f03f34d Binary files /dev/null and b/docs/management/alerting/images/bulk-mute-disable.png differ diff --git a/docs/management/alerting/images/connector-action-count.png b/docs/management/alerting/images/connector-action-count.png new file mode 100644 index 0000000000000..b792ae2cc11c8 Binary files /dev/null and b/docs/management/alerting/images/connector-action-count.png differ diff --git a/docs/management/alerting/images/connector-delete.png b/docs/management/alerting/images/connector-delete.png new file mode 100644 index 0000000000000..ccb6bcea4bade Binary files /dev/null and b/docs/management/alerting/images/connector-delete.png differ diff --git a/docs/management/alerting/images/connector-filter-by-search.png b/docs/management/alerting/images/connector-filter-by-search.png new file mode 100644 index 0000000000000..1f052ea23a577 Binary files /dev/null and b/docs/management/alerting/images/connector-filter-by-search.png differ diff --git a/docs/management/alerting/images/connector-filter-by-type.png b/docs/management/alerting/images/connector-filter-by-type.png new file mode 100644 index 0000000000000..06c7d6f4dad47 Binary files /dev/null and b/docs/management/alerting/images/connector-filter-by-type.png differ diff --git a/docs/management/alerting/images/connector-listing.png b/docs/management/alerting/images/connector-listing.png new file mode 100644 index 0000000000000..43014ff88057f Binary files /dev/null and b/docs/management/alerting/images/connector-listing.png differ diff --git a/docs/management/alerting/images/individual-mute-disable.png b/docs/management/alerting/images/individual-mute-disable.png new file mode 100644 index 0000000000000..ca00240a4af61 Binary files /dev/null and b/docs/management/alerting/images/individual-mute-disable.png differ diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index e3b9e61667bdf..d7f1ec637d1df 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -27,7 +27,7 @@ If not set, {kib} will generate a random key on startup, but all alert and actio Although the key can be specified in clear text in `kibana.yml`, it's recommended to store this key securely in the <<secure-settings,{kib} Keystore>>. [float] -[[alert-settings]] +[[action-settings]] ==== Action settings `xpack.actions.whitelistedHosts`:: @@ -41,7 +41,7 @@ A list of action types that are enabled. It defaults to `[*]`, enabling all type Disabled action types will not appear as an option when creating new connectors, but existing connectors and actions of that type will remain in {kib} and will not function. [float] -[[action-settings]] +[[alert-settings]] ==== Alert settings You do not need to configure any additional settings to use alerting in {kib}. diff --git a/docs/user/alerting/action-types.asciidoc b/docs/user/alerting/action-types.asciidoc new file mode 100644 index 0000000000000..02c09736e1fa0 --- /dev/null +++ b/docs/user/alerting/action-types.asciidoc @@ -0,0 +1,182 @@ +[role="xpack"] +[[action-types]] +== Action and connector types + +{kib} provides the following types of actions: + +* <<email-action-type, Email>> +* <<index-action-type, Index>> +* <<pagerduty-action-type, PagerDuty>> +* <<server-log-action-type, ServerLog>> +* <<slack-action-type, Slack>> +* <<webhook-action-type, Webhook>> + +This section describes how to configure connectors and actions for each type. + +[NOTE] +============================================== +Some action types are paid commercial features, while others are free. +For a comparison of the Elastic license levels, +see https://www.elastic.co/subscriptions[the subscription page]. +============================================== + +[float] +[[email-action-type]] +=== Email + +The email action type uses the SMTP protocol to send mail message, using an integration of https://nodemailer.com/[Nodemailer]. Email message text is sent as both plain text and html text. + +[float] +[[email-connector-configuration]] +==== Connector configuration + +Email connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +Sender:: The from address for all emails sent with this connector, specified in `user@host-name` format. +Host:: Host name of the service provider. If you are using the <<action-settings, `xpack.actions.whitelistedHosts`>> setting, make sure this hostname is whitelisted. +Port:: The port to connect to on the service provider. +Secure:: If true the connection will use TLS when connecting to the service provider. See https://nodemailer.com/smtp/#tls-options[nodemailer TLS documentation] for more information. +Username:: username for 'login' type authentication. +Password:: password for 'login' type authentication. + +[float] +[[email-action-configuration]] +==== Action configuration + +Email actions have the following configuration properties: + +To, CC, BCC:: Each is a list of addresses. Addresses can be specified in `user@host-name` format, or in `name <user@host-name>` format. One of To, CC, or BCC must contain an entry. +Subject:: The subject line of the email. +Message:: The message text of the email. Markdown format is supported. + +[float] +[[index-action-type]] +=== Index + +The index action type will index a document into {es}. + +[float] +[[index-connector-configuration]] +==== Connector configuration + +Index connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +Index:: The {es} index to be written to. +Refresh:: Setting for the {ref}/docs-refresh.html[refresh] policy for the write request. +Execution time field:: This field will be automatically set to the time the alert condition was detected. + +[float] +[[index-action-configuration]] +==== Action configuration + +Index actions have the following properties: + +Document:: The document to index in json format. + +[float] +[[pagerduty-action-type]] +=== PagerDuty + +The PagerDuty action type uses the https://v2.developer.pagerduty.com/docs/events-api-v2[v2 Events API] to trigger, acknowledge, and resolve PagerDuty alerts. + +[float] +[[pagerduty-connector-configuration]] +==== Connector configuration + +PagerDuty connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +API URL:: An optional PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`. If you are using the <<action-settings, `xpack.actions.whitelistedHosts`>> setting, make sure the hostname is whitelisted. +Routing Key:: A 32 character PagerDuty Integration Key for an integration on a service or on a global ruleset. + +[float] +[[pagerduty-action-configuration]] +==== Action configuration + +PagerDuty actions have the following properties: + +Severity:: The perceived severity of on the affected system. This can be one of `Critical`, `Error`, `Warning` or `Info`(default). +Event action:: One of `Trigger` (default), `Resolve`, or `Acknowledge`. See https://v2.developer.pagerduty.com/docs/events-api-v2#event-action[event action] for more details. +Dedup Key:: All actions sharing this key will be associated with the same PagerDuty alert. This value is used to correlate trigger and resolution. This value is *optional*, and if unset defaults to `action:<action saved object id>`. The maximum length is *255* characters. See https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication[alert deduplication] for details. +Timestamp:: An *optional* https://v2.developer.pagerduty.com/v2/docs/types#datetime[ISO-8601 format date-time], indicating the time the event was detected or generated. +Component:: An *optional* value indicating the component of the source machine that is responsible for the event, for example `mysql` or `eth0`. +Group:: An *optional* value indicating the logical grouping of components of a service, for example `app-stack`. +Source:: An *optional* value indicating the affected system, preferably a hostname or fully qualified domain name. Defaults to the {kib} saved object id of the action. +Summary:: An *optional* text summary of the event, defaults to `No summary provided`. The maximum length is 1024 characters. +Class:: An *optional* value indicating the class/type of the event, for example `ping failure` or `cpu load`. + +For more details on these properties, see https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[PagerDuty v2 event parameters]. + +[float] +[[server-log-action-type]] +=== Server log + +This action type writes and entry to the {kib} server log. + +[float] +[[server-log-connector-configuration]] +==== Connector configuration + +Server log connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. + +[float] +[[server-log-action-configuration]] +==== Action configuration + +Server log actions have the following properties: + +Message:: The message to log. + +[float] +[[slack-action-type]] +=== Slack + +The Slack action type uses https://api.slack.com/incoming-webhooks[Slack Incoming Webhooks]. + +[float] +[[slack-connector-configuration]] +==== Connector configuration + +Slack connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +Webhook URL:: The URL of the incoming webhook. See https://api.slack.com/messaging/webhooks#getting_started[Slack Incoming Webhooks] for instructions on generating this URL. If you are using the <<action-settings, `xpack.actions.whitelistedHosts`>> setting, make sure the hostname is whitelisted. + +[float] +[[slack-action-configuration]] +==== Action configuration + +Slack actions have the following properties: + +Message:: The message text, converted to the `text` field in the Webhook JSON payload. Currently only the text field is supported. Markdown, images, and other advanced formatting are not yet supported. + +[float] +[[webhook-action-type]] +=== Webhook + +The Webhook action type uses https://github.com/axios/axios[axios] to send a POST or PUT request to a web service. + +[float] +[[webhook-connector-configuration]] +==== Connector configuration + +Webhook connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +URL:: The request URL. If you are using the <<action-settings, `xpack.actions.whitelistedHosts`>> setting, make sure the hostname is whitelisted. +Method:: HTTP request method, either `post`(default) or `put`. +Headers:: A set of key-value pairs sent as headers with the request +User:: An optional username. If set, HTTP basic authentication is used. Currently only basic authentication is supported. +Password:: An optional password. If set, HTTP basic authentication is used. Currently only basic authentication is supported. + +[float] +[[webhook-action-configuration]] +==== Action configuration + +Webhook actions have the following properties: + +Body:: A json payload sent to the request URL. \ No newline at end of file diff --git a/docs/user/alerting/alert-types.asciidoc b/docs/user/alerting/alert-types.asciidoc new file mode 100644 index 0000000000000..4a99c70f9d961 --- /dev/null +++ b/docs/user/alerting/alert-types.asciidoc @@ -0,0 +1,115 @@ +[role="xpack"] +[[alert-types]] +== Alert types + +{kib} supplies alerts types in two ways: some are built into {kib}, while domain-specific alert types are registered by {kib} apps such as <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, and <<xpack-uptime,*Uptime*>>. + +This section covers built-in alert types. For domain-specific alert types, refer to the documentation for that app. + +Currently {kib} provides one built-in alert type: the <<alert-type-index-threshold>> type. + +[float] +[[alert-type-index-threshold]] +=== Index threshold + +The index threshold alert type is designed to run an {es} query over indices, aggregating field values from documents, comparing them to threshold values, and scheduling actions to run when the thresholds are met. + +[float] +==== Creating the alert + +An index threshold alert can be created from the *Create* button in the <<alert-management, alert management UI>>. Fill in the <<defining-alerts-general-details, general alert details>>, then select *Index Threshold*. + +[role="screenshot"] +image::images/alert-types-index-threshold-select.png[Choosing an index threshold alert type] + +[float] +==== Defining the conditions + +The index threshold has 5 clauses that define the condition to detect. + +[role="screenshot"] +image::images/alert-types-index-threshold-conditions.png[Five clauses define the condition to detect] + +Index:: This clause requires an *index or index pattern* and a *time field* that will be used for the *time window*. +When:: This clause specifies how the value to be compared to the threshold is calculated. The value is calculated by aggregating a numeric field a the *time window*. The aggregation options are: `count`, `average`, `sum`, `min`, and `max`. When using `count` the document count is used, and an aggregation field is not necessary. +Over/Grouped Over:: This clause lets you configure whether the aggregation is applied over all documents, or should be split into groups using a grouping field. If grouping is used, an <<alerting-concepts-alert-instances, alert instance>> will be created for each group when it exceeds the threshold. To limit the number of instances on high cardinality fields, you must specify the number of groups to check against the threshold. Only the *top* groups are checked. +Threshold:: This clause defines a threshold value and a comparison operator (one of `is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The result of the aggregation is compared to this threshold. +Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be to a value higher than the *check every* value in the <<defining-alerts-general-details, general alert details>>, to avoid gaps in detection. + +If data is available and all clauses have been defined, a preview chart will render the threshold value and display a line chart showing the value for the last 30 intervals. This can provide an indication of recent values and their proximity to the threshold, and help you tune the clauses. + +[role="screenshot"] +image::images/alert-types-index-threshold-preview.png[Five clauses define the condition to detect] + +[float] +=== Example + +In this section, you will use the {kib} <<add-sample-data, weblog sample dataset>> to setup and tune the conditions on an index threshold alert. For this example, we want to detect when any of our top three sites have served more than 420,000 bytes over a 24 hour period. + +From the <<alert-management, alert management UI>>, create a new alert, and fill in the <<defining-alerts-general-details, general alert details>>. This alert will be checked every 4 hours, and will not execute actions more than once per day. Choose the index threshold alert type. + +[role="screenshot"] +image::images/alert-types-index-threshold-select.png[Choosing an index threshold alert type] + +Click on each clause to open a control that helps you set the value: + +[float] +==== Index clause +The index clause control will list and allow you to search for available indices. Choose *kibana_sample_data_logs* + +[role="screenshot"] +image::images/alert-types-index-threshold-example-index.png[Choosing an index] + +Once an index is selected, the list of time fields for that index will be available to select. Choose *@timestamp*. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-timefield.png[Choosing a time field] + +[float] +==== When clause + +We want to detect the number of bytes served during the time window, so we select `sum` as the aggregation, and `bytes` as the field to aggregate. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-aggregation.png[Choosing the aggregation] + +[float] +==== Over/Grouped over clause + +We want to alert on the three sites that have the most traffic, so we'll group the sum of bytes by the `host.keyword` field and take the top 3 values. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-grouping.png[Choosing the groups] + +[float] +==== Threshold clause + +We want to alert when any site exceeds 420,000 bytes over a 24 hour period, so we'll set the threshold to 420,000 and use the `is above` comparison. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-threshold.png[Setting the threshold] + +[float] +==== Time window clause + +Finally, set the time window to 24 hours to complete the alert configuration. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-window.png[Setting the time window] + +The preview chart will render showing the 24 hour sum of bytes at 4 hours intervals (the *check every* interval) for the past 120 hours (the last 30 intervals). + +[role="screenshot"] +image::images/alert-types-index-threshold-example-preview.png[Setting the time window] + +[float] +==== Comparing time windows + +You can interactively change the time window and observe the effect it has on the chart. Compare a 24 window to a 12 hour window. Notice the variability in the sum of bytes, due to different traffic levels during the day compared to at night. This variability would result in noisy alerts, so the 24 hour window is better. The preview chart can help you find the right values for your alert. + +[role="screenshot"] +image::images/alert-types-index-threshold-example-comparison.png[Comparing two time windows] + + + + diff --git a/docs/user/alerting/alerting-scale-performance.asciidoc b/docs/user/alerting/alerting-scale-performance.asciidoc new file mode 100644 index 0000000000000..644a7143f8278 --- /dev/null +++ b/docs/user/alerting/alerting-scale-performance.asciidoc @@ -0,0 +1,28 @@ +[role="xpack"] +[[alerting-scale-performance]] +== Scale and performance + +{kib} alerting run both alert checks and actions as persistent background tasks. This has two major benefits: + +* *Persistence*: all task state and scheduling is stored in {es}, so if {kib} is restarted, alerts and actions will pick up where they left off. +* *Scaling*: multiple {kib} instances can read from and update the same task queue in {es}, allowing the alerting and action load to be distributed across instances. In cases where a {kib} instance no longer has capacity to run alert checks or actions, capacity can be increased by adding additional {kib} instances. + +[float] +=== Running background alert checks and actions + +{kib} background tasks are managed by: + +* Polling an {es} task index for overdue tasks at 3 second intervals. +* Tasks are then claiming them by updating them in the {es} index, using optimistic concurrency control to prevent conflicts. Each {kib} instance can run a maximum of 10 concurrent tasks, so a maximum of 10 tasks are claimed each interval. +* Tasks are run on the {kib} server. +* In the case of alerts which are recurring background checks, upon completion the task is scheduled again according to the <<defining-alerts-general-details, check interval>>. + +[IMPORTANT] +============================================== +Because tasks are polled at 3 second intervals and only 10 tasks can run concurrently per {kib} instance, it is possible for alert and action tasks to be run late. This can happen if: + +* Alerts use a small *check interval*. The lowest interval possible is 3 seconds, though intervals of 30 seconds or higher are recommended. +* Many alerts or actions must be *run at once*. In this case pending tasks will queue in {es}, and be pulled 10 at a time from the queue at 3 second intervals. +* *Long running tasks* occupy slots for an extended time, leaving fewer slots for other tasks. + +============================================== \ No newline at end of file diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc new file mode 100644 index 0000000000000..89c4c88708d58 --- /dev/null +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -0,0 +1,80 @@ +[role="xpack"] +[[defining-alerts]] +== Defining alerts + +{kib} alerts can be created in a variety of apps including <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, <<xpack-siem,*SIEM*>>, <<xpack-uptime,*Uptime*>> and from <<management,*Management*>> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. + +[float] +=== Alert flyout + +When an alert is created in an app, the app will display a flyout panel with three main sections to configure: + +. <<defining-alerts-general-details, General alert details>> +. <<defining-alerts-type-conditions, Alert type and conditions>> +. <<defining-alerts-actions-details, Action type and action details>> + +image::images/alert-flyout-sections.png[The three sections of an alert definition] + +[float] +[[defining-alerts-general-details]] +=== General alert details + +All alert share the following four properties in common: + +[role="screenshot"] +image::images/alert-flyout-general-details.png[All alerts have name, tags, check every, and re-notify every properties in common] + +Name:: The name of the alert. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable alert listing in the management UI. A distinctive name can help identify and find an alert. +Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag. +Check every:: This value determines how frequently the alert conditions below are checked. Note that the timing of background alert checks are not guaranteed, particularly for intervals of less than 10 seconds. See <<alerting-scale-performance>> for more information. +Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <<alerting-concepts-suppressing-duplicate-notifications>> for more information. + +[float] +[[defining-alerts-type-conditions]] +=== Alert type and conditions + +Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you. + +[role="screenshot"] +image::images/alert-flyout-alert-type-selection.png[Choosing the type of alert to create] + +Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field. + +[role="screenshot"] +image::images/alert-flyout-alert-conditions.png[UI for defining alert conditions on an index threshold alert] + +[float] +[[defining-alerts-actions-details]] +=== Action type and action details + +To add an action to an alert, you first select the type of action: + +[role="screenshot"] +image::images/alert-flyout-action-type-selection.png[UI for selecting an action type] + +Each action must specify a <<alerting-concepts-connectors, connector>> instance. If no connectors exist for that action type, click "Add new" to create one. + +Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <<action-types>> for details on the types of actions provided by {kib} and their properties. + +[role="screenshot"] +image::images/alert-flyout-action-details.png[UI for defining an email action] + +Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button at the right of the text box. + +[role="screenshot"] +image::images/alert-flyout-action-variables.png[Passing alert values to an action] + +You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again. + +[role="screenshot"] +image::images/alert-flyout-add-action.png[You can add multiple actions on an alert] + +[NOTE] +============================================== +Actions are not required on alerts. In some cases you may want to run an alert without actions first to understand its behavior, and configure actions later. +============================================== + +[float] +=== Managing alerts + +To modify an alert after it was created, including muting or disabling it, use the <<alert-management, alert listing in the Management UI>>. \ No newline at end of file diff --git a/docs/user/alerting/images/alert-concepts-connectors.svg b/docs/user/alerting/images/alert-concepts-connectors.svg new file mode 100644 index 0000000000000..9ae4c21ee5870 --- /dev/null +++ b/docs/user/alerting/images/alert-concepts-connectors.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 756.2965879265092 405.96587926509187" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l756.2966 0l0 405.96588l-756.2966 0l0 -405.96588z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l756.2966 0l0 405.96588l-756.2966 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m13.120735 28.889763l164.37796 0l0 217.51181l-164.37796 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m13.120735 28.889763l164.37796 0l0 217.51181l-164.37796 0z" fill-rule="evenodd"/><path fill="#000000" d="m22.089485 55.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm12.507233 1.46875l-1.640625 0l0 -10.453125q-0.59375 0.5625 -1.5625 1.140625q-0.953125 0.5625 -1.71875 0.84375l0 -1.59375q1.375 -0.640625 2.40625 -1.5625q1.03125 -0.921875 1.453125 -1.78125l1.0625 0l0 13.40625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m17.565195 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m17.565195 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m35.174572 87.471115l1.390625 0.34375q-0.4375 1.703125 -1.578125 2.609375q-1.125 0.890625 -2.765625 0.890625q-1.6875019 0 -2.750002 -0.6875q-1.0625 -0.6875 -1.625 -2.0q-0.546875 -1.3125 -0.546875 -2.8125q0 -1.640625 0.625 -2.859375q0.625 -1.21875 1.78125 -1.84375q1.15625 -0.640625 2.546877 -0.640625q1.5625 0 2.640625 0.8125q1.078125 0.796875 1.5 2.25l-1.375 0.3125q-0.359375 -1.140625 -1.0625 -1.65625q-0.6875 -0.53125 -1.734375 -0.53125q-1.2187519 0 -2.031252 0.578125q-0.8125 0.578125 -1.140625 1.5625q-0.328125 0.96875 -0.328125 2.015625q0 1.328125 0.390625 2.328125q0.390625 1.0 1.21875 1.5q0.828125 0.484375 1.7812519 0.484375q1.171875 0 1.96875 -0.671875q0.8125 -0.671875 1.09375 -1.984375zm2.4592743 -0.125q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307358 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072983 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.291733 -5.21875l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686455 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594757 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717743 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307358 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m17.565195 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m17.565195 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m27.221445 123.56732l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.7968769 0 1.4062519 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.8750019 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.1718769 0 2.062502 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125019 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.7031269 0.375 2.328127 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015627 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.041231 0.59375l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm2.375 2.78125l0 -10.484375l1.28125 0l0 3.75q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354233 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104229 4.53125l0 -0.953125q-0.71875 1.125 -2.1249962 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6874962 0 1.2187462 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.062496 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.8437462 0 1.4374962 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.4843712 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.276104 3.796875l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm3.1354828 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.490524 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m17.565195 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m17.565195 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m26.54957 164.13766l4.015625 -10.484375l1.5000019 0l4.296875 10.484375l-1.578125 0l-1.234375 -3.171875l-4.375002 0l-1.15625 3.171875l-1.46875 0zm3.015625 -4.3125l3.562502 0l-1.09375 -2.90625q-0.5000019 -1.3125 -0.7500019 -2.171875q-0.203125 1.015625 -0.5625 2.0l-1.15625 3.078125zm12.697481 1.53125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594757 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717743 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307358 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6874962 0 1.2656212 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.3749962 -0.234375 -0.8906212 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm7.635479 -2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m30.065617 172.23885l125.79527 0l0 56.850388l-125.79527 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m30.065617 172.23885l125.79527 0l0 56.850388l-125.79527 0z" fill-rule="evenodd"/><path fill="#000000" d="m42.17499 191.60684l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.0937538 0.125q-0.25 0.953125 -0.9531288 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.7968788 0.84375 0.7968788 2.390625q0 0.09375 0 0.28125l-4.640629 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158207 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m113.39179 189.49747l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199211 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.0937424 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.3593674 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.0937424 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.7968674 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.9218674 0.078125 -1.3124924 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.5312424 0 1.0156174 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m46.128117 205.59122l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.9843788 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.6718788 0 -1.1718788 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923832 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m108.15742 208.60684l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339767 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.6562424 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.1562424 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.26561737 0.828125 -0.26561737 1.578125q0 0.796875 0.34374237 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m40.159367 221.60684l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m259.5328 278.57742l245.03937 0l0 113.5748l-245.03937 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m259.5328 278.57742l245.03937 0l0 113.5748l-245.03937 0z" fill-rule="evenodd"/><path fill="#000000" d="m270.11093 306.77744l0 -14.3125l10.359375 0l0 1.6875l-8.453125 0l0 4.375l7.90625 0l0 1.6875l-7.90625 0l0 4.875l8.78125 0l0 1.6875l-10.6875 0zm13.074219 0l0 -10.375l1.578125 0l0 1.453125q0.484375 -0.75 1.296875 -1.21875q0.8125 -0.46875 1.84375 -0.46875q1.15625 0 1.890625 0.484375q0.734375 0.46875 1.046875 1.328125q1.234375 -1.8125 3.203125 -1.8125q1.546875 0 2.375 0.859375q0.828125 0.859375 0.828125 2.625l0 7.125l-1.75 0l0 -6.53125q0 -1.0625 -0.171875 -1.515625q-0.171875 -0.46875 -0.625 -0.75q-0.4375 -0.28125 -1.046875 -0.28125q-1.09375 0 -1.828125 0.734375q-0.71875 0.71875 -0.71875 2.3125l0 6.03125l-1.75 0l0 -6.734375q0 -1.171875 -0.4375 -1.75q-0.421875 -0.59375 -1.40625 -0.59375q-0.734375 0 -1.375 0.390625q-0.625 0.390625 -0.90625 1.140625q-0.28125 0.75 -0.28125 2.171875l0 5.375l-1.765625 0zm23.441406 -1.28125q-0.984375 0.828125 -1.890625 1.171875q-0.90625 0.34375 -1.9375 0.34375q-1.703125 0 -2.625 -0.828125q-0.921875 -0.84375 -0.921875 -2.140625q0 -0.765625 0.34375 -1.390625q0.359375 -0.625 0.921875 -1.0q0.5625 -0.390625 1.265625 -0.59375q0.515625 -0.125 1.5625 -0.265625q2.125 -0.25 3.125 -0.59375q0.015625 -0.359375 0.015625 -0.46875q0 -1.0625 -0.5 -1.515625q-0.671875 -0.59375 -2.0 -0.59375q-1.25 0 -1.84375 0.4375q-0.578125 0.4375 -0.859375 1.546875l-1.71875 -0.234375q0.234375 -1.109375 0.765625 -1.78125q0.53125 -0.6875 1.546875 -1.046875q1.015625 -0.375 2.359375 -0.375q1.328125 0 2.15625 0.3125q0.828125 0.3125 1.21875 0.796875q0.390625 0.46875 0.546875 1.1875q0.09375 0.453125 0.09375 1.625l0 2.34375q0 2.453125 0.109375 3.109375q0.109375 0.640625 0.453125 1.234375l-1.84375 0q-0.265625 -0.546875 -0.34375 -1.28125zm-0.15625 -3.921875q-0.953125 0.390625 -2.875 0.65625q-1.078125 0.15625 -1.53125 0.359375q-0.4375 0.1875 -0.6875 0.5625q-0.25 0.375 -0.25 0.84375q0 0.703125 0.53125 1.171875q0.53125 0.46875 1.5625 0.46875q1.015625 0 1.796875 -0.4375q0.796875 -0.453125 1.171875 -1.21875q0.28125 -0.609375 0.28125 -1.765625l0 -0.640625zm4.513672 -7.09375l0 -2.015625l1.765625 0l0 2.015625l-1.765625 0zm0 12.296875l0 -10.375l1.765625 0l0 10.375l-1.765625 0zm4.3964844 0l0 -14.3125l1.75 0l0 14.3125l-1.75 0zm16.8125 -3.796875l1.71875 0.21875q-0.28125 1.796875 -1.453125 2.8125q-1.15625 1.0 -2.859375 1.0q-2.125 0 -3.421875 -1.390625q-1.296875 -1.390625 -1.296875 -3.984375q0 -1.6875 0.546875 -2.9375q0.5625 -1.265625 1.703125 -1.890625q1.140625 -0.640625 2.484375 -0.640625q1.6875 0 2.75 0.859375q1.078125 0.859375 1.390625 2.421875l-1.71875 0.265625q-0.234375 -1.046875 -0.859375 -1.5625q-0.625 -0.53125 -1.5 -0.53125q-1.328125 0 -2.15625 0.953125q-0.828125 0.953125 -0.828125 3.0q0 2.09375 0.796875 3.046875q0.796875 0.9375 2.09375 0.9375q1.03125 0 1.71875 -0.625q0.703125 -0.640625 0.890625 -1.953125zm2.578125 -1.390625q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875zm9.966797 5.1875l0 -10.375l1.59375 0l0 1.484375q1.140625 -1.71875 3.296875 -1.71875q0.9375 0 1.71875 0.34375q0.796875 0.328125 1.1875 0.875q0.390625 0.546875 0.546875 1.296875q0.09375 0.5 0.09375 1.71875l0 6.375l-1.765625 0l0 -6.3125q0 -1.078125 -0.203125 -1.609375q-0.203125 -0.53125 -0.734375 -0.84375q-0.515625 -0.3125 -1.21875 -0.3125q-1.125 0 -1.9375 0.71875q-0.8125 0.703125 -0.8125 2.6875l0 5.671875l-1.765625 0zm11.123047 0l0 -10.375l1.59375 0l0 1.484375q1.140625 -1.71875 3.296875 -1.71875q0.9375 0 1.71875 0.34375q0.796875 0.328125 1.1875 0.875q0.390625 0.546875 0.546875 1.296875q0.09375 0.5 0.09375 1.71875l0 6.375l-1.765625 0l0 -6.3125q0 -1.078125 -0.203125 -1.609375q-0.203125 -0.53125 -0.734375 -0.84375q-0.515625 -0.3125 -1.21875 -0.3125q-1.125 0 -1.9375 0.71875q-0.8125 0.703125 -0.8125 2.6875l0 5.671875l-1.765625 0zm18.232422 -3.34375l1.8125 0.234375q-0.421875 1.578125 -1.59375 2.46875q-1.15625 0.875 -2.96875 0.875q-2.265625 0 -3.609375 -1.390625q-1.328125 -1.40625 -1.328125 -3.9375q0 -2.625 1.34375 -4.0625q1.34375 -1.453125 3.5 -1.453125q2.078125 0 3.390625 1.421875q1.328125 1.40625 1.328125 3.984375q0 0.15625 -0.015625 0.46875l-7.734375 0q0.09375 1.703125 0.96875 2.609375q0.875 0.90625 2.171875 0.90625q0.96875 0 1.640625 -0.5q0.6875 -0.515625 1.09375 -1.625zm-5.78125 -2.84375l5.796875 0q-0.109375 -1.296875 -0.65625 -1.953125q-0.84375 -1.015625 -2.1875 -1.015625q-1.203125 0 -2.03125 0.8125q-0.828125 0.796875 -0.921875 2.15625zm16.576172 2.390625l1.71875 0.21875q-0.28125 1.796875 -1.453125 2.8125q-1.15625 1.0 -2.859375 1.0q-2.125 0 -3.421875 -1.390625q-1.296875 -1.390625 -1.296875 -3.984375q0 -1.6875 0.546875 -2.9375q0.5625 -1.265625 1.703125 -1.890625q1.140625 -0.640625 2.484375 -0.640625q1.6875 0 2.75 0.859375q1.078125 0.859375 1.390625 2.421875l-1.71875 0.265625q-0.234375 -1.046875 -0.859375 -1.5625q-0.625 -0.53125 -1.5 -0.53125q-1.328125 0 -2.15625 0.953125q-0.828125 0.953125 -0.828125 3.0q0 2.09375 0.796875 3.046875q0.796875 0.9375 2.09375 0.9375q1.03125 0 1.71875 -0.625q0.703125 -0.640625 0.890625 -1.953125zm7.0625 2.21875l0.25 1.5625q-0.734375 0.15625 -1.328125 0.15625q-0.953125 0 -1.484375 -0.296875q-0.515625 -0.3125 -0.734375 -0.796875q-0.21875 -0.5 -0.21875 -2.078125l0 -5.96875l-1.28125 0l0 -1.375l1.28125 0l0 -2.5625l1.75 -1.0625l0 3.625l1.765625 0l0 1.375l-1.765625 0l0 6.0625q0 0.75 0.09375 0.96875q0.09375 0.203125 0.296875 0.34375q0.21875 0.125 0.609375 0.125q0.28125 0 0.765625 -0.078125zm1.0722656 -3.609375q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875zm9.951172 5.1875l0 -10.375l1.578125 0l0 1.578125q0.609375 -1.109375 1.125 -1.453125q0.515625 -0.359375 1.125 -0.359375q0.890625 0 1.8125 0.5625l-0.609375 1.640625q-0.640625 -0.390625 -1.28125 -0.390625q-0.578125 0 -1.046875 0.359375q-0.453125 0.34375 -0.65625 0.953125q-0.28125 0.9375 -0.28125 2.046875l0 5.4375l-1.765625 0zm11.560547 -4.296875l0 -1.765625l5.390625 0l0 1.765625l-5.390625 0zm12.888672 4.296875l0 -10.375l1.578125 0l0 1.453125q0.484375 -0.75 1.296875 -1.21875q0.8125 -0.46875 1.84375 -0.46875q1.15625 0 1.890625 0.484375q0.734375 0.46875 1.046875 1.328125q1.234375 -1.8125 3.203125 -1.8125q1.546875 0 2.375 0.859375q0.828125 0.859375 0.828125 2.625l0 7.125l-1.75 0l0 -6.53125q0 -1.0625 -0.171875 -1.515625q-0.171875 -0.46875 -0.625 -0.75q-0.4375 -0.28125 -1.046875 -0.28125q-1.09375 0 -1.828125 0.734375q-0.71875 0.71875 -0.71875 2.3125l0 6.03125l-1.75 0l0 -6.734375q0 -1.171875 -0.4375 -1.75q-0.421875 -0.59375 -1.40625 -0.59375q-0.734375 0 -1.375 0.390625q-0.625 0.390625 -0.90625 1.140625q-0.28125 0.75 -0.28125 2.171875l0 5.375l-1.765625 0zm16.582031 4.0l-0.1875 -1.65625q0.578125 0.15625 1.0 0.15625q0.59375 0 0.9375 -0.203125q0.359375 -0.1875 0.578125 -0.53125q0.171875 -0.265625 0.546875 -1.3125q0.046875 -0.15625 0.15625 -0.4375l-3.9375 -10.390625l1.890625 0l2.15625 6.015625q0.421875 1.140625 0.75 2.390625q0.3125 -1.203125 0.71875 -2.359375l2.21875 -6.046875l1.765625 0l-3.953125 10.546875q-0.625 1.71875 -0.984375 2.359375q-0.46875 0.875 -1.078125 1.265625q-0.59375 0.40625 -1.4375 0.40625q-0.515625 0 -1.140625 -0.203125zm9.09375 -4.0l0 -2.0l2.0 0l0 2.0l-2.0 0zm11.837891 -3.796875l1.71875 0.21875q-0.28125 1.796875 -1.453125 2.8125q-1.15625 1.0 -2.859375 1.0q-2.125 0 -3.421875 -1.390625q-1.296875 -1.390625 -1.296875 -3.984375q0 -1.6875 0.546875 -2.9375q0.5625 -1.265625 1.703125 -1.890625q1.140625 -0.640625 2.484375 -0.640625q1.6875 0 2.75 0.859375q1.078125 0.859375 1.390625 2.421875l-1.71875 0.265625q-0.234375 -1.046875 -0.859375 -1.5625q-0.625 -0.53125 -1.5 -0.53125q-1.328125 0 -2.15625 0.953125q-0.828125 0.953125 -0.828125 3.0q0 2.09375 0.796875 3.046875q0.796875 0.9375 2.09375 0.9375q1.03125 0 1.71875 -0.625q0.703125 -0.640625 0.890625 -1.953125zm2.578125 -1.390625q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875z" fill-rule="nonzero"/><path fill="#000000" d="m288.13907 337.09744l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.861328 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533203 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm2.1933594 -4.15625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m364.92343 337.09744l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m287.60782 353.48804l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.298828 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm2.1933594 -4.15625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m365.37656 348.6443l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m292.37344 363.9724q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.5332031 -1.0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.46875 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm3.9960938 0l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm10.861328 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.0800781 3.15625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.574219 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm6.517578 -1.359375l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m364.92343 365.0974l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm10.640625 -3.53125q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.5332031 -1.0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.46875 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0z" fill-rule="nonzero"/><path fill="#000000" d="m287.60782 381.48804l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm9.298828 1.765625q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.1894531 1.03125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm6.0 0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm7.078125 2.125l-0.640625 -6.21875l1.015625 0l0.28125 2.796875l0.109375 1.5625q0.015625 0.171875 0.03125 0.703125q0.1875 -0.59375 0.296875 -0.90625q0.125 -0.328125 0.40625 -0.921875l1.46875 -3.234375l1.15625 0l0.203125 3.109375q0.046875 0.703125 0.0625 1.890625q0.296875 -0.78125 0.953125 -2.1875l1.34375 -2.8125l1.0625 0l-3.046875 6.21875l-1.09375 0l-0.234375 -3.65625q-0.03125 -0.328125 -0.046875 -1.3125q-0.234375 0.625 -0.5625 1.34375l-1.640625 3.625l-1.125 0zm7.6816406 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm8.183594 -0.90625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm6.720703 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m369.2203 376.8318l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.71875 2.265625l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm10.861328 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.0957031 3.15625l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm6.611328 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm9.970703 0.640625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.574219 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625z" fill-rule="nonzero"/><path fill="#ffffff" d="m200.14961 28.889763l164.37794 0l0 217.51181l-164.37794 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m200.14961 28.889763l164.37794 0l0 217.51181l-164.37794 0z" fill-rule="evenodd"/><path fill="#000000" d="m209.11836 55.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm14.944717 -0.109375l0 1.578125l-8.82811 0q-0.015625 -0.59375 0.1875 -1.140625q0.34375 -0.90625 1.078125 -1.78125q0.75 -0.875 2.1562347 -2.015625q2.171875 -1.78125 2.9375 -2.828125q0.765625 -1.046875 0.765625 -1.96875q0 -0.984375 -0.703125 -1.640625q-0.6875 -0.671875 -1.8125 -0.671875q-1.1875 0 -1.9062347 0.71875q-0.703125 0.703125 -0.703125 1.953125l-1.6875 -0.171875q0.171875 -1.890625 1.296875 -2.875q1.1406097 -0.984375 3.0312347 -0.984375q1.921875 0 3.046875 1.0625q1.125 1.0625 1.125 2.640625q0 0.796875 -0.328125 1.578125q-0.328125 0.78125 -1.09375 1.640625q-0.75 0.84375 -2.53125 2.34375q-1.46875 1.234375 -1.890625 1.6875q-0.42185974 0.4375 -0.68748474 0.875l6.5468597 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m204.59407 73.062996l152.0945 0l0 25.51181l-152.0945 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m204.59407 73.062996l152.0945 0l0 25.51181l-152.0945 0z" fill-rule="evenodd"/><path fill="#000000" d="m222.20345 87.471115l1.390625 0.34375q-0.4375 1.703125 -1.578125 2.609375q-1.125 0.890625 -2.765625 0.890625q-1.6875 0 -2.75 -0.6875q-1.0625 -0.6875 -1.625 -2.0q-0.546875 -1.3125 -0.546875 -2.8125q0 -1.640625 0.625 -2.859375q0.625 -1.21875 1.78125 -1.84375q1.15625 -0.640625 2.546875 -0.640625q1.5625 0 2.640625 0.8125q1.078125 0.796875 1.5 2.25l-1.375 0.3125q-0.359375 -1.140625 -1.0625 -1.65625q-0.6875 -0.53125 -1.734375 -0.53125q-1.21875 0 -2.03125 0.578125q-0.8125 0.578125 -1.140625 1.5625q-0.328125 0.96875 -0.328125 2.015625q0 1.328125 0.390625 2.328125q0.390625 1.0 1.21875 1.5q0.828125 0.484375 1.78125 0.484375q1.171875 0 1.96875 -0.671875q0.8125 -0.671875 1.09375 -1.984375zm2.4592743 -0.125q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307358 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072983 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.291733 -5.21875l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686493 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594604 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717896 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.3073425 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m204.59407 108.86232l152.0945 0l0 29.952759l-152.0945 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m204.59407 108.86232l152.0945 0l0 29.952759l-152.0945 0z" fill-rule="evenodd"/><path fill="#000000" d="m214.25032 123.56732l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.041229 0.59375l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm2.375 2.78125l0 -10.484375l1.28125 0l0 3.75q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354233 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104233 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.276108 3.796875l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm3.1354675 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.49054 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m204.59407 146.05766l152.0945 0l0 93.41733l-152.0945 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m204.59407 146.05766l152.0945 0l0 93.41733l-152.0945 0z" fill-rule="evenodd"/><path fill="#000000" d="m213.57845 164.13766l4.015625 -10.484375l1.5 0l4.296875 10.484375l-1.578125 0l-1.234375 -3.171875l-4.375 0l-1.15625 3.171875l-1.46875 0zm3.015625 -4.3125l3.5625 0l-1.09375 -2.90625q-0.5 -1.3125 -0.75 -2.171875q-0.203125 1.015625 -0.5625 2.0l-1.15625 3.078125zm12.697479 1.53125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594757 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717743 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307358 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm7.635483 -2.265625l1.2656097 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.54685974 -0.265625 -0.82810974 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.29685974 -0.21875 0.81248474 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.2656097 -0.609375q-0.765625 -0.625 -0.984375 -1.828125z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m217.09448 172.23885l125.79529 0l0 56.850388l-125.79529 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m217.09448 172.23885l125.79529 0l0 56.850388l-125.79529 0z" fill-rule="evenodd"/><path fill="#000000" d="m229.20386 191.60684l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m300.42065 189.49747l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m233.15698 205.59122l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m295.18628 208.60684l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m227.18823 221.60684l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m387.17847 28.889763l164.37799 0l0 217.51181l-164.37799 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m387.17847 28.889763l164.37799 0l0 217.51181l-164.37799 0z" fill-rule="evenodd"/><path fill="#000000" d="m396.14722 55.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816711 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125702 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm6.3353577 -2.0625l1.640625 -0.21875q0.28125 1.40625 0.953125 2.015625q0.6875 0.609375 1.65625 0.609375q1.15625 0 1.953125 -0.796875q0.796875 -0.796875 0.796875 -1.984375q0 -1.125 -0.734375 -1.859375q-0.734375 -0.734375 -1.875 -0.734375q-0.46875 0 -1.15625 0.171875l0.1875 -1.4375q0.15625 0.015625 0.265625 0.015625q1.046875 0 1.875 -0.546875q0.84375 -0.546875 0.84375 -1.671875q0 -0.90625 -0.609375 -1.5q-0.609375 -0.59375 -1.578125 -0.59375q-0.953125 0 -1.59375 0.609375q-0.640625 0.59375 -0.8125 1.796875l-1.640625 -0.296875q0.296875 -1.640625 1.359375 -2.546875q1.0625 -0.90625 2.65625 -0.90625q1.09375 0 2.0 0.46875q0.921875 0.46875 1.40625 1.28125q0.5 0.8125 0.5 1.71875q0 0.859375 -0.46875 1.578125q-0.46875 0.703125 -1.375 1.125q1.1875 0.28125 1.84375 1.140625q0.65625 0.859375 0.65625 2.15625q0 1.734375 -1.28125 2.953125q-1.265625 1.21875 -3.21875 1.21875q-1.765625 0 -2.921875 -1.046875q-1.15625 -1.046875 -1.328125 -2.71875z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m391.62292 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m391.62292 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m409.2323 87.471115l1.390625 0.34375q-0.4375 1.703125 -1.578125 2.609375q-1.125 0.890625 -2.765625 0.890625q-1.6875 0 -2.75 -0.6875q-1.0625 -0.6875 -1.625 -2.0q-0.546875 -1.3125 -0.546875 -2.8125q0 -1.640625 0.625 -2.859375q0.625 -1.21875 1.78125 -1.84375q1.15625 -0.640625 2.546875 -0.640625q1.5625 0 2.640625 0.8125q1.078125 0.796875 1.5 2.25l-1.375 0.3125q-0.359375 -1.140625 -1.0625 -1.65625q-0.6875 -0.53125 -1.734375 -0.53125q-1.21875 0 -2.03125 0.578125q-0.8125 0.578125 -1.140625 1.5625q-0.328125 0.96875 -0.328125 2.015625q0 1.328125 0.390625 2.328125q0.390625 1.0 1.21875 1.5q0.828125 0.484375 1.78125 0.484375q1.171875 0 1.96875 -0.671875q0.8125 -0.671875 1.09375 -1.984375zm2.4592896 -0.125q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.3073425 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072998 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.2917175 -5.21875l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686646 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594604 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717896 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.3073425 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m391.62292 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m391.62292 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m401.27917 123.56732l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.041229 0.59375l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm2.375 2.78125l0 -10.484375l1.28125 0l0 3.75q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354248 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104218 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.276123 3.796875l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm3.1354675 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.49054 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m391.62292 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m391.62292 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m400.6073 164.13766l4.015625 -10.484375l1.5 0l4.296875 10.484375l-1.578125 0l-1.234375 -3.171875l-4.375 0l-1.15625 3.171875l-1.46875 0zm3.015625 -4.3125l3.5625 0l-1.09375 -2.90625q-0.5 -1.3125 -0.75 -2.171875q-0.203125 1.015625 -0.5625 2.0l-1.15625 3.078125zm12.697479 1.53125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.259491 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.771759 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm7.6354675 -2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m404.12335 172.23885l125.79529 0l0 56.850388l-125.79529 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m404.12335 172.23885l125.79529 0l0 56.850388l-125.79529 0z" fill-rule="evenodd"/><path fill="#000000" d="m416.23273 191.60684l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m487.44952 189.49747l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m420.18585 205.59122l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m482.21515 208.60684l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m414.2171 221.60684l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#ffffff" d="m578.65094 28.889763l164.37793 0l0 217.51181l-164.37793 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m578.65094 28.889763l164.37793 0l0 217.51181l-164.37793 0z" fill-rule="evenodd"/><path fill="#000000" d="m587.6197 55.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.8029175 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816711 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125732 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.8063965 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm11.585388 1.46875l0 -3.203125l-5.796875 0l0 -1.5l6.09375 -8.65625l1.34375 0l0 8.65625l1.796875 0l0 1.5l-1.796875 0l0 3.203125l-1.640625 0zm0 -4.703125l0 -6.015625l-4.1875 6.015625l4.1875 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m583.0954 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m583.0954 73.062996l152.09448 0l0 25.51181l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m600.7048 87.471115l1.390625 0.34375q-0.4375 1.703125 -1.578125 2.609375q-1.125 0.890625 -2.765625 0.890625q-1.6875 0 -2.75 -0.6875q-1.0625 -0.6875 -1.625 -2.0q-0.546875 -1.3125 -0.546875 -2.8125q0 -1.640625 0.625 -2.859375q0.625 -1.21875 1.78125 -1.84375q1.15625 -0.640625 2.546875 -0.640625q1.5625 0 2.640625 0.8125q1.078125 0.796875 1.5 2.25l-1.375 0.3125q-0.359375 -1.140625 -1.0625 -1.65625q-0.6875 -0.53125 -1.734375 -0.53125q-1.21875 0 -2.03125 0.578125q-0.8125 0.578125 -1.140625 1.5625q-0.328125 0.96875 -0.328125 2.015625q0 1.328125 0.390625 2.328125q0.390625 1.0 1.21875 1.5q0.828125 0.484375 1.78125 0.484375q1.171875 0 1.96875 -0.671875q0.8125 -0.671875 1.09375 -1.984375zm2.4592285 -0.125q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072998 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.291748 -5.21875l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686035 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2595215 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717285 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m583.0954 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m583.0954 108.86232l152.09448 0l0 29.952759l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m592.75165 123.56732l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.041199 0.59375l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm2.375 2.78125l0 -10.484375l1.28125 0l0 3.75q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354248 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104248 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.276062 3.796875l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm3.135498 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.49054 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m583.0954 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m583.0954 146.05766l152.09448 0l0 93.41733l-152.09448 0z" fill-rule="evenodd"/><path fill="#000000" d="m592.0798 164.13766l4.015625 -10.484375l1.5 0l4.296875 10.484375l-1.578125 0l-1.234375 -3.171875l-4.375 0l-1.15625 3.171875l-1.46875 0zm3.015625 -4.3125l3.5625 0l-1.09375 -2.90625q-0.5 -1.3125 -0.75 -2.171875q-0.203125 1.015625 -0.5625 2.0l-1.15625 3.078125zm12.697449 1.53125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594604 -7.859375l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717896 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm7.635498 -2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m595.5958 172.23885l125.79523 0l0 56.850388l-125.79523 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m595.5958 172.23885l125.79523 0l0 56.850388l-125.79523 0z" fill-rule="evenodd"/><path fill="#000000" d="m607.7052 191.60684l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m678.922 189.49747l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m611.6583 205.59122l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m673.6876 208.60684l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m605.6896 221.60684l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm3.3339844 0l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m124.698166 215.20735l257.3543 63.37007" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m124.698166 215.20735l257.3543 63.37007" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m307.37534 216.08923l74.677155 62.48819" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m307.37534 216.08923l74.677155 62.48819" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m495.28085 215.20735l-113.22836 63.37007" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m495.28085 215.20735l-113.22836 63.37007" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m685.76904 215.20735l-303.71655 63.37007" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m685.76904 215.20735l-303.71655 63.37007" fill-rule="evenodd"/></g></svg> \ No newline at end of file diff --git a/docs/user/alerting/images/alert-concepts-summary.svg b/docs/user/alerting/images/alert-concepts-summary.svg new file mode 100644 index 0000000000000..d11023b706418 --- /dev/null +++ b/docs/user/alerting/images/alert-concepts-summary.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 995.4120734908137 468.84776902887137" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l995.41205 0l0 468.84778l-995.41205 0l0 -468.84778z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l995.41205 0l0 468.84778l-995.41205 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m13.120735 52.889763l260.8819 0l0 266.61417l-260.8819 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m13.120735 52.889763l260.8819 0l0 266.61417l-260.8819 0z" fill-rule="evenodd"/><path fill="#000000" d="m22.089485 79.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 97.062996l233.00789 0l0 33.511803l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 97.062996l233.00789 0l0 33.511803l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m43.750084 117.40737l1.515625 0.375q-0.46875 1.875 -1.71875 2.859375q-1.234375 0.984375 -3.015625 0.984375q-1.859375 0 -3.015625 -0.75q-1.15625 -0.765625 -1.765625 -2.1875q-0.609375 -1.4375 -0.609375 -3.078125q0 -1.796875 0.6875 -3.125q0.6875 -1.328125 1.9375 -2.015625q1.265625 -0.703125 2.78125 -0.703125q1.71875 0 2.890625 0.875q1.171875 0.875 1.640625 2.46875l-1.5 0.34375q-0.390625 -1.25 -1.15625 -1.8125q-0.75 -0.578125 -1.90625 -0.578125q-1.3125 0 -2.203125 0.640625q-0.890625 0.625 -1.25 1.703125q-0.359375 1.0625 -0.359375 2.1875q0 1.46875 0.421875 2.5625q0.4375 1.078125 1.328125 1.625q0.90625 0.53125 1.953125 0.53125q1.265625 0 2.140625 -0.734375q0.890625 -0.734375 1.203125 -2.171875zm2.6796875 -0.140625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm14.2734375 0l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm7.9609375 -5.703125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm6.6171875 -1.265625l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0z" fill-rule="nonzero"/><path fill="#000000" d="m136.46883 120.39175q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm4.8671875 4.203125l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm5.828125 0.75l1.4375 0.140625q-0.015625 0.484375 0.109375 0.71875q0.140625 0.25 0.421875 0.375q0.390625 0.171875 1.0 0.171875q1.28125 0 1.84375 -0.65625q0.359375 -0.453125 0.671875 -1.953125l0.140625 -0.671875q-1.09375 1.125 -2.34375 1.125q-1.25 0 -2.109375 -0.921875q-0.84375 -0.9375 -0.84375 -2.625q0 -1.40625 0.671875 -2.578125q0.671875 -1.171875 1.59375 -1.765625q0.921875 -0.59375 1.890625 -0.59375q1.640625 0 2.515625 1.546875l0.28125 -1.359375l1.296875 0l-1.671875 8.0q-0.265625 1.328125 -0.71875 2.0625q-0.4375 0.75 -1.234375 1.15625q-0.796875 0.40625 -1.828125 0.40625q-1.0 0 -1.734375 -0.265625q-0.71875 -0.25 -1.078125 -0.75q-0.34375 -0.5 -0.34375 -1.140625q0 -0.1875 0.03125 -0.421875zm1.765625 -4.421875q0 0.84375 0.171875 1.28125q0.234375 0.59375 0.65625 0.921875q0.4375 0.3125 0.96875 0.3125q0.703125 0 1.390625 -0.484375q0.6875 -0.5 1.109375 -1.515625q0.421875 -1.03125 0.421875 -1.953125q0 -1.03125 -0.5625 -1.625q-0.5625 -0.609375 -1.40625 -0.609375q-0.515625 0 -1.0 0.28125q-0.484375 0.265625 -0.90625 0.84375q-0.40625 0.5625 -0.625 1.359375q-0.21875 0.78125 -0.21875 1.1875zm20.78125 -0.359375l1.515625 0.203125q-0.71875 1.984375 -2.09375 3.015625q-1.375 1.015625 -3.09375 1.015625q-2.078125 0 -3.3125 -1.28125q-1.21875 -1.28125 -1.21875 -3.65625q0 -3.09375 1.859375 -5.109375q1.65625 -1.8125 4.125 -1.8125q1.8125 0 2.9375 0.984375q1.140625 0.96875 1.3125 2.625l-1.421875 0.125q-0.234375 -1.234375 -0.9375 -1.84375q-0.703125 -0.625 -1.828125 -0.625q-2.09375 0 -3.390625 1.875q-1.125 1.609375 -1.125 3.8125q0 1.765625 0.859375 2.703125q0.875 0.921875 2.265625 0.921875q1.1875 0 2.140625 -0.765625q0.96875 -0.78125 1.40625 -2.1875zm2.5859375 4.03125l2.40625 -11.453125l4.78125 0q1.234375 0 1.859375 0.28125q0.625 0.28125 1.03125 0.984375q0.40625 0.6875 0.40625 1.546875q0 0.703125 -0.296875 1.4375q-0.28125 0.734375 -0.734375 1.21875q-0.4375 0.46875 -0.890625 0.71875q-0.453125 0.234375 -0.96875 0.359375q-1.09375 0.25 -2.21875 0.25l-2.875 0l-0.96875 4.65625l-1.53125 0zm2.78125 -5.953125l2.515625 0q1.46875 0 2.15625 -0.3125q0.6875 -0.3125 1.09375 -0.953125q0.421875 -0.65625 0.421875 -1.390625q0 -0.5625 -0.21875 -0.90625q-0.21875 -0.359375 -0.625 -0.53125q-0.390625 -0.171875 -1.515625 -0.171875l-2.9375 0l-0.890625 4.265625zm10.375 -5.5l1.53125 0l-1.46875 7.03125q-0.171875 0.875 -0.171875 1.296875q0 0.921875 0.71875 1.484375q0.734375 0.5625 1.828125 0.5625q0.875 0 1.625 -0.390625q0.765625 -0.40625 1.203125 -1.1875q0.4375 -0.78125 0.78125 -2.5l1.328125 -6.296875l1.53125 0l-1.40625 6.71875q-0.359375 1.71875 -0.953125 2.71875q-0.578125 1.0 -1.625 1.609375q-1.03125 0.609375 -2.40625 0.609375q-1.296875 0 -2.25 -0.421875q-0.9375 -0.4375 -1.421875 -1.1875q-0.46875 -0.765625 -0.46875 -1.734375q0 -0.59375 0.328125 -2.0625l1.296875 -6.25zm21.859375 6.4375l-7.59375 3.25l0 -1.40625l6.015625 -2.484375l-6.015625 -2.46875l0 -1.40625l7.59375 3.203125l0 1.3125zm5.8984375 1.25q0 -1.453125 0.421875 -2.953125q0.4375 -1.5 0.96875 -2.390625q0.53125 -0.90625 1.09375 -1.40625q0.578125 -0.515625 1.125 -0.75q0.5625 -0.234375 1.234375 -0.234375q1.3125 0 2.1875 0.984375q0.875 0.96875 0.875 2.8125q0 1.890625 -0.609375 3.75q-0.71875 2.203125 -2.0 3.3125q-0.984375 0.84375 -2.234375 0.84375q-1.296875 0 -2.1875 -1.015625q-0.875 -1.015625 -0.875 -2.953125zm1.359375 0.359375q0 1.0625 0.359375 1.65625q0.46875 0.8125 1.40625 0.8125q0.828125 0 1.5 -0.734375q0.96875 -1.046875 1.453125 -3.0625q0.484375 -2.03125 0.484375 -3.3125q0 -1.234375 -0.46875 -1.78125q-0.46875 -0.546875 -1.25 -0.546875q-0.5625 0 -1.046875 0.296875q-0.484375 0.28125 -0.9375 0.984375q-0.625 1.0 -1.09375 2.96875q-0.40625 1.6875 -0.40625 2.71875zm7.3203125 3.40625l0.34375 -1.609375l1.59375 0l-0.34375 1.609375l-1.59375 0zm4.6015625 -2.625l1.328125 -0.140625q0.140625 0.96875 0.546875 1.375q0.421875 0.40625 0.984375 0.40625q0.8125 0 1.515625 -0.703125q1.015625 -1.03125 1.5 -2.96875q-0.703125 0.53125 -1.265625 0.765625q-0.546875 0.21875 -1.125 0.21875q-1.046875 0 -1.875 -0.703125q-1.09375 -0.90625 -1.09375 -2.625q0 -1.9375 1.265625 -3.3125q1.09375 -1.1875 2.671875 -1.1875q1.421875 0 2.359375 1.046875q0.9375 1.046875 0.9375 2.96875q0 1.875 -0.625 3.6875q-0.75 2.140625 -2.015625 3.15625q-1.03125 0.84375 -2.3125 0.84375q-1.1875 0 -1.953125 -0.734375q-0.75 -0.75 -0.84375 -2.09375zm1.890625 -4.53125q0 1.078125 0.5625 1.71875q0.578125 0.640625 1.375 0.640625q0.578125 0 1.15625 -0.390625q0.578125 -0.40625 0.984375 -1.203125q0.421875 -0.796875 0.421875 -1.625q0 -0.65625 -0.28125 -1.21875q-0.265625 -0.5625 -0.734375 -0.84375q-0.46875 -0.296875 -0.953125 -0.296875q-0.46875 0 -0.921875 0.25q-0.453125 0.25 -0.84375 0.734375q-0.390625 0.484375 -0.578125 1.125q-0.1875 0.625 -0.1875 1.109375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 144.07611l233.00789 0l0 39.3071l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 144.07611l233.00789 0l0 39.3071l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m35.062584 164.74861l1.4375 -0.125q0.09375 0.859375 0.46875 1.421875q0.375 0.546875 1.15625 0.890625q0.78125 0.328125 1.75 0.328125q0.875 0 1.53125 -0.25q0.671875 -0.265625 0.984375 -0.703125q0.328125 -0.453125 0.328125 -0.984375q0 -0.546875 -0.3125 -0.9375q-0.3125 -0.40625 -1.03125 -0.6875q-0.453125 -0.171875 -2.03125 -0.546875q-1.578125 -0.390625 -2.21875 -0.71875q-0.8125 -0.4375 -1.21875 -1.0625q-0.40625 -0.640625 -0.40625 -1.4375q0 -0.859375 0.484375 -1.609375q0.5 -0.765625 1.4375 -1.15625q0.953125 -0.390625 2.109375 -0.390625q1.28125 0 2.25 0.421875q0.96875 0.40625 1.484375 1.203125q0.53125 0.796875 0.578125 1.796875l-1.453125 0.109375q-0.125 -1.078125 -0.796875 -1.625q-0.671875 -0.5625 -2.0 -0.5625q-1.375 0 -2.0 0.5q-0.625 0.5 -0.625 1.21875q0 0.609375 0.4375 1.015625q0.4375 0.390625 2.28125 0.8125q1.859375 0.421875 2.546875 0.734375q1.0 0.453125 1.46875 1.171875q0.484375 0.703125 0.484375 1.625q0 0.90625 -0.53125 1.71875q-0.515625 0.8125 -1.5 1.265625q-0.984375 0.453125 -2.203125 0.453125q-1.5625 0 -2.609375 -0.453125q-1.046875 -0.46875 -1.65625 -1.375q-0.59375 -0.90625 -0.625 -2.0625zm16.421875 0.640625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm2.59375 3.046875l0 -11.453125l1.40625 0l0 4.109375q0.984375 -1.140625 2.484375 -1.140625q0.921875 0 1.59375 0.359375q0.6875 0.359375 0.96875 1.0q0.296875 0.640625 0.296875 1.859375l0 5.265625l-1.40625 0l0 -5.265625q0 -1.046875 -0.453125 -1.53125q-0.453125 -0.484375 -1.296875 -0.484375q-0.625 0 -1.171875 0.328125q-0.546875 0.328125 -0.78125 0.890625q-0.234375 0.546875 -0.234375 1.515625l0 4.546875l-1.40625 0zm14.5703125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875zm13.2109375 4.953125l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm13.3984375 4.140625l0 -1.21875q-0.96875 1.40625 -2.640625 1.40625q-0.734375 0 -1.375 -0.28125q-0.625 -0.28125 -0.9375 -0.703125q-0.3125 -0.4375 -0.4375 -1.046875q-0.078125 -0.421875 -0.078125 -1.3125l0 -5.140625l1.40625 0l0 4.59375q0 1.109375 0.078125 1.484375q0.140625 0.5625 0.5625 0.875q0.4375 0.3125 1.0625 0.3125q0.640625 0 1.1875 -0.3125q0.5625 -0.328125 0.78125 -0.890625q0.234375 -0.5625 0.234375 -1.625l0 -4.4375l1.40625 0l0 8.296875l-1.25 0zm3.4296875 0l0 -11.453125l1.40625 0l0 11.453125l-1.40625 0zm9.2578125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875z" fill-rule="nonzero"/><path fill="#000000" d="m136.96883 165.60799l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm9.0078125 4.875l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm12.0 -2.828125l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm4.796875 3.203125l0.09375 -1.328125q0.4375 0.125 0.84375 0.125q0.4375 0 0.703125 -0.1875q0.34375 -0.265625 0.75 -0.96875l0.453125 -0.8125l-1.390625 -8.328125l1.390625 0l0.625 4.1875q0.1875 1.25 0.328125 2.484375l3.703125 -6.671875l1.484375 0l-5.296875 9.40625q-0.765625 1.375 -1.359375 1.8125q-0.59375 0.453125 -1.359375 0.453125q-0.5 0 -0.96875 -0.171875zm12.9765625 -3.203125l1.734375 -8.296875l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.34375l-1.40625 0l1.140625 -5.484375q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.03125l-1.421875 0l1.171875 -5.609375q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.921875l-1.40625 0zm15.34375 -9.859375l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859375l1.734375 -8.296875l1.40625 0l-1.734375 8.296875l-1.40625 0zm3.6015625 0l1.734375 -8.296875l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.03125l-1.40625 0l1.09375 -5.265625q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.859375l-1.421875 0zm14.5703125 -1.5q-1.5 1.6875 -3.0625 1.6875q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5625 -0.59375 -1.359375q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296875l-1.296875 0l0.3125 -1.5zm6.5390625 0.34375l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 192.92389l233.00789 0l0 112.12598l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 192.92389l233.00789 0l0 112.12598l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m34.312584 217.28389l4.40625 -11.453125l1.640625 0l4.6875 11.453125l-1.734375 0l-1.328125 -3.46875l-4.796875 0l-1.25 3.46875l-1.625 0zm3.3125 -4.703125l3.890625 0l-1.203125 -3.171875q-0.546875 -1.453125 -0.8125 -2.375q-0.21875 1.09375 -0.609375 2.1875l-1.265625 3.359375zm13.859375 1.65625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm5.65625 1.78125l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm8.3359375 -2.484375l1.390625 -0.21875q0.109375 0.84375 0.640625 1.296875q0.546875 0.4375 1.5 0.4375q0.96875 0 1.4375 -0.390625q0.46875 -0.40625 0.46875 -0.9375q0 -0.46875 -0.40625 -0.75q-0.296875 -0.1875 -1.4375 -0.46875q-1.546875 -0.390625 -2.15625 -0.671875q-0.59375 -0.296875 -0.90625 -0.796875q-0.296875 -0.5 -0.296875 -1.109375q0 -0.5625 0.25 -1.03125q0.25 -0.46875 0.6875 -0.78125q0.328125 -0.25 0.890625 -0.40625q0.578125 -0.171875 1.21875 -0.171875q0.984375 0 1.71875 0.28125q0.734375 0.28125 1.078125 0.765625q0.359375 0.46875 0.5 1.28125l-1.375 0.1875q-0.09375 -0.640625 -0.546875 -1.0q-0.453125 -0.359375 -1.265625 -0.359375q-0.96875 0 -1.390625 0.328125q-0.40625 0.3125 -0.40625 0.734375q0 0.28125 0.171875 0.5q0.171875 0.21875 0.53125 0.375q0.21875 0.078125 1.25 0.359375q1.484375 0.390625 2.078125 0.65625q0.59375 0.25 0.921875 0.734375q0.34375 0.484375 0.34375 1.203125q0 0.703125 -0.421875 1.328125q-0.40625 0.609375 -1.1875 0.953125q-0.765625 0.34375 -1.734375 0.34375q-1.625 0 -2.46875 -0.671875q-0.84375 -0.671875 -1.078125 -2.0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m45.49346 236.11156l195.77954 0l0 53.48033l-195.77954 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m45.49346 236.11156l195.77954 0l0 53.48033l-195.77954 0z" fill-rule="evenodd"/><path fill="#000000" d="m55.446587 256.63156l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m61.55596 267.61594l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm6.3867188 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm9.949219 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34374237 0 0.5468674 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.3749924 -6.234375l1.140625 0l1.2968674 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.8593674 0.25q-0.296875 0 -0.671875 -0.140625zm5.4531174 -2.390625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm7.0996094 -2.28125l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm1.546875 -0.828125q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125z" fill-rule="nonzero"/><path fill="#000000" d="m59.08721 277.63156l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m103.84112 273.76828l58.04882 0l0 13.798828l-58.04882 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m104.34112 282.2253l0.3125 -1.40625q0.421875 -0.015625 0.671875 -0.125q0.25 -0.109375 0.453125 -0.375q0.21875 -0.265625 0.34375 -0.609375q0.140625 -0.34375 0.296875 -1.09375q0.21875 -1.0625 0.4375 -1.515625q0.234375 -0.453125 0.546875 -0.703125q0.328125 -0.25 0.890625 -0.40625q0.359375 -0.09375 1.125 -0.09375l0.3125 0l-0.3125 1.390625q-0.65625 0 -0.875 0.09375q-0.21875 0.078125 -0.328125 0.265625q-0.078125 0.109375 -0.265625 0.859375q-0.328125 1.296875 -0.4375 1.578125q-0.203125 0.515625 -0.5 0.828125q-0.28125 0.3125 -0.796875 0.609375q0.34375 0.234375 0.5 0.5625q0.171875 0.3125 0.171875 0.84375q0 0.203125 -0.078125 0.625q-0.1875 1.15625 -0.25 1.359375q-0.046875 0.21875 -0.046875 0.359375q0 0.15625 0.078125 0.265625q0.09375 0.109375 0.25 0.15625q0.171875 0.0625 0.75 0.0625l-0.3125 1.40625l-0.3125 0q-0.796875 0 -1.203125 -0.140625q-0.390625 -0.125 -0.609375 -0.4375q-0.21875 -0.296875 -0.21875 -0.78125q0 -0.390625 0.203125 -1.328125q0.203125 -0.9375 0.203125 -1.25q0 -0.5 -0.21875 -0.734375q-0.21875 -0.234375 -0.78125 -0.265625zm4.669922 0l0.3125 -1.40625q0.421875 -0.015625 0.671875 -0.125q0.25 -0.109375 0.453125 -0.375q0.21875 -0.265625 0.34375 -0.609375q0.140625 -0.34375 0.296875 -1.09375q0.21875 -1.0625 0.4375 -1.515625q0.234375 -0.453125 0.546875 -0.703125q0.328125 -0.25 0.890625 -0.40625q0.359375 -0.09375 1.125 -0.09375l0.3125 0l-0.3125 1.390625q-0.65625 0 -0.875 0.09375q-0.21875 0.078125 -0.328125 0.265625q-0.078125 0.109375 -0.265625 0.859375q-0.328125 1.296875 -0.4375 1.578125q-0.203125 0.515625 -0.5 0.828125q-0.28125 0.3125 -0.796875 0.609375q0.34375 0.234375 0.5 0.5625q0.171875 0.3125 0.171875 0.84375q0 0.203125 -0.078125 0.625q-0.1875 1.15625 -0.25 1.359375q-0.046875 0.21875 -0.046875 0.359375q0 0.15625 0.078125 0.265625q0.09375 0.109375 0.25 0.15625q0.171875 0.0625 0.75 0.0625l-0.3125 1.40625l-0.3125 0q-0.796875 0 -1.203125 -0.140625q-0.390625 -0.125 -0.609375 -0.4375q-0.21875 -0.296875 -0.21875 -0.78125q0 -0.390625 0.203125 -1.328125q0.203125 -0.9375 0.203125 -1.25q0 -0.5 -0.21875 -0.734375q-0.21875 -0.234375 -0.78125 -0.265625zm4.435547 0.671875l1.625 -0.265625q0.21875 0.515625 0.53125 0.734375q0.328125 0.203125 0.890625 0.203125q0.578125 0 0.921875 -0.25q0.234375 -0.171875 0.234375 -0.421875q0 -0.171875 -0.125 -0.3125q-0.125 -0.125 -0.6875 -0.3125q-1.53125 -0.5 -1.890625 -0.796875q-0.5625 -0.453125 -0.5625 -1.203125q0 -0.734375 0.546875 -1.265625q0.765625 -0.75 2.28125 -0.75q1.203125 0 1.8125 0.453125q0.609375 0.4375 0.78125 1.1875l-1.5625 0.265625q-0.109375 -0.34375 -0.390625 -0.515625q-0.375 -0.21875 -0.90625 -0.21875q-0.53125 0 -0.765625 0.171875q-0.21875 0.171875 -0.21875 0.40625q0 0.234375 0.234375 0.375q0.140625 0.09375 0.9375 0.328125q1.234375 0.359375 1.65625 0.703125q0.578125 0.5 0.578125 1.171875q0 0.890625 -0.75 1.546875q-0.734375 0.640625 -2.09375 0.640625q-1.34375 0 -2.078125 -0.484375q-0.734375 -0.5 -1.0 -1.390625zm12.955078 -0.859375l-4.21875 0q-0.015625 0.109375 -0.015625 0.15625q0 0.625 0.359375 1.0q0.359375 0.375 0.859375 0.375q0.84375 0 1.3125 -0.859375l1.5 0.25q-0.4375 0.90625 -1.171875 1.359375q-0.734375 0.453125 -1.65625 0.453125q-1.25 0 -2.03125 -0.78125q-0.78125 -0.796875 -0.78125 -2.109375q0 -1.28125 0.703125 -2.265625q0.96875 -1.359375 2.765625 -1.359375q1.140625 0 1.8125 0.71875q0.671875 0.703125 0.671875 1.96875q0 0.609375 -0.109375 1.09375zm-1.421875 -1.015625q0 -0.125 0 -0.171875q0 -0.703125 -0.3125 -1.046875q-0.3125 -0.34375 -0.828125 -0.34375q-0.515625 0 -0.9375 0.390625q-0.40625 0.390625 -0.5625 1.171875l2.640625 0zm3.2363205 -2.609375l1.578125 0l-0.265625 1.203125q0.890625 -1.359375 1.90625 -1.359375q0.375 0 0.78125 0.1875l-0.640625 1.375q-0.234375 -0.078125 -0.484375 -0.078125q-0.4375 0 -0.890625 0.328125q-0.4375 0.328125 -0.703125 0.875q-0.25 0.546875 -0.484375 1.734375l-0.421875 1.953125l-1.6718674 0l1.2968674 -6.21875zm6.576172 6.21875l-1.453125 0l-1.25 -6.21875l1.65625 0l0.4375 2.703125q0.1875 1.109375 0.21875 1.46875q0.046875 -0.09375 0.40625 -0.75q0.359375 -0.671875 0.453125 -0.796875l1.546875 -2.625l1.8125 0l-3.828125 6.21875zm9.626953 -2.59375l-4.21875 0q-0.015625 0.109375 -0.015625 0.15625q0 0.625 0.359375 1.0q0.359375 0.375 0.859375 0.375q0.84375 0 1.3125 -0.859375l1.5 0.25q-0.4375 0.90625 -1.171875 1.359375q-0.734375 0.453125 -1.65625 0.453125q-1.25 0 -2.03125 -0.78125q-0.78125 -0.796875 -0.78125 -2.109375q0 -1.28125 0.703125 -2.265625q0.96875 -1.359375 2.765625 -1.359375q1.140625 0 1.8125 0.71875q0.671875 0.703125 0.671875 1.96875q0 0.609375 -0.109375 1.09375zm-1.421875 -1.015625q0 -0.125 0 -0.171875q0 -0.703125 -0.3125 -1.046875q-0.3125 -0.34375 -0.828125 -0.34375q-0.515625 0 -0.9375 0.390625q-0.40625 0.390625 -0.5625 1.171875l2.640625 0zm3.2363281 -2.609375l1.578125 0l-0.265625 1.203125q0.890625 -1.359375 1.90625 -1.359375q0.375 0 0.78125 0.1875l-0.640625 1.375q-0.234375 -0.078125 -0.484375 -0.078125q-0.4375 0 -0.890625 0.328125q-0.4375 0.328125 -0.703125 0.875q-0.25 0.546875 -0.484375 1.734375l-0.421875 1.953125l-1.671875 0l1.296875 -6.21875zm7.044922 3.8125q-0.53125 0.03125 -0.828125 0.21875q-0.296875 0.1875 -0.515625 0.609375q-0.21875 0.40625 -0.4375 1.4375q-0.203125 1.015625 -0.4375 1.453125q-0.21875 0.453125 -0.546875 0.703125q-0.3125 0.25 -0.875 0.40625q-0.375 0.109375 -1.125 0.109375l-0.3125 0l0.296875 -1.40625q0.640625 0 0.859375 -0.09375q0.234375 -0.09375 0.359375 -0.265625q0.078125 -0.125 0.25 -0.84375q0.328125 -1.296875 0.421875 -1.546875q0.21875 -0.515625 0.53125 -0.875q0.3125 -0.359375 0.796875 -0.609375q-0.390625 -0.28125 -0.546875 -0.578125q-0.140625 -0.296875 -0.140625 -0.828125q0 -0.203125 0.078125 -0.625q0.1875 -1.125 0.234375 -1.34375q0.0625 -0.234375 0.0625 -0.390625q0 -0.15625 -0.078125 -0.25q-0.078125 -0.109375 -0.25 -0.15625q-0.15625 -0.0625 -0.75 -0.0625l0.3125 -1.390625l0.3125 0q0.796875 0 1.1875 0.140625q0.40625 0.125 0.625 0.421875q0.21875 0.296875 0.21875 0.78125q0 0.390625 -0.203125 1.328125q-0.203125 0.9375 -0.203125 1.25q0 0.5 0.21875 0.734375q0.21875 0.234375 0.78125 0.265625l-0.296875 1.40625zm4.669922 0q-0.53125 0.03125 -0.828125 0.21875q-0.296875 0.1875 -0.515625 0.609375q-0.21875 0.40625 -0.4375 1.4375q-0.203125 1.015625 -0.4375 1.453125q-0.21875 0.453125 -0.546875 0.703125q-0.3125 0.25 -0.875 0.40625q-0.375 0.109375 -1.125 0.109375l-0.3125 0l0.296875 -1.40625q0.640625 0 0.859375 -0.09375q0.234375 -0.09375 0.359375 -0.265625q0.078125 -0.125 0.25 -0.84375q0.328125 -1.296875 0.421875 -1.546875q0.21875 -0.515625 0.53125 -0.875q0.3125 -0.359375 0.796875 -0.609375q-0.390625 -0.28125 -0.546875 -0.578125q-0.140625 -0.296875 -0.140625 -0.828125q0 -0.203125 0.078125 -0.625q0.1875 -1.125 0.234375 -1.34375q0.0625 -0.234375 0.0625 -0.390625q0 -0.15625 -0.078125 -0.25q-0.078125 -0.109375 -0.25 -0.15625q-0.15625 -0.0625 -0.75 -0.0625l0.3125 -1.390625l0.3125 0q0.796875 0 1.1875 0.140625q0.40625 0.125 0.625 0.421875q0.21875 0.296875 0.21875 0.78125q0 0.390625 -0.203125 1.328125q-0.203125 0.9375 -0.203125 1.25q0 0.5 0.21875 0.734375q0.21875 0.234375 0.78125 0.265625l-0.296875 1.40625z" fill-rule="nonzero"/><path fill="#000000" d="m163.79619 277.24094l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m103.84112 285.41156l58.04882 0l0 1.0799866l-58.04882 0l0 -1.0799866z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m637.41473 52.889763l139.37012 0l0 56.598427l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m637.41473 52.889763l139.37012 0l0 56.598427l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m647.36786 73.40977l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m653.47723 84.39414l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm6.3867188 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm9.949219 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm5.453125 -2.390625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm7.0996094 -2.28125l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm1.546875 -0.828125q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125z" fill-rule="nonzero"/><path fill="#000000" d="m651.0085 94.40977l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m695.7624 90.546486l28.02539 0l0 13.798828l-28.02539 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m697.68427 101.40977l-2.28125 0l3.78125 -4.34375l-2.125 -4.25l1.84375 0l0.84375 1.609375q0.03125 0.09375 0.5625 1.1875q0.046875 0.0625 0.078125 0.171875q0.71875 -0.875 1.203125 -1.4375l1.359375 -1.53125l2.21875 0l-3.9375 4.53125l2.125 4.0625l-2.0 0l-0.640625 -1.296875q-0.5 -1.03125 -0.671875 -1.46875q-0.21875 0.34375 -1.171875 1.421875l-1.1875 1.34375zm7.5039062 -4.9375l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m729.028 94.01914l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m695.7624 102.189766l28.02539 0l0 1.0800018l-28.02539 0l0 -1.0800018z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 -32.62992" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l75.97275 -30.40084" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m334.93808 84.95158l3.5996704 -3.2194824l-4.826935 0.15245819z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 72.37795" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l77.05597 68.395" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m334.31122 183.4492l4.490448 1.7771912l-2.2975159 -4.2478027z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m352.57217 6.0367455l140.56693 0l0 33.51181l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m361.54092 32.956745l5.125 -13.359377l1.90625 0l5.46875 13.359377l-2.015625 0l-1.546875 -4.046877l-5.59375 0l-1.46875 4.046877l-1.875 0zm3.859375 -5.484377l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484377l0 -13.359377l1.640625 0l0 13.359377l-1.640625 0zm10.816711 -3.109377l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.312502q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.2968769q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125702 5.765627l0 -9.671877l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.062502l-1.625 0zm9.806427 -1.4687519l0.234375 1.4531269q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.4687519 -0.203125 -1.9375019l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.2884827 1.4687519l0 -13.359377l1.765625 0l0 13.359377l-1.765625 0zm4.683319 0l0 -9.671877l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953127l-1.640625 0l0 -5.890627q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.281252l-1.640625 0zm9.719452 -2.890627l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.7187519 -1.375 1.1250019q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.7812519 -1.25 -2.328127zm13.5625 1.421875l0.234375 1.4531269q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.4687519 -0.203125 -1.9375019l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.917694 0.28125q-0.921875 0.7656269 -1.765625 1.0937519q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.7812519 -0.859375 -1.9843769q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.5937519 0.40625 1.1562519l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875019zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.203827 4.859377l0 -9.671877l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953127l-1.640625 0l0 -5.890627q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.281252l-1.640625 0zm16.688232 -3.546877l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609377q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.2968769q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm9.640625 0.4375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.312502q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.2968769q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.90027 52.889763l139.37009 0l0 56.598427l-139.37009 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.90027 52.889763l139.37009 0l0 56.598427l-139.37009 0z" fill-rule="evenodd"/><path fill="#000000" d="m369.50748 82.893974l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm8.062012 0l4.0625 -5.46875l-3.578125 -5.015625l1.65625 0l1.890625 2.6875q0.59375 0.828125 0.84375 1.28125q0.359375 -0.5625 0.84375 -1.1875l2.109375 -2.78125l1.5 0l-3.6875 4.9375l3.984375 5.546875l-1.71875 0l-2.640625 -3.75q-0.21875 -0.3125 -0.46875 -0.6875q-0.34375 0.5625 -0.5 0.78125l-2.625 3.65625l-1.671875 0zm15.166229 0l-1.28125 0l0 -8.203125q-0.46875 0.4375 -1.21875 0.890625q-0.75 0.4375 -1.359375 0.65625l0 -1.25q1.078125 -0.5 1.890625 -1.21875q0.8125 -0.734375 1.140625 -1.40625l0.828125 0l0 10.53125zm10.072968 -1.234375l0 1.234375l-6.9375 0q-0.015625 -0.46875 0.15625 -0.890625q0.265625 -0.71875 0.84375 -1.40625q0.59375 -0.6875 1.6875 -1.578125q1.71875 -1.40625 2.3125 -2.21875q0.609375 -0.828125 0.609375 -1.5625q0 -0.765625 -0.5625 -1.28125q-0.546875 -0.53125 -1.421875 -0.53125q-0.921875 0 -1.484375 0.5625q-0.5625 0.5625 -0.5625 1.546875l-1.328125 -0.140625q0.140625 -1.484375 1.015625 -2.25q0.890625 -0.78125 2.390625 -0.78125q1.515625 0 2.390625 0.84375q0.875 0.828125 0.875 2.0625q0 0.640625 -0.265625 1.25q-0.25 0.59375 -0.84375 1.265625q-0.59375 0.671875 -1.984375 1.859375q-1.15625 0.96875 -1.484375 1.3125q-0.328125 0.34375 -0.546875 0.703125l5.140625 0zm1.385498 -1.53125l1.296875 -0.171875q0.21875 1.09375 0.75 1.578125q0.53125 0.484375 1.296875 0.484375q0.90625 0 1.53125 -0.625q0.640625 -0.640625 0.640625 -1.5625q0 -0.890625 -0.59375 -1.46875q-0.578125 -0.578125 -1.46875 -0.578125q-0.359375 0 -0.90625 0.140625l0.140625 -1.125q0.125 0.015625 0.203125 0.015625q0.828125 0 1.484375 -0.421875q0.65625 -0.4375 0.65625 -1.34375q0 -0.703125 -0.484375 -1.15625q-0.46875 -0.46875 -1.234375 -0.46875q-0.75 0 -1.25 0.46875q-0.5 0.46875 -0.640625 1.421875l-1.28125 -0.234375q0.234375 -1.296875 1.0625 -2.0q0.84375 -0.71875 2.09375 -0.71875q0.859375 0 1.578125 0.375q0.71875 0.359375 1.09375 1.0q0.390625 0.640625 0.390625 1.34375q0 0.6875 -0.375 1.25q-0.359375 0.546875 -1.0625 0.875q0.921875 0.21875 1.4375 0.90625q0.515625 0.671875 0.515625 1.6875q0 1.375 -1.0 2.328125q-1.0 0.953125 -2.53125 0.953125q-1.390625 0 -2.296875 -0.8125q-0.90625 -0.828125 -1.046875 -2.140625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.89764 157.89842l140.56693 0l0 56.59842l-140.56693 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.89764 157.89842l140.56693 0l0 56.59842l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m370.23578 187.90263l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm11.828278 0l0 -4.4375l-4.046875 -6.046875l1.6875 0l2.0625 3.15625q0.578125 0.890625 1.0625 1.78125q0.484375 -0.828125 1.15625 -1.859375l2.03125 -3.078125l1.609375 0l-4.1875 6.046875l0 4.4375l-1.375 0zm10.416229 0l0 -2.515625l-4.546875 0l0 -1.171875l4.78125 -6.796875l1.0625 0l0 6.796875l1.40625 0l0 1.171875l-1.40625 0l0 2.515625l-1.296875 0zm0 -3.6875l0 -4.734375l-3.28125 4.734375l3.28125 0zm4.0260925 0.9375l1.34375 -0.109375q0.15625 0.984375 0.703125 1.484375q0.546875 0.5 1.328125 0.5q0.921875 0 1.5625 -0.703125q0.65625 -0.703125 0.65625 -1.859375q0 -1.109375 -0.625 -1.734375q-0.625 -0.640625 -1.625 -0.640625q-0.625 0 -1.125 0.28125q-0.5 0.28125 -0.78125 0.734375l-1.203125 -0.15625l1.015625 -5.390625l5.21875 0l0 1.21875l-4.1875 0l-0.578125 2.828125q0.953125 -0.65625 1.984375 -0.65625q1.375 0 2.3125 0.953125q0.953125 0.953125 0.953125 2.4375q0 1.4375 -0.828125 2.46875q-1.015625 1.265625 -2.75 1.265625q-1.4375 0 -2.34375 -0.796875q-0.90625 -0.796875 -1.03125 -2.125zm14.838623 -5.171875l-1.28125 0.09375q-0.171875 -0.75 -0.484375 -1.09375q-0.53125 -0.546875 -1.296875 -0.546875q-0.609375 0 -1.078125 0.34375q-0.609375 0.4375 -0.96875 1.296875q-0.34375 0.84375 -0.359375 2.421875q0.46875 -0.71875 1.140625 -1.0625q0.671875 -0.34375 1.40625 -0.34375q1.296875 0 2.203125 0.953125q0.90625 0.953125 0.90625 2.453125q0 0.984375 -0.4375 1.84375q-0.421875 0.84375 -1.171875 1.296875q-0.734375 0.4375 -1.6875 0.4375q-1.609375 0 -2.625 -1.171875q-1.015625 -1.1875 -1.015625 -3.90625q0 -3.046875 1.125 -4.421875q0.984375 -1.203125 2.640625 -1.203125q1.234375 0 2.03125 0.703125q0.796875 0.6875 0.953125 1.90625zm-5.265625 4.515625q0 0.671875 0.28125 1.28125q0.28125 0.609375 0.78125 0.9375q0.515625 0.3125 1.078125 0.3125q0.8125 0 1.390625 -0.65625q0.59375 -0.671875 0.59375 -1.796875q0 -1.09375 -0.578125 -1.71875q-0.578125 -0.625 -1.453125 -0.625q-0.875 0 -1.484375 0.625q-0.609375 0.625 -0.609375 1.640625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.90027 261.96118l140.56693 0l0 56.59842l-140.56693 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.90027 261.96118l140.56693 0l0 56.59842l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m370.5174 291.9654l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm8.296387 0l0 -1.28125l5.375 -6.734375q0.5625 -0.703125 1.078125 -1.234375l-5.84375 0l0 -1.234375l7.515625 0l0 1.234375l-5.890625 7.28125l-0.640625 0.734375l6.703125 0l0 1.234375l-8.296875 0zm9.343231 -9.125l0 -1.234375l6.796875 0l0 1.0q-1.0 1.078125 -1.984375 2.84375q-0.984375 1.765625 -1.515625 3.625q-0.390625 1.328125 -0.5 2.890625l-1.328125 0q0.03125 -1.234375 0.484375 -2.984375q0.46875 -1.765625 1.34375 -3.390625q0.875 -1.625 1.84375 -2.75l-5.140625 0zm10.057373 3.4375q-0.796875 -0.296875 -1.1875 -0.84375q-0.390625 -0.546875 -0.390625 -1.296875q0 -1.140625 0.8125 -1.921875q0.828125 -0.78125 2.203125 -0.78125q1.375 0 2.203125 0.796875q0.84375 0.796875 0.84375 1.9375q0 0.734375 -0.390625 1.28125q-0.375 0.53125 -1.15625 0.828125q0.96875 0.3125 1.46875 1.015625q0.5 0.703125 0.5 1.671875q0 1.34375 -0.953125 2.265625q-0.9375 0.90625 -2.5 0.90625q-1.546875 0 -2.5 -0.90625q-0.953125 -0.921875 -0.953125 -2.296875q0 -1.03125 0.515625 -1.71875q0.515625 -0.6875 1.484375 -0.9375zm-0.265625 -2.1875q0 0.75 0.484375 1.21875q0.484375 0.46875 1.25 0.46875q0.734375 0 1.203125 -0.46875q0.484375 -0.46875 0.484375 -1.140625q0 -0.71875 -0.5 -1.1875q-0.484375 -0.484375 -1.203125 -0.484375q-0.734375 0 -1.234375 0.46875q-0.484375 0.46875 -0.484375 1.125zm-0.40625 4.84375q0 0.5625 0.25 1.078125q0.265625 0.5 0.78125 0.796875q0.515625 0.28125 1.109375 0.28125q0.921875 0 1.515625 -0.59375q0.609375 -0.59375 0.609375 -1.515625q0 -0.9375 -0.625 -1.53125q-0.609375 -0.609375 -1.546875 -0.609375q-0.90625 0 -1.5 0.609375q-0.59375 0.59375 -0.59375 1.484375zm7.0260925 0.609375l1.25 -0.125q0.15625 0.875 0.59375 1.28125q0.4375 0.390625 1.140625 0.390625q0.59375 0 1.03125 -0.265625q0.453125 -0.28125 0.734375 -0.734375q0.296875 -0.453125 0.484375 -1.21875q0.1875 -0.78125 0.1875 -1.59375q0 -0.078125 0 -0.25q-0.390625 0.609375 -1.0625 1.0q-0.65625 0.375 -1.4375 0.375q-1.3125 0 -2.21875 -0.9375q-0.890625 -0.953125 -0.890625 -2.484375q0 -1.609375 0.9375 -2.578125q0.9375 -0.96875 2.359375 -0.96875q1.03125 0 1.875 0.546875q0.84375 0.546875 1.28125 1.578125q0.4375 1.015625 0.4375 2.953125q0 2.0 -0.4375 3.203125q-0.421875 1.1875 -1.296875 1.8125q-0.859375 0.609375 -2.015625 0.609375q-1.234375 0 -2.015625 -0.671875q-0.78125 -0.6875 -0.9375 -1.921875zm5.28125 -4.640625q0 -1.109375 -0.59375 -1.75q-0.59375 -0.65625 -1.421875 -0.65625q-0.859375 0 -1.5 0.703125q-0.625 0.703125 -0.625 1.8125q0 1.0 0.59375 1.640625q0.609375 0.625 1.5 0.625q0.890625 0 1.46875 -0.625q0.578125 -0.640625 0.578125 -1.75z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 176.44095" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l79.026184 170.99445" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m335.87854 285.50632l3.4031677 3.4264832l-0.40444946 -4.812378z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m661.33215 6.0367227l140.5669 0l0 33.51181l-140.5669 0z" fill-rule="evenodd"/><path fill="#000000" d="m670.3009 32.956722l5.125 -13.359377l1.90625 0l5.46875 13.359377l-2.015625 0l-1.546875 -4.046877l-5.59375 0l-1.46875 4.046877l-1.875 0zm3.859375 -5.484377l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm16.162292 1.9375l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609377q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.2968769q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm6.59375 2.078125l0.234375 1.4531269q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.4687519 -0.203125 -1.9375019l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm1.6052246 -10.0l0 -1.890625l1.640625 0l0 1.890625l-1.640625 0zm0 11.468752l0 -9.671877l1.640625 0l0 9.671877l-1.640625 0zm3.5354004 -4.843752q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.6562519q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.2968769q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.297607 4.843752l0 -9.671877l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953127l-1.640625 0l0 -5.890627q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.281252l-1.640625 0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m637.4121 157.89842l139.37012 0l0 56.59842l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m637.4121 157.89842l139.37012 0l0 56.59842l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m647.36523 178.41843l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m653.4746 189.4028l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm6.3867188 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm9.949219 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm5.453125 -2.390625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm7.0996094 -2.28125l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm1.546875 -0.828125q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125z" fill-rule="nonzero"/><path fill="#000000" d="m651.00586 199.41843l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m695.75977 195.55515l8.003906 0l0 13.798828l-8.003906 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m700.57227 206.41843l-1.765625 0l0.703125 -3.34375l-2.375 -5.25l1.890625 0l1.0625 2.421875q0.375 0.875 0.5 1.265625q0.21875 -0.375 0.515625 -0.8125l0.8125 -1.125l1.203125 -1.75l2.0625 0l-3.9375 5.40625l-0.671875 3.1875z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m703.7637 195.55515l20.021484 0l0 13.798828l-20.021484 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m705.18555 201.48093l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m729.0254 199.0278l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m695.75977 207.19843l28.02539 0l0 1.0800018l-28.02539 0l0 -1.0800018z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m637.41473 261.96167l139.37012 0l0 56.59842l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m637.41473 261.96167l139.37012 0l0 56.59842l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m647.36786 282.4817l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m653.47723 293.46606l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm0.6464844 -2.171875q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.970703 3.109375l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm4.2929688 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm6.3867188 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm9.949219 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm5.453125 -2.390625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm7.0996094 -2.28125l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm1.546875 -0.828125q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125z" fill-rule="nonzero"/><path fill="#000000" d="m651.0085 303.4817l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m695.7624 299.6184l7.330078 0l0 13.798828l-7.330078 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m696.05927 310.4817l0.28125 -1.359375l4.953125 -5.796875l-4.0 0l0.296875 -1.4375l6.1875 0l-0.25 1.34375l-5.0 5.84375q0.796875 -0.015625 0.921875 -0.015625q0.5625 0 1.546875 -0.015625l2.03125 0l-0.296875 1.4375l-6.671875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m703.09247 299.6184l20.021484 0l0 13.798828l-20.021484 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m704.51434 305.5442l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m728.3542 303.09106l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m695.7624 311.2617l27.351562 0l0 1.0799866l-27.351562 0l0 -1.0799866z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m480.46457 186.19763l156.94485 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m480.46457 186.19763l150.94485 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m631.4094 187.84937l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m479.27036 81.18898l158.1417 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m479.27036 81.18898l152.1417 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m631.41205 82.840706l4.538147 -1.6517258l-4.538147 -1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m480.4672 290.2604l156.94485 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m480.4672 290.2604l150.94485 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m631.41205 291.91214l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"/><path fill="#ffffff" d="m829.90027 157.89764l139.37006 0l0 56.59842l-139.37006 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m829.90027 157.89764l139.37006 0l0 56.59842l-139.37006 0z" fill-rule="evenodd"/><path fill="#000000" d="m862.00665 182.27686l0 -7.59375l1.15625 0l0 1.0625q0.34375 -0.5625 0.9375 -0.890625q0.609375 -0.34375 1.359375 -0.34375q0.84375 0 1.375 0.34375q0.546875 0.34375 0.765625 0.984375q0.90625 -1.328125 2.359375 -1.328125q1.125 0 1.734375 0.625q0.609375 0.625 0.609375 1.921875l0 5.21875l-1.28125 0l0 -4.78125q0 -0.78125 -0.125 -1.109375q-0.125 -0.34375 -0.453125 -0.546875q-0.328125 -0.21875 -0.78125 -0.21875q-0.796875 0 -1.328125 0.53125q-0.53125 0.53125 -0.53125 1.703125l0 4.421875l-1.28125 0l0 -4.9375q0 -0.859375 -0.3125 -1.28125q-0.3125 -0.4375 -1.03125 -0.4375q-0.546875 0 -1.015625 0.296875q-0.453125 0.28125 -0.671875 0.828125q-0.203125 0.546875 -0.203125 1.59375l0 3.9375l-1.28125 0zm12.14624 2.921875l-0.140625 -1.203125q0.421875 0.109375 0.734375 0.109375q0.4375 0 0.6875 -0.140625q0.265625 -0.140625 0.421875 -0.40625q0.125 -0.1875 0.390625 -0.953125q0.046875 -0.109375 0.125 -0.3125l-2.890625 -7.609375l1.390625 0l1.578125 4.390625q0.3125 0.84375 0.546875 1.765625q0.234375 -0.890625 0.53125 -1.734375l1.625 -4.421875l1.296875 0l-2.890625 7.71875q-0.46875 1.25 -0.734375 1.734375q-0.34375 0.625 -0.78125 0.921875q-0.4375 0.296875 -1.0625 0.296875q-0.375 0 -0.828125 -0.15625zm6.661499 -2.921875l0 -1.46875l1.46875 0l0 1.46875l-1.46875 0zm8.66571 -2.78125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm1.890625 -1.015625q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm16.582458 1.34375l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.182373 4.53125l0 -7.59375l1.15625 0l0 1.0625q0.34375 -0.5625 0.9375 -0.890625q0.609375 -0.34375 1.359375 -0.34375q0.84375 0 1.375 0.34375q0.546875 0.34375 0.765625 0.984375q0.90625 -1.328125 2.359375 -1.328125q1.125 0 1.734375 0.625q0.609375 0.625 0.609375 1.921875l0 5.21875l-1.28125 0l0 -4.78125q0 -0.78125 -0.125 -1.109375q-0.125 -0.34375 -0.453125 -0.546875q-0.328125 -0.21875 -0.78125 -0.21875q-0.796875 0 -1.328125 0.53125q-0.53125 0.53125 -0.53125 1.703125l0 4.421875l-1.28125 0l0 -4.9375q0 -0.859375 -0.3125 -1.28125q-0.3125 -0.4375 -1.03125 -0.4375q-0.546875 0 -1.015625 0.296875q-0.453125 0.28125 -0.671875 0.828125q-0.203125 0.546875 -0.203125 1.59375l0 3.9375l-1.28125 0zm17.161865 -0.9375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm3.307373 -5.203125l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm3.2249146 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0z" fill-rule="nonzero"/><path fill="#000000" d="m876.8267 198.01123l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125zm13.046875 -0.1875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.005615 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm5.21875 -9.015625l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm8.20929 -2.78125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm7.578125 0.328125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m776.78485 81.18898l53.102356 105.00787" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m776.78485 81.18898l50.394714 99.653564" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m825.70557 181.58794l3.5219116 3.3043365l-0.5739136 -4.7951202z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m776.7822 186.19763l53.102356 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m776.7822 186.19763l47.102356 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m823.8846 187.84937l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m776.78485 290.2609l53.102356 -104.063" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m776.78485 290.2609l50.375183 -98.71861" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m828.6313 192.29305l0.59143066 -4.792984l-3.5339355 3.2914581z" fill-rule="evenodd"/><path fill="#ffffff" d="m25.338583 342.32285l233.00789 0l0 105.00787l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.338583 342.32285l233.00789 0l0 105.00787l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m46.104206 365.5072l1.890625 0.46875q-0.59375 2.34375 -2.140625 3.578125q-1.546875 1.21875 -3.796875 1.21875q-2.3125 0 -3.765625 -0.9375q-1.4375 -0.953125 -2.203125 -2.734375q-0.75 -1.796875 -0.75 -3.84375q0 -2.234375 0.84375 -3.890625q0.859375 -1.671875 2.4375 -2.53125q1.578125 -0.875 3.46875 -0.875q2.15625 0 3.609375 1.09375q1.46875 1.09375 2.046875 3.078125l-1.859375 0.4375q-0.5 -1.5625 -1.453125 -2.265625q-0.9375 -0.71875 -2.375 -0.71875q-1.65625 0 -2.765625 0.796875q-1.109375 0.78125 -1.5625 2.125q-0.4375 1.328125 -0.4375 2.734375q0 1.828125 0.53125 3.203125q0.53125 1.359375 1.65625 2.03125q1.125 0.671875 2.421875 0.671875q1.59375 0 2.703125 -0.921875q1.109375 -0.921875 1.5 -2.71875zm3.3496094 -0.171875q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875zm9.966797 5.1875l0 -10.375l1.59375 0l0 1.484375q1.140625 -1.71875 3.2968788 -1.71875q0.9375 0 1.71875 0.34375q0.796875 0.328125 1.1875 0.875q0.390625 0.546875 0.546875 1.296875q0.09375 0.5 0.09375 1.71875l0 6.375l-1.765625 0l0 -6.3125q0 -1.078125 -0.203125 -1.609375q-0.203125 -0.53125 -0.734375 -0.84375q-0.515625 -0.3125 -1.21875 -0.3125q-1.125 0 -1.9375038 0.71875q-0.8125 0.703125 -0.8125 2.6875l0 5.671875l-1.765625 0zm11.123051 0l0 -10.375l1.59375 0l0 1.484375q1.140625 -1.71875 3.296875 -1.71875q0.9375 0 1.71875 0.34375q0.796875 0.328125 1.1875 0.875q0.390625 0.546875 0.546875 1.296875q0.09375 0.5 0.09375 1.71875l0 6.375l-1.765625 0l0 -6.3125q0 -1.078125 -0.203125 -1.609375q-0.203125 -0.53125 -0.734375 -0.84375q-0.515625 -0.3125 -1.21875 -0.3125q-1.125 0 -1.9375 0.71875q-0.8125 0.703125 -0.8125 2.6875l0 5.671875l-1.765625 0zm18.232422 -3.34375l1.8125 0.234375q-0.421875 1.578125 -1.59375 2.46875q-1.15625 0.875 -2.96875 0.875q-2.265625 0 -3.609375 -1.390625q-1.328125 -1.40625 -1.328125 -3.9375q0 -2.625 1.34375 -4.0625q1.34375 -1.453125 3.5 -1.453125q2.078125 0 3.390625 1.421875q1.328125 1.40625 1.328125 3.984375q0 0.15625 -0.015625 0.46875l-7.734375 0q0.09375 1.703125 0.96875 2.609375q0.875 0.90625 2.171875 0.90625q0.96875 0 1.640625 -0.5q0.6875 -0.515625 1.09375 -1.625zm-5.78125 -2.84375l5.796875 0q-0.109375 -1.296875 -0.65625 -1.953125q-0.84375 -1.015625 -2.1875 -1.015625q-1.203125 0 -2.03125 0.8125q-0.828125 0.796875 -0.921875 2.15625zm16.576172 2.390625l1.71875 0.21875q-0.28125 1.796875 -1.453125 2.8125q-1.15625 1.0 -2.859375 1.0q-2.125 0 -3.421875 -1.390625q-1.296875 -1.390625 -1.296875 -3.984375q0 -1.6875 0.546875 -2.9375q0.5625 -1.265625 1.703125 -1.890625q1.140625 -0.640625 2.484375 -0.640625q1.6875 0 2.75 0.859375q1.078125 0.859375 1.390625 2.421875l-1.71875 0.265625q-0.234375 -1.046875 -0.859375 -1.5625q-0.625 -0.53125 -1.5 -0.53125q-1.328125 0 -2.15625 0.953125q-0.828125 0.953125 -0.828125 3.0q0 2.09375 0.796875 3.046875q0.796875 0.9375 2.09375 0.9375q1.03125 0 1.71875 -0.625q0.703125 -0.640625 0.890625 -1.953125zm7.0625 2.21875l0.25 1.5625q-0.734375 0.15625 -1.328125 0.15625q-0.953125 0 -1.484375 -0.296875q-0.515625 -0.3125 -0.734375 -0.796875q-0.21875 -0.5 -0.21875 -2.078125l0 -5.96875l-1.28125 0l0 -1.375l1.28125 0l0 -2.5625l1.75 -1.0625l0 3.625l1.765625 0l0 1.375l-1.765625 0l0 6.0625q0 0.75 0.09375 0.96875q0.09375 0.203125 0.296875 0.34375q0.21875 0.125 0.609375 0.125q0.28125 0 0.765625 -0.078125zm1.0722656 -3.609375q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875zm9.951172 5.1875l0 -10.375l1.578125 0l0 1.578125q0.609375 -1.109375 1.125 -1.453125q0.515625 -0.359375 1.125 -0.359375q0.890625 0 1.8125 0.5625l-0.609375 1.640625q-0.640625 -0.390625 -1.28125 -0.390625q-0.578125 0 -1.046875 0.359375q-0.453125 0.34375 -0.65625 0.953125q-0.28125 0.9375 -0.28125 2.046875l0 5.4375l-1.765625 0zm11.560539 -4.296875l0 -1.765625l5.390625 0l0 1.765625l-5.390625 0zm12.888672 4.296875l0 -10.375l1.578125 0l0 1.453125q0.484375 -0.75 1.296875 -1.21875q0.8125 -0.46875 1.84375 -0.46875q1.15625 0 1.890625 0.484375q0.734375 0.46875 1.046875 1.328125q1.234375 -1.8125 3.203125 -1.8125q1.546875 0 2.375 0.859375q0.828125 0.859375 0.828125 2.625l0 7.125l-1.75 0l0 -6.53125q0 -1.0625 -0.171875 -1.515625q-0.171875 -0.46875 -0.625 -0.75q-0.4375 -0.28125 -1.046875 -0.28125q-1.09375 0 -1.828125 0.734375q-0.71875 0.71875 -0.71875 2.3125l0 6.03125l-1.75 0l0 -6.734375q0 -1.171875 -0.4375 -1.75q-0.421875 -0.59375 -1.40625 -0.59375q-0.734375 0 -1.375 0.390625q-0.625 0.390625 -0.90625 1.140625q-0.28125 0.75 -0.28125 2.171875l0 5.375l-1.765625 0zm16.582031 4.0l-0.1875 -1.65625q0.578125 0.15625 1.0 0.15625q0.59375 0 0.9375 -0.203125q0.359375 -0.1875 0.578125 -0.53125q0.171875 -0.265625 0.546875 -1.3125q0.046875 -0.15625 0.15625 -0.4375l-3.9375 -10.390625l1.890625 0l2.15625 6.015625q0.421875 1.140625 0.75 2.390625q0.3125 -1.203125 0.71875 -2.359375l2.21875 -6.046875l1.765625 0l-3.953125 10.546875q-0.625 1.71875 -0.984375 2.359375q-0.46875 0.875 -1.078125 1.265625q-0.59375 0.40625 -1.4375 0.40625q-0.515625 0 -1.140625 -0.203125zm9.09375 -4.0l0 -2.0l2.0 0l0 2.0l-2.0 0zm11.837891 -3.796875l1.71875 0.21875q-0.28125 1.796875 -1.453125 2.8125q-1.15625 1.0 -2.859375 1.0q-2.125 0 -3.421875 -1.390625q-1.296875 -1.390625 -1.296875 -3.984375q0 -1.6875 0.546875 -2.9375q0.5625 -1.265625 1.703125 -1.890625q1.140625 -0.640625 2.484375 -0.640625q1.6875 0 2.75 0.859375q1.078125 0.859375 1.390625 2.421875l-1.71875 0.265625q-0.234375 -1.046875 -0.859375 -1.5625q-0.625 -0.53125 -1.5 -0.53125q-1.328125 0 -2.15625 0.953125q-0.828125 0.953125 -0.828125 3.0q0 2.09375 0.796875 3.046875q0.796875 0.9375 2.09375 0.9375q1.03125 0 1.71875 -0.625q0.703125 -0.640625 0.890625 -1.953125zm2.578125 -1.390625q0 -2.875 1.59375 -4.265625q1.34375 -1.15625 3.265625 -1.15625q2.140625 0 3.484375 1.40625q1.359375 1.40625 1.359375 3.875q0 2.0 -0.59375 3.15625q-0.59375 1.140625 -1.75 1.78125q-1.140625 0.625 -2.5 0.625q-2.1875 0 -3.53125 -1.390625q-1.328125 -1.40625 -1.328125 -4.03125zm1.796875 0q0 2.0 0.859375 2.984375q0.875 0.984375 2.203125 0.984375q1.3125 0 2.171875 -0.984375q0.875 -1.0 0.875 -3.046875q0 -1.921875 -0.875 -2.90625q-0.875 -1.0 -2.171875 -1.0q-1.328125 0 -2.203125 1.0q-0.859375 0.984375 -0.859375 2.96875z" fill-rule="nonzero"/><path fill="#000000" d="m53.94483 392.84283l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.5156212 -0.25 1.0624962 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.0937462 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.8613243 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.3281288 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875038 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.6718788 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5000038 0 -0.9062538 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533207 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm2.1933594 -4.15625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m130.7292 392.84283l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m53.41358 409.23346l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4374962 -0.21875 0.9218712 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.9843712 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.9218712 0 1.4843712 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.4062462 0 -0.7499962 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.2988243 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.3281288 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875038 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.6718788 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5000038 0 -0.9062538 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439457 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm2.1933594 -4.15625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m131.18233 404.3897l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m58.179203 419.71783q-1.1093712 1.265625 -2.2812462 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4374962 -0.21875 0.7343712 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.5332031 -1.0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.7031288 0 1.0468788 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625038 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.1718788 0 1.7812538 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625038 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.2187538 0.53125 1.5312538 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.3750038 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.468754 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm3.9960938 0l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm10.861328 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.0800781 3.15625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.574219 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm6.517578 -1.359375l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m130.7292 420.84283l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm10.640625 -3.53125q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.5332031 -1.0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.46875 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0z" fill-rule="nonzero"/><path fill="#000000" d="m53.41358 437.23346l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4374962 -0.21875 0.9218712 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.9843712 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.9218712 0 1.4843712 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.4062462 0 -0.7499962 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm9.298828 1.765625q-0.546875 0.484375 -1.0625038 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0000038 -0.046875 1.4218788 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.6718788 0 -1.0937538 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.7968788 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.8437538 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.4843788 -0.28125 0.7656288 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.1894531 1.03125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm6.0 0l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm7.078125 2.125l-0.640625 -6.21875l1.015625 0l0.28125 2.796875l0.109375 1.5625q0.015625 0.171875 0.03125 0.703125q0.1875 -0.59375 0.296875 -0.90625q0.125 -0.328125 0.40625 -0.921875l1.46875 -3.234375l1.15625 0l0.203125 3.109375q0.046875 0.703125 0.0625 1.890625q0.296875 -0.78125 0.953125 -2.1875l1.34375 -2.8125l1.0625 0l-3.046875 6.21875l-1.09375 0l-0.234375 -3.65625q-0.03125 -0.328125 -0.046875 -1.3125q-0.234375 0.625 -0.5625 1.34375l-1.640625 3.625l-1.125 0zm7.6816406 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm8.183594 -0.90625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm6.720703 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm-1.046875 5.015625l0.25 -1.203125l1.203125 0l-0.265625 1.203125l-1.1875 0z" fill-rule="nonzero"/><path fill="#000000" d="m135.02608 432.5772l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.71875 2.265625l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm10.861328 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm2.0957031 3.15625l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm6.611328 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm9.970703 0.640625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.574219 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625z" fill-rule="nonzero"/><path fill="#666666" d="m152.55838 267.70898l0 0c0 -1.800354 1.3678284 -3.2598267 3.0551147 -3.2598267l0 0c0.8102722 0 1.5873566 0.34344482 2.1602936 0.95477295c0.5729523 0.61135864 0.89482117 1.4404907 0.89482117 2.3050537l0 0c0 1.8003845 -1.3678131 3.2598572 -3.0551147 3.2598572l0 0c-1.6872864 0 -3.0551147 -1.4594727 -3.0551147 -3.2598572z" fill-rule="evenodd"/><path fill="#666666" d="m639.8609 292.85303l0 0c0 -1.8003845 1.3677979 -3.2598572 3.0551147 -3.2598572l0 0c0.8102417 0 1.5873413 0.34344482 2.1602783 0.95480347c0.572937 0.6113281 0.8948364 1.4404907 0.8948364 2.3050537l0 0c0 1.800354 -1.3677979 3.2598267 -3.0551147 3.2598267l0 0c-1.6873169 0 -3.0551147 -1.4594727 -3.0551147 -3.2598267z" fill-rule="evenodd"/><path fill="#666666" d="m639.8609 189.4567l0 0c0 -1.8003693 1.3677979 -3.259842 3.0551147 -3.259842l0 0c0.8102417 0 1.5873413 0.34344482 2.1602783 0.9547882c0.572937 0.6113281 0.8948364 1.4404907 0.8948364 2.3050537l0 0c0 1.800354 -1.3677979 3.259842 -3.0551147 3.259842l0 0c-1.6873169 0 -3.0551147 -1.4594879 -3.0551147 -3.259842z" fill-rule="evenodd"/><path fill="#666666" d="m639.8609 83.031494l0 0c0 -1.8003616 1.3677979 -3.259842 3.0551147 -3.259842l0 0c0.8102417 0 1.5873413 0.34344482 2.1602783 0.9547882c0.572937 0.61133575 0.8948364 1.4404907 0.8948364 2.3050537l0 0c0 1.8003616 -1.3677979 3.259842 -3.0551147 3.259842l0 0c-1.6873169 0 -3.0551147 -1.4594803 -3.0551147 -3.259842z" fill-rule="evenodd"/><path fill="#999999" d="m244.2231 392.55905l0 0c0 -1.800354 1.3678284 -3.2598267 3.0551147 -3.2598267l0 0c0.8102722 0 1.5873566 0.34344482 2.1602936 0.95477295c0.5729523 0.6113281 0.89482117 1.4404907 0.89482117 2.3050537l0 0c0 1.800354 -1.3678131 3.2598572 -3.0551147 3.2598572l0 0c-1.6872864 0 -3.0551147 -1.4595032 -3.0551147 -3.2598572z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m158.66861 267.70898c44.299225 0 88.598434 60.787415 88.598434 121.57483" fill-rule="evenodd"/><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m158.66861 267.70898c44.299225 0 88.598434 60.787415 88.598434 121.57483" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m250.33333 392.55905c196.29921 0 392.59845 -48.22046 392.59845 -96.44095" fill-rule="evenodd"/><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m250.33333 392.55905c196.29921 0 392.59845 -48.22046 392.59845 -96.44095" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m250.33333 392.55905c195.2126 0 390.42523 -100.39371 390.42523 -200.7874" fill-rule="evenodd"/><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m250.33333 392.55905c195.2126 0 390.42523 -100.39371 390.42523 -200.7874" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m250.33333 392.55905c196.29921 0 392.59845 -153.13385 392.59845 -306.2677" fill-rule="evenodd"/><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m250.33333 392.55905c196.29921 0 392.59845 -153.13385 392.59845 -306.2677" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m844.39624 4.631458l111.590515 0l0 33.51181l-111.590515 0z" fill-rule="evenodd"/><path fill="#000000" d="m855.1306 31.551456l0 -13.359375l1.765625 0l0 13.359375l-1.765625 0zm4.6832886 0l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0zm13.953857 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm8.230164 -1.640625l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm8.828857 6.5625l1.59375 0.234375q0.109375 0.75 0.5625 1.078125q0.609375 0.453125 1.671875 0.453125q1.140625 0 1.75 -0.453125q0.625 -0.453125 0.84375 -1.265625q0.125 -0.5 0.109375 -2.109375q-1.0625 1.265625 -2.671875 1.265625q-2.0 0 -3.09375 -1.4375q-1.09375 -1.4375 -1.09375 -3.453125q0 -1.390625 0.5 -2.5625q0.515625 -1.171875 1.453125 -1.796875q0.953125 -0.640625 2.25 -0.640625q1.703125 0 2.8125 1.375l0 -1.15625l1.515625 0l0 8.359375q0 2.265625 -0.46875 3.203125q-0.453125 0.9375 -1.453125 1.484375q-0.984375 0.546875 -2.453125 0.546875q-1.71875 0 -2.796875 -0.78125q-1.0625 -0.765625 -1.03125 -2.34375zm1.359375 -5.8125q0 1.90625 0.75 2.78125q0.765625 0.875 1.90625 0.875q1.125 0 1.890625 -0.859375q0.765625 -0.875 0.765625 -2.734375q0 -1.78125 -0.796875 -2.671875q-0.78125 -0.90625 -1.890625 -0.90625q-1.09375 0 -1.859375 0.890625q-0.765625 0.875 -0.765625 2.625zm9.313232 5.015625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm12.5407715 -1.1875q-0.921875 0.765625 -1.765625 1.09375q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.78125 -0.859375 -1.984375q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.59375 0.40625 1.15625l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm7.7819824 3.390625l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm1.6051636 -10.0l0 -1.890625l1.640625 0l0 1.890625l-1.640625 0zm0 11.46875l0 -9.671875l1.640625 0l0 9.671875l-1.640625 0zm3.5354614 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.297607 4.84375l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0z" fill-rule="nonzero"/></g></svg> \ No newline at end of file diff --git a/docs/user/alerting/images/alert-flyout-action-details.png b/docs/user/alerting/images/alert-flyout-action-details.png new file mode 100644 index 0000000000000..06287ed1837d2 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-details.png differ diff --git a/docs/user/alerting/images/alert-flyout-action-type-selection.png b/docs/user/alerting/images/alert-flyout-action-type-selection.png new file mode 100644 index 0000000000000..e4448ca5f3fcd Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-type-selection.png differ diff --git a/docs/user/alerting/images/alert-flyout-action-variables.png b/docs/user/alerting/images/alert-flyout-action-variables.png new file mode 100644 index 0000000000000..73fc1fe9dea63 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-action-variables.png differ diff --git a/docs/user/alerting/images/alert-flyout-add-action.png b/docs/user/alerting/images/alert-flyout-add-action.png new file mode 100644 index 0000000000000..159dbd5c1e449 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-add-action.png differ diff --git a/docs/user/alerting/images/alert-flyout-alert-conditions.png b/docs/user/alerting/images/alert-flyout-alert-conditions.png new file mode 100644 index 0000000000000..f3e8f42ff0f37 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-alert-conditions.png differ diff --git a/docs/user/alerting/images/alert-flyout-alert-type-selection.png b/docs/user/alerting/images/alert-flyout-alert-type-selection.png new file mode 100644 index 0000000000000..a0a25dc5f1bbc Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-alert-type-selection.png differ diff --git a/docs/user/alerting/images/alert-flyout-general-details.png b/docs/user/alerting/images/alert-flyout-general-details.png new file mode 100644 index 0000000000000..db56c16c1c308 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-general-details.png differ diff --git a/docs/user/alerting/images/alert-flyout-sections.png b/docs/user/alerting/images/alert-flyout-sections.png new file mode 100644 index 0000000000000..8fa4bfffe39a3 Binary files /dev/null and b/docs/user/alerting/images/alert-flyout-sections.png differ diff --git a/docs/user/alerting/images/alert-instances.svg b/docs/user/alerting/images/alert-instances.svg new file mode 100644 index 0000000000000..b7b0bd4996053 --- /dev/null +++ b/docs/user/alerting/images/alert-instances.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 722.8110236220473 331.005249343832" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l722.81104 0l0 331.00525l-722.81104 0l0 -331.00525z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l722.81104 0l0 331.00525l-722.81104 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m13.120735 52.889763l268.7874 0l0 266.61417l-268.7874 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m13.120735 52.889763l268.7874 0l0 266.61417l-268.7874 0z" fill-rule="evenodd"/><path fill="#000000" d="m22.089485 79.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 97.062996l233.00789 0l0 33.511803l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 97.062996l233.00789 0l0 33.511803l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m43.750084 117.40737l1.515625 0.375q-0.46875 1.875 -1.71875 2.859375q-1.234375 0.984375 -3.015625 0.984375q-1.859375 0 -3.015625 -0.75q-1.15625 -0.765625 -1.765625 -2.1875q-0.609375 -1.4375 -0.609375 -3.078125q0 -1.796875 0.6875 -3.125q0.6875 -1.328125 1.9375 -2.015625q1.265625 -0.703125 2.78125 -0.703125q1.71875 0 2.890625 0.875q1.171875 0.875 1.640625 2.46875l-1.5 0.34375q-0.390625 -1.25 -1.15625 -1.8125q-0.75 -0.578125 -1.90625 -0.578125q-1.3125 0 -2.203125 0.640625q-0.890625 0.625 -1.25 1.703125q-0.359375 1.0625 -0.359375 2.1875q0 1.46875 0.421875 2.5625q0.4375 1.078125 1.328125 1.625q0.90625 0.53125 1.953125 0.53125q1.265625 0 2.140625 -0.734375q0.890625 -0.734375 1.203125 -2.171875zm2.6796875 -0.140625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm14.2734375 0l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm7.9609375 -5.703125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm6.6171875 -1.265625l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0z" fill-rule="nonzero"/><path fill="#000000" d="m136.46883 120.39175q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm4.8671875 4.203125l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm5.828125 0.75l1.4375 0.140625q-0.015625 0.484375 0.109375 0.71875q0.140625 0.25 0.421875 0.375q0.390625 0.171875 1.0 0.171875q1.28125 0 1.84375 -0.65625q0.359375 -0.453125 0.671875 -1.953125l0.140625 -0.671875q-1.09375 1.125 -2.34375 1.125q-1.25 0 -2.109375 -0.921875q-0.84375 -0.9375 -0.84375 -2.625q0 -1.40625 0.671875 -2.578125q0.671875 -1.171875 1.59375 -1.765625q0.921875 -0.59375 1.890625 -0.59375q1.640625 0 2.515625 1.546875l0.28125 -1.359375l1.296875 0l-1.671875 8.0q-0.265625 1.328125 -0.71875 2.0625q-0.4375 0.75 -1.234375 1.15625q-0.796875 0.40625 -1.828125 0.40625q-1.0 0 -1.734375 -0.265625q-0.71875 -0.25 -1.078125 -0.75q-0.34375 -0.5 -0.34375 -1.140625q0 -0.1875 0.03125 -0.421875zm1.765625 -4.421875q0 0.84375 0.171875 1.28125q0.234375 0.59375 0.65625 0.921875q0.4375 0.3125 0.96875 0.3125q0.703125 0 1.390625 -0.484375q0.6875 -0.5 1.109375 -1.515625q0.421875 -1.03125 0.421875 -1.953125q0 -1.03125 -0.5625 -1.625q-0.5625 -0.609375 -1.40625 -0.609375q-0.515625 0 -1.0 0.28125q-0.484375 0.265625 -0.90625 0.84375q-0.40625 0.5625 -0.625 1.359375q-0.21875 0.78125 -0.21875 1.1875zm20.78125 -0.359375l1.515625 0.203125q-0.71875 1.984375 -2.09375 3.015625q-1.375 1.015625 -3.09375 1.015625q-2.078125 0 -3.3125 -1.28125q-1.21875 -1.28125 -1.21875 -3.65625q0 -3.09375 1.859375 -5.109375q1.65625 -1.8125 4.125 -1.8125q1.8125 0 2.9375 0.984375q1.140625 0.96875 1.3125 2.625l-1.421875 0.125q-0.234375 -1.234375 -0.9375 -1.84375q-0.703125 -0.625 -1.828125 -0.625q-2.09375 0 -3.390625 1.875q-1.125 1.609375 -1.125 3.8125q0 1.765625 0.859375 2.703125q0.875 0.921875 2.265625 0.921875q1.1875 0 2.140625 -0.765625q0.96875 -0.78125 1.40625 -2.1875zm2.5859375 4.03125l2.40625 -11.453125l4.78125 0q1.234375 0 1.859375 0.28125q0.625 0.28125 1.03125 0.984375q0.40625 0.6875 0.40625 1.546875q0 0.703125 -0.296875 1.4375q-0.28125 0.734375 -0.734375 1.21875q-0.4375 0.46875 -0.890625 0.71875q-0.453125 0.234375 -0.96875 0.359375q-1.09375 0.25 -2.21875 0.25l-2.875 0l-0.96875 4.65625l-1.53125 0zm2.78125 -5.953125l2.515625 0q1.46875 0 2.15625 -0.3125q0.6875 -0.3125 1.09375 -0.953125q0.421875 -0.65625 0.421875 -1.390625q0 -0.5625 -0.21875 -0.90625q-0.21875 -0.359375 -0.625 -0.53125q-0.390625 -0.171875 -1.515625 -0.171875l-2.9375 0l-0.890625 4.265625zm10.375 -5.5l1.53125 0l-1.46875 7.03125q-0.171875 0.875 -0.171875 1.296875q0 0.921875 0.71875 1.484375q0.734375 0.5625 1.828125 0.5625q0.875 0 1.625 -0.390625q0.765625 -0.40625 1.203125 -1.1875q0.4375 -0.78125 0.78125 -2.5l1.328125 -6.296875l1.53125 0l-1.40625 6.71875q-0.359375 1.71875 -0.953125 2.71875q-0.578125 1.0 -1.625 1.609375q-1.03125 0.609375 -2.40625 0.609375q-1.296875 0 -2.25 -0.421875q-0.9375 -0.4375 -1.421875 -1.1875q-0.46875 -0.765625 -0.46875 -1.734375q0 -0.59375 0.328125 -2.0625l1.296875 -6.25zm21.859375 6.4375l-7.59375 3.25l0 -1.40625l6.015625 -2.484375l-6.015625 -2.46875l0 -1.40625l7.59375 3.203125l0 1.3125zm5.8984375 1.25q0 -1.453125 0.421875 -2.953125q0.4375 -1.5 0.96875 -2.390625q0.53125 -0.90625 1.09375 -1.40625q0.578125 -0.515625 1.125 -0.75q0.5625 -0.234375 1.234375 -0.234375q1.3125 0 2.1875 0.984375q0.875 0.96875 0.875 2.8125q0 1.890625 -0.609375 3.75q-0.71875 2.203125 -2.0 3.3125q-0.984375 0.84375 -2.234375 0.84375q-1.296875 0 -2.1875 -1.015625q-0.875 -1.015625 -0.875 -2.953125zm1.359375 0.359375q0 1.0625 0.359375 1.65625q0.46875 0.8125 1.40625 0.8125q0.828125 0 1.5 -0.734375q0.96875 -1.046875 1.453125 -3.0625q0.484375 -2.03125 0.484375 -3.3125q0 -1.234375 -0.46875 -1.78125q-0.46875 -0.546875 -1.25 -0.546875q-0.5625 0 -1.046875 0.296875q-0.484375 0.28125 -0.9375 0.984375q-0.625 1.0 -1.09375 2.96875q-0.40625 1.6875 -0.40625 2.71875zm7.3203125 3.40625l0.34375 -1.609375l1.59375 0l-0.34375 1.609375l-1.59375 0zm4.6015625 -2.625l1.328125 -0.140625q0.140625 0.96875 0.546875 1.375q0.421875 0.40625 0.984375 0.40625q0.8125 0 1.515625 -0.703125q1.015625 -1.03125 1.5 -2.96875q-0.703125 0.53125 -1.265625 0.765625q-0.546875 0.21875 -1.125 0.21875q-1.046875 0 -1.875 -0.703125q-1.09375 -0.90625 -1.09375 -2.625q0 -1.9375 1.265625 -3.3125q1.09375 -1.1875 2.671875 -1.1875q1.421875 0 2.359375 1.046875q0.9375 1.046875 0.9375 2.96875q0 1.875 -0.625 3.6875q-0.75 2.140625 -2.015625 3.15625q-1.03125 0.84375 -2.3125 0.84375q-1.1875 0 -1.953125 -0.734375q-0.75 -0.75 -0.84375 -2.09375zm1.890625 -4.53125q0 1.078125 0.5625 1.71875q0.578125 0.640625 1.375 0.640625q0.578125 0 1.15625 -0.390625q0.578125 -0.40625 0.984375 -1.203125q0.421875 -0.796875 0.421875 -1.625q0 -0.65625 -0.28125 -1.21875q-0.265625 -0.5625 -0.734375 -0.84375q-0.46875 -0.296875 -0.953125 -0.296875q-0.46875 0 -0.921875 0.25q-0.453125 0.25 -0.84375 0.734375q-0.390625 0.484375 -0.578125 1.125q-0.1875 0.625 -0.1875 1.109375z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 144.07611l233.00789 0l0 39.3071l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 144.07611l233.00789 0l0 39.3071l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m35.062584 164.74861l1.4375 -0.125q0.09375 0.859375 0.46875 1.421875q0.375 0.546875 1.15625 0.890625q0.78125 0.328125 1.75 0.328125q0.875 0 1.53125 -0.25q0.671875 -0.265625 0.984375 -0.703125q0.328125 -0.453125 0.328125 -0.984375q0 -0.546875 -0.3125 -0.9375q-0.3125 -0.40625 -1.03125 -0.6875q-0.453125 -0.171875 -2.03125 -0.546875q-1.578125 -0.390625 -2.21875 -0.71875q-0.8125 -0.4375 -1.21875 -1.0625q-0.40625 -0.640625 -0.40625 -1.4375q0 -0.859375 0.484375 -1.609375q0.5 -0.765625 1.4375 -1.15625q0.953125 -0.390625 2.109375 -0.390625q1.28125 0 2.25 0.421875q0.96875 0.40625 1.484375 1.203125q0.53125 0.796875 0.578125 1.796875l-1.453125 0.109375q-0.125 -1.078125 -0.796875 -1.625q-0.671875 -0.5625 -2.0 -0.5625q-1.375 0 -2.0 0.5q-0.625 0.5 -0.625 1.21875q0 0.609375 0.4375 1.015625q0.4375 0.390625 2.28125 0.8125q1.859375 0.421875 2.546875 0.734375q1.0 0.453125 1.46875 1.171875q0.484375 0.703125 0.484375 1.625q0 0.90625 -0.53125 1.71875q-0.515625 0.8125 -1.5 1.265625q-0.984375 0.453125 -2.203125 0.453125q-1.5625 0 -2.609375 -0.453125q-1.046875 -0.46875 -1.65625 -1.375q-0.59375 -0.90625 -0.625 -2.0625zm16.421875 0.640625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm2.59375 3.046875l0 -11.453125l1.40625 0l0 4.109375q0.984375 -1.140625 2.484375 -1.140625q0.921875 0 1.59375 0.359375q0.6875 0.359375 0.96875 1.0q0.296875 0.640625 0.296875 1.859375l0 5.265625l-1.40625 0l0 -5.265625q0 -1.046875 -0.453125 -1.53125q-0.453125 -0.484375 -1.296875 -0.484375q-0.625 0 -1.171875 0.328125q-0.546875 0.328125 -0.78125 0.890625q-0.234375 0.546875 -0.234375 1.515625l0 4.546875l-1.40625 0zm14.5703125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875zm13.2109375 4.953125l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm13.3984375 4.140625l0 -1.21875q-0.96875 1.40625 -2.640625 1.40625q-0.734375 0 -1.375 -0.28125q-0.625 -0.28125 -0.9375 -0.703125q-0.3125 -0.4375 -0.4375 -1.046875q-0.078125 -0.421875 -0.078125 -1.3125l0 -5.140625l1.40625 0l0 4.59375q0 1.109375 0.078125 1.484375q0.140625 0.5625 0.5625 0.875q0.4375 0.3125 1.0625 0.3125q0.640625 0 1.1875 -0.3125q0.5625 -0.328125 0.78125 -0.890625q0.234375 -0.5625 0.234375 -1.625l0 -4.4375l1.40625 0l0 8.296875l-1.25 0zm3.4296875 0l0 -11.453125l1.40625 0l0 11.453125l-1.40625 0zm9.2578125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875z" fill-rule="nonzero"/><path fill="#000000" d="m136.96883 165.60799l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm9.0078125 4.875l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm12.0 -2.828125l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm4.796875 3.203125l0.09375 -1.328125q0.4375 0.125 0.84375 0.125q0.4375 0 0.703125 -0.1875q0.34375 -0.265625 0.75 -0.96875l0.453125 -0.8125l-1.390625 -8.328125l1.390625 0l0.625 4.1875q0.1875 1.25 0.328125 2.484375l3.703125 -6.671875l1.484375 0l-5.296875 9.40625q-0.765625 1.375 -1.359375 1.8125q-0.59375 0.453125 -1.359375 0.453125q-0.5 0 -0.96875 -0.171875zm12.9765625 -3.203125l1.734375 -8.296875l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.34375l-1.40625 0l1.140625 -5.484375q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.03125l-1.421875 0l1.171875 -5.609375q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.921875l-1.40625 0zm15.34375 -9.859375l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859375l1.734375 -8.296875l1.40625 0l-1.734375 8.296875l-1.40625 0zm3.6015625 0l1.734375 -8.296875l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.03125l-1.40625 0l1.09375 -5.265625q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.859375l-1.421875 0zm14.5703125 -1.5q-1.5 1.6875 -3.0625 1.6875q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5625 -0.59375 -1.359375q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296875l-1.296875 0l0.3125 -1.5zm6.5390625 0.34375l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 192.92389l233.00789 0l0 112.12598l-233.00789 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 192.92389l233.00789 0l0 112.12598l-233.00789 0z" fill-rule="evenodd"/><path fill="#000000" d="m34.312584 217.28389l4.40625 -11.453125l1.640625 0l4.6875 11.453125l-1.734375 0l-1.328125 -3.46875l-4.796875 0l-1.25 3.46875l-1.625 0zm3.3125 -4.703125l3.890625 0l-1.203125 -3.171875q-0.546875 -1.453125 -0.8125 -2.375q-0.21875 1.09375 -0.609375 2.1875l-1.265625 3.359375zm13.859375 1.65625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm5.65625 1.78125l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm8.3359375 -2.484375l1.390625 -0.21875q0.109375 0.84375 0.640625 1.296875q0.546875 0.4375 1.5 0.4375q0.96875 0 1.4375 -0.390625q0.46875 -0.40625 0.46875 -0.9375q0 -0.46875 -0.40625 -0.75q-0.296875 -0.1875 -1.4375 -0.46875q-1.546875 -0.390625 -2.15625 -0.671875q-0.59375 -0.296875 -0.90625 -0.796875q-0.296875 -0.5 -0.296875 -1.109375q0 -0.5625 0.25 -1.03125q0.25 -0.46875 0.6875 -0.78125q0.328125 -0.25 0.890625 -0.40625q0.578125 -0.171875 1.21875 -0.171875q0.984375 0 1.71875 0.28125q0.734375 0.28125 1.078125 0.765625q0.359375 0.46875 0.5 1.28125l-1.375 0.1875q-0.09375 -0.640625 -0.546875 -1.0q-0.453125 -0.359375 -1.265625 -0.359375q-0.96875 0 -1.390625 0.328125q-0.40625 0.3125 -0.40625 0.734375q0 0.28125 0.171875 0.5q0.171875 0.21875 0.53125 0.375q0.21875 0.078125 1.25 0.359375q1.484375 0.390625 2.078125 0.65625q0.59375 0.25 0.921875 0.734375q0.34375 0.484375 0.34375 1.203125q0 0.703125 -0.421875 1.328125q-0.40625 0.609375 -1.1875 0.953125q-0.765625 0.34375 -1.734375 0.34375q-1.625 0 -2.46875 -0.671875q-0.84375 -0.671875 -1.078125 -2.0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m45.49346 236.11156l195.77954 0l0 53.48033l-195.77954 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m45.49346 236.11156l195.77954 0l0 53.48033l-195.77954 0z" fill-rule="evenodd"/><path fill="#000000" d="m55.446587 256.63156l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0zm10.09375 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm6.767578 0.84375l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.2753906 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0z" fill-rule="nonzero"/><path fill="#000000" d="m59.08721 263.63156l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m103.84112 259.76828l58.04882 0l0 13.798828l-58.04882 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m104.34112 268.2253l0.3125 -1.40625q0.421875 -0.015625 0.671875 -0.125q0.25 -0.109375 0.453125 -0.375q0.21875 -0.265625 0.34375 -0.609375q0.140625 -0.34375 0.296875 -1.09375q0.21875 -1.0625 0.4375 -1.515625q0.234375 -0.453125 0.546875 -0.703125q0.328125 -0.25 0.890625 -0.40625q0.359375 -0.09375 1.125 -0.09375l0.3125 0l-0.3125 1.390625q-0.65625 0 -0.875 0.09375q-0.21875 0.078125 -0.328125 0.265625q-0.078125 0.109375 -0.265625 0.859375q-0.328125 1.296875 -0.4375 1.578125q-0.203125 0.515625 -0.5 0.828125q-0.28125 0.3125 -0.796875 0.609375q0.34375 0.234375 0.5 0.5625q0.171875 0.3125 0.171875 0.84375q0 0.203125 -0.078125 0.625q-0.1875 1.15625 -0.25 1.359375q-0.046875 0.21875 -0.046875 0.359375q0 0.15625 0.078125 0.265625q0.09375 0.109375 0.25 0.15625q0.171875 0.0625 0.75 0.0625l-0.3125 1.40625l-0.3125 0q-0.796875 0 -1.203125 -0.140625q-0.390625 -0.125 -0.609375 -0.4375q-0.21875 -0.296875 -0.21875 -0.78125q0 -0.390625 0.203125 -1.328125q0.203125 -0.9375 0.203125 -1.25q0 -0.5 -0.21875 -0.734375q-0.21875 -0.234375 -0.78125 -0.265625zm4.669922 0l0.3125 -1.40625q0.421875 -0.015625 0.671875 -0.125q0.25 -0.109375 0.453125 -0.375q0.21875 -0.265625 0.34375 -0.609375q0.140625 -0.34375 0.296875 -1.09375q0.21875 -1.0625 0.4375 -1.515625q0.234375 -0.453125 0.546875 -0.703125q0.328125 -0.25 0.890625 -0.40625q0.359375 -0.09375 1.125 -0.09375l0.3125 0l-0.3125 1.390625q-0.65625 0 -0.875 0.09375q-0.21875 0.078125 -0.328125 0.265625q-0.078125 0.109375 -0.265625 0.859375q-0.328125 1.296875 -0.4375 1.578125q-0.203125 0.515625 -0.5 0.828125q-0.28125 0.3125 -0.796875 0.609375q0.34375 0.234375 0.5 0.5625q0.171875 0.3125 0.171875 0.84375q0 0.203125 -0.078125 0.625q-0.1875 1.15625 -0.25 1.359375q-0.046875 0.21875 -0.046875 0.359375q0 0.15625 0.078125 0.265625q0.09375 0.109375 0.25 0.15625q0.171875 0.0625 0.75 0.0625l-0.3125 1.40625l-0.3125 0q-0.796875 0 -1.203125 -0.140625q-0.390625 -0.125 -0.609375 -0.4375q-0.21875 -0.296875 -0.21875 -0.78125q0 -0.390625 0.203125 -1.328125q0.203125 -0.9375 0.203125 -1.25q0 -0.5 -0.21875 -0.734375q-0.21875 -0.234375 -0.78125 -0.265625zm4.435547 0.671875l1.625 -0.265625q0.21875 0.515625 0.53125 0.734375q0.328125 0.203125 0.890625 0.203125q0.578125 0 0.921875 -0.25q0.234375 -0.171875 0.234375 -0.421875q0 -0.171875 -0.125 -0.3125q-0.125 -0.125 -0.6875 -0.3125q-1.53125 -0.5 -1.890625 -0.796875q-0.5625 -0.453125 -0.5625 -1.203125q0 -0.734375 0.546875 -1.265625q0.765625 -0.75 2.28125 -0.75q1.203125 0 1.8125 0.453125q0.609375 0.4375 0.78125 1.1875l-1.5625 0.265625q-0.109375 -0.34375 -0.390625 -0.515625q-0.375 -0.21875 -0.90625 -0.21875q-0.53125 0 -0.765625 0.171875q-0.21875 0.171875 -0.21875 0.40625q0 0.234375 0.234375 0.375q0.140625 0.09375 0.9375 0.328125q1.234375 0.359375 1.65625 0.703125q0.578125 0.5 0.578125 1.171875q0 0.890625 -0.75 1.546875q-0.734375 0.640625 -2.09375 0.640625q-1.34375 0 -2.078125 -0.484375q-0.734375 -0.5 -1.0 -1.390625zm12.955078 -0.859375l-4.21875 0q-0.015625 0.109375 -0.015625 0.15625q0 0.625 0.359375 1.0q0.359375 0.375 0.859375 0.375q0.84375 0 1.3125 -0.859375l1.5 0.25q-0.4375 0.90625 -1.171875 1.359375q-0.734375 0.453125 -1.65625 0.453125q-1.25 0 -2.03125 -0.78125q-0.78125 -0.796875 -0.78125 -2.109375q0 -1.28125 0.703125 -2.265625q0.96875 -1.359375 2.765625 -1.359375q1.140625 0 1.8125 0.71875q0.671875 0.703125 0.671875 1.96875q0 0.609375 -0.109375 1.09375zm-1.421875 -1.015625q0 -0.125 0 -0.171875q0 -0.703125 -0.3125 -1.046875q-0.3125 -0.34375 -0.828125 -0.34375q-0.515625 0 -0.9375 0.390625q-0.40625 0.390625 -0.5625 1.171875l2.640625 0zm3.2363205 -2.609375l1.578125 0l-0.265625 1.203125q0.890625 -1.359375 1.90625 -1.359375q0.375 0 0.78125 0.1875l-0.640625 1.375q-0.234375 -0.078125 -0.484375 -0.078125q-0.4375 0 -0.890625 0.328125q-0.4375 0.328125 -0.703125 0.875q-0.25 0.546875 -0.484375 1.734375l-0.421875 1.953125l-1.6718674 0l1.2968674 -6.21875zm6.576172 6.21875l-1.453125 0l-1.25 -6.21875l1.65625 0l0.4375 2.703125q0.1875 1.109375 0.21875 1.46875q0.046875 -0.09375 0.40625 -0.75q0.359375 -0.671875 0.453125 -0.796875l1.546875 -2.625l1.8125 0l-3.828125 6.21875zm9.626953 -2.59375l-4.21875 0q-0.015625 0.109375 -0.015625 0.15625q0 0.625 0.359375 1.0q0.359375 0.375 0.859375 0.375q0.84375 0 1.3125 -0.859375l1.5 0.25q-0.4375 0.90625 -1.171875 1.359375q-0.734375 0.453125 -1.65625 0.453125q-1.25 0 -2.03125 -0.78125q-0.78125 -0.796875 -0.78125 -2.109375q0 -1.28125 0.703125 -2.265625q0.96875 -1.359375 2.765625 -1.359375q1.140625 0 1.8125 0.71875q0.671875 0.703125 0.671875 1.96875q0 0.609375 -0.109375 1.09375zm-1.421875 -1.015625q0 -0.125 0 -0.171875q0 -0.703125 -0.3125 -1.046875q-0.3125 -0.34375 -0.828125 -0.34375q-0.515625 0 -0.9375 0.390625q-0.40625 0.390625 -0.5625 1.171875l2.640625 0zm3.2363281 -2.609375l1.578125 0l-0.265625 1.203125q0.890625 -1.359375 1.90625 -1.359375q0.375 0 0.78125 0.1875l-0.640625 1.375q-0.234375 -0.078125 -0.484375 -0.078125q-0.4375 0 -0.890625 0.328125q-0.4375 0.328125 -0.703125 0.875q-0.25 0.546875 -0.484375 1.734375l-0.421875 1.953125l-1.671875 0l1.296875 -6.21875zm7.044922 3.8125q-0.53125 0.03125 -0.828125 0.21875q-0.296875 0.1875 -0.515625 0.609375q-0.21875 0.40625 -0.4375 1.4375q-0.203125 1.015625 -0.4375 1.453125q-0.21875 0.453125 -0.546875 0.703125q-0.3125 0.25 -0.875 0.40625q-0.375 0.109375 -1.125 0.109375l-0.3125 0l0.296875 -1.40625q0.640625 0 0.859375 -0.09375q0.234375 -0.09375 0.359375 -0.265625q0.078125 -0.125 0.25 -0.84375q0.328125 -1.296875 0.421875 -1.546875q0.21875 -0.515625 0.53125 -0.875q0.3125 -0.359375 0.796875 -0.609375q-0.390625 -0.28125 -0.546875 -0.578125q-0.140625 -0.296875 -0.140625 -0.828125q0 -0.203125 0.078125 -0.625q0.1875 -1.125 0.234375 -1.34375q0.0625 -0.234375 0.0625 -0.390625q0 -0.15625 -0.078125 -0.25q-0.078125 -0.109375 -0.25 -0.15625q-0.15625 -0.0625 -0.75 -0.0625l0.3125 -1.390625l0.3125 0q0.796875 0 1.1875 0.140625q0.40625 0.125 0.625 0.421875q0.21875 0.296875 0.21875 0.78125q0 0.390625 -0.203125 1.328125q-0.203125 0.9375 -0.203125 1.25q0 0.5 0.21875 0.734375q0.21875 0.234375 0.78125 0.265625l-0.296875 1.40625zm4.669922 0q-0.53125 0.03125 -0.828125 0.21875q-0.296875 0.1875 -0.515625 0.609375q-0.21875 0.40625 -0.4375 1.4375q-0.203125 1.015625 -0.4375 1.453125q-0.21875 0.453125 -0.546875 0.703125q-0.3125 0.25 -0.875 0.40625q-0.375 0.109375 -1.125 0.109375l-0.3125 0l0.296875 -1.40625q0.640625 0 0.859375 -0.09375q0.234375 -0.09375 0.359375 -0.265625q0.078125 -0.125 0.25 -0.84375q0.328125 -1.296875 0.421875 -1.546875q0.21875 -0.515625 0.53125 -0.875q0.3125 -0.359375 0.796875 -0.609375q-0.390625 -0.28125 -0.546875 -0.578125q-0.140625 -0.296875 -0.140625 -0.828125q0 -0.203125 0.078125 -0.625q0.1875 -1.125 0.234375 -1.34375q0.0625 -0.234375 0.0625 -0.390625q0 -0.15625 -0.078125 -0.25q-0.078125 -0.109375 -0.25 -0.15625q-0.15625 -0.0625 -0.75 -0.0625l0.3125 -1.390625l0.3125 0q0.796875 0 1.1875 0.140625q0.40625 0.125 0.625 0.421875q0.21875 0.296875 0.21875 0.78125q0 0.390625 -0.203125 1.328125q-0.203125 0.9375 -0.203125 1.25q0 0.5 0.21875 0.734375q0.21875 0.234375 0.78125 0.265625l-0.296875 1.40625z" fill-rule="nonzero"/><path fill="#000000" d="m163.79619 263.24094l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m103.84112 271.41156l58.04882 0l0 1.0799866l-58.04882 0l0 -1.0799866z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m557.41504 68.88976l139.37012 0l0 44.15748l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m557.41504 68.88976l139.37012 0l0 44.15748l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m567.36816 89.40977l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m571.0088 96.40977l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m615.7627 92.546486l28.02539 0l0 13.798828l-28.02539 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m617.6846 103.40977l-2.28125 0l3.78125 -4.34375l-2.125 -4.25l1.84375 0l0.84375 1.609375q0.03125 0.09375 0.5625 1.1875q0.046875 0.0625 0.078125 0.171875q0.71875 -0.875 1.203125 -1.4375l1.359375 -1.53125l2.21875 0l-3.9375 4.53125l2.125 4.0625l-2.0 0l-0.640625 -1.296875q-0.5 -1.03125 -0.671875 -1.46875q-0.21875 0.34375 -1.171875 1.421875l-1.1875 1.34375zm7.5039062 -4.9375l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m649.0283 96.01914l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m615.7627 104.189766l28.02539 0l0 1.0800018l-28.02539 0l0 -1.0800018z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 -22.834648" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l75.765564 -21.216705" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m334.56268 94.19274l3.924591 -2.8142776l-4.815399 -0.36681366z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 69.35433" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l76.97284 65.46705" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m334.25443 180.54414l4.527008 1.6819458l-2.3867493 -4.1983337z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m352.57217 6.0367455l140.56693 0l0 33.51181l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m361.54092 32.956745l5.125 -13.359377l1.90625 0l5.46875 13.359377l-2.015625 0l-1.546875 -4.046877l-5.59375 0l-1.46875 4.046877l-1.875 0zm3.859375 -5.484377l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484377l0 -13.359377l1.640625 0l0 13.359377l-1.640625 0zm10.816711 -3.109377l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.312502q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.2968769q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125702 5.765627l0 -9.671877l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.062502l-1.625 0zm9.806427 -1.4687519l0.234375 1.4531269q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.4687519 -0.203125 -1.9375019l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.2884827 1.4687519l0 -13.359377l1.765625 0l0 13.359377l-1.765625 0zm4.683319 0l0 -9.671877l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953127l-1.640625 0l0 -5.890627q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.281252l-1.640625 0zm9.719452 -2.890627l1.625 -0.25q0.125 0.96875 0.75 1.5q0.625 0.515625 1.75 0.515625q1.125 0 1.671875 -0.453125q0.546875 -0.46875 0.546875 -1.09375q0 -0.546875 -0.484375 -0.875q-0.328125 -0.21875 -1.671875 -0.546875q-1.8125 -0.46875 -2.515625 -0.796875q-0.6875 -0.328125 -1.046875 -0.90625q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.640625 0.296875 -1.1875q0.296875 -0.5625 0.8125 -0.921875q0.375 -0.28125 1.03125 -0.46875q0.671875 -0.203125 1.421875 -0.203125q1.140625 0 2.0 0.328125q0.859375 0.328125 1.265625 0.890625q0.421875 0.5625 0.578125 1.5l-1.609375 0.21875q-0.109375 -0.75 -0.640625 -1.171875q-0.515625 -0.421875 -1.46875 -0.421875q-1.140625 0 -1.625 0.375q-0.46875 0.375 -0.46875 0.875q0 0.3125 0.1875 0.578125q0.203125 0.265625 0.640625 0.4375q0.234375 0.09375 1.4375 0.421875q1.75 0.453125 2.4375 0.75q0.6875 0.296875 1.078125 0.859375q0.390625 0.5625 0.390625 1.40625q0 0.828125 -0.484375 1.546875q-0.46875 0.7187519 -1.375 1.1250019q-0.90625 0.390625 -2.046875 0.390625q-1.875 0 -2.875 -0.78125q-0.984375 -0.7812519 -1.25 -2.328127zm13.5625 1.421875l0.234375 1.4531269q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.4687519 -0.203125 -1.9375019l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm7.917694 0.28125q-0.921875 0.7656269 -1.765625 1.0937519q-0.828125 0.3125 -1.796875 0.3125q-1.59375 0 -2.453125 -0.78125q-0.859375 -0.7812519 -0.859375 -1.9843769q0 -0.71875 0.328125 -1.296875q0.328125 -0.59375 0.84375 -0.9375q0.53125 -0.359375 1.1875 -0.546875q0.46875 -0.125 1.453125 -0.25q1.984375 -0.234375 2.921875 -0.5625q0.015625 -0.34375 0.015625 -0.421875q0 -1.0 -0.46875 -1.421875q-0.625 -0.546875 -1.875 -0.546875q-1.15625 0 -1.703125 0.40625q-0.546875 0.40625 -0.8125 1.421875l-1.609375 -0.21875q0.21875 -1.015625 0.71875 -1.640625q0.5 -0.640625 1.453125 -0.984375q0.953125 -0.34375 2.1875 -0.34375q1.25 0 2.015625 0.296875q0.78125 0.28125 1.140625 0.734375q0.375 0.4375 0.515625 1.109375q0.078125 0.421875 0.078125 1.515625l0 2.1875q0 2.28125 0.109375 2.890625q0.109375 0.5937519 0.40625 1.1562519l-1.703125 0q-0.265625 -0.515625 -0.328125 -1.1875019zm-0.140625 -3.671875q-0.890625 0.375 -2.671875 0.625q-1.015625 0.140625 -1.4375 0.328125q-0.421875 0.1875 -0.65625 0.53125q-0.21875 0.34375 -0.21875 0.78125q0 0.65625 0.5 1.09375q0.5 0.4375 1.453125 0.4375q0.9375 0 1.671875 -0.40625q0.75 -0.421875 1.09375 -1.140625q0.265625 -0.5625 0.265625 -1.640625l0 -0.609375zm4.203827 4.859377l0 -9.671877l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953127l-1.640625 0l0 -5.890627q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.281252l-1.640625 0zm16.688232 -3.546877l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609377q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.2968769q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm9.640625 0.4375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.312502q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.2968769q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.90027 68.88976l139.37009 0l0 44.15748l-139.37009 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.90027 68.88976l139.37009 0l0 44.15748l-139.37009 0z" fill-rule="evenodd"/><path fill="#000000" d="m369.50748 92.67351l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm8.062012 0l4.0625 -5.46875l-3.578125 -5.015625l1.65625 0l1.890625 2.6875q0.59375 0.828125 0.84375 1.28125q0.359375 -0.5625 0.84375 -1.1875l2.109375 -2.78125l1.5 0l-3.6875 4.9375l3.984375 5.546875l-1.71875 0l-2.640625 -3.75q-0.21875 -0.3125 -0.46875 -0.6875q-0.34375 0.5625 -0.5 0.78125l-2.625 3.65625l-1.671875 0zm15.166229 0l-1.28125 0l0 -8.203125q-0.46875 0.4375 -1.21875 0.890625q-0.75 0.4375 -1.359375 0.65625l0 -1.25q1.078125 -0.5 1.890625 -1.21875q0.8125 -0.734375 1.140625 -1.40625l0.828125 0l0 10.53125zm10.072968 -1.234375l0 1.234375l-6.9375 0q-0.015625 -0.46875 0.15625 -0.890625q0.265625 -0.71875 0.84375 -1.40625q0.59375 -0.6875 1.6875 -1.578125q1.71875 -1.40625 2.3125 -2.21875q0.609375 -0.828125 0.609375 -1.5625q0 -0.765625 -0.5625 -1.28125q-0.546875 -0.53125 -1.421875 -0.53125q-0.921875 0 -1.484375 0.5625q-0.5625 0.5625 -0.5625 1.546875l-1.328125 -0.140625q0.140625 -1.484375 1.015625 -2.25q0.890625 -0.78125 2.390625 -0.78125q1.515625 0 2.390625 0.84375q0.875 0.828125 0.875 2.0625q0 0.640625 -0.265625 1.25q-0.25 0.59375 -0.84375 1.265625q-0.59375 0.671875 -1.984375 1.859375q-1.15625 0.96875 -1.484375 1.3125q-0.328125 0.34375 -0.546875 0.703125l5.140625 0zm1.385498 -1.53125l1.296875 -0.171875q0.21875 1.09375 0.75 1.578125q0.53125 0.484375 1.296875 0.484375q0.90625 0 1.53125 -0.625q0.640625 -0.640625 0.640625 -1.5625q0 -0.890625 -0.59375 -1.46875q-0.578125 -0.578125 -1.46875 -0.578125q-0.359375 0 -0.90625 0.140625l0.140625 -1.125q0.125 0.015625 0.203125 0.015625q0.828125 0 1.484375 -0.421875q0.65625 -0.4375 0.65625 -1.34375q0 -0.703125 -0.484375 -1.15625q-0.46875 -0.46875 -1.234375 -0.46875q-0.75 0 -1.25 0.46875q-0.5 0.46875 -0.640625 1.421875l-1.28125 -0.234375q0.234375 -1.296875 1.0625 -2.0q0.84375 -0.71875 2.09375 -0.71875q0.859375 0 1.578125 0.375q0.71875 0.359375 1.09375 1.0q0.390625 0.640625 0.390625 1.34375q0 0.6875 -0.375 1.25q-0.359375 0.546875 -1.0625 0.875q0.921875 0.21875 1.4375 0.90625q0.515625 0.671875 0.515625 1.6875q0 1.375 -1.0 2.328125q-1.0 0.953125 -2.53125 0.953125q-1.390625 0 -2.296875 -0.8125q-0.90625 -0.828125 -1.046875 -2.140625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.90027 161.08923l140.56693 0l0 44.157486l-140.56693 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.90027 161.08923l140.56693 0l0 44.157486l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m370.2384 184.87299l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm11.828278 0l0 -4.4375l-4.046875 -6.046875l1.6875 0l2.0625 3.15625q0.578125 0.890625 1.0625 1.78125q0.484375 -0.828125 1.15625 -1.859375l2.03125 -3.078125l1.609375 0l-4.1875 6.046875l0 4.4375l-1.375 0zm10.416229 0l0 -2.515625l-4.546875 0l0 -1.171875l4.78125 -6.796875l1.0625 0l0 6.796875l1.40625 0l0 1.171875l-1.40625 0l0 2.515625l-1.296875 0zm0 -3.6875l0 -4.734375l-3.28125 4.734375l3.28125 0zm4.0260925 0.9375l1.34375 -0.109375q0.15625 0.984375 0.703125 1.484375q0.546875 0.5 1.328125 0.5q0.921875 0 1.5625 -0.703125q0.65625 -0.703125 0.65625 -1.859375q0 -1.109375 -0.625 -1.734375q-0.625 -0.640625 -1.625 -0.640625q-0.625 0 -1.125 0.28125q-0.5 0.28125 -0.78125 0.734375l-1.203125 -0.15625l1.015625 -5.390625l5.21875 0l0 1.21875l-4.1875 0l-0.578125 2.828125q0.953125 -0.65625 1.984375 -0.65625q1.375 0 2.3125 0.953125q0.953125 0.953125 0.953125 2.4375q0 1.4375 -0.828125 2.46875q-1.015625 1.265625 -2.75 1.265625q-1.4375 0 -2.34375 -0.796875q-0.90625 -0.796875 -1.03125 -2.125zm14.838623 -5.171875l-1.28125 0.09375q-0.171875 -0.75 -0.484375 -1.09375q-0.53125 -0.546875 -1.296875 -0.546875q-0.609375 0 -1.078125 0.34375q-0.609375 0.4375 -0.96875 1.296875q-0.34375 0.84375 -0.359375 2.421875q0.46875 -0.71875 1.140625 -1.0625q0.671875 -0.34375 1.40625 -0.34375q1.296875 0 2.203125 0.953125q0.90625 0.953125 0.90625 2.453125q0 0.984375 -0.4375 1.84375q-0.421875 0.84375 -1.171875 1.296875q-0.734375 0.4375 -1.6875 0.4375q-1.609375 0 -2.625 -1.171875q-1.015625 -1.1875 -1.015625 -3.90625q0 -3.046875 1.125 -4.421875q0.984375 -1.203125 2.640625 -1.203125q1.234375 0 2.03125 0.703125q0.796875 0.6875 0.953125 1.90625zm-5.265625 4.515625q0 0.671875 0.28125 1.28125q0.28125 0.609375 0.78125 0.9375q0.515625 0.3125 1.078125 0.3125q0.8125 0 1.390625 -0.65625q0.59375 -0.671875 0.59375 -1.796875q0 -1.09375 -0.578125 -1.71875q-0.578125 -0.625 -1.453125 -0.625q-0.875 0 -1.484375 0.625q-0.609375 0.625 -0.609375 1.640625z" fill-rule="nonzero"/><path fill="#ffffff" d="m339.90027 260.88937l140.56693 0l0 44.15747l-140.56693 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m339.90027 260.88937l140.56693 0l0 44.15747l-140.56693 0z" fill-rule="evenodd"/><path fill="#000000" d="m370.5174 284.67313l1.3125 -0.109375q0.09375 0.78125 0.421875 1.296875q0.34375 0.5 1.0625 0.8125q0.71875 0.3125 1.609375 0.3125q0.796875 0 1.40625 -0.234375q0.609375 -0.234375 0.90625 -0.640625q0.296875 -0.421875 0.296875 -0.90625q0 -0.5 -0.296875 -0.859375q-0.28125 -0.375 -0.9375 -0.625q-0.421875 -0.171875 -1.875 -0.515625q-1.4375 -0.34375 -2.015625 -0.65625q-0.75 -0.390625 -1.125 -0.96875q-0.359375 -0.59375 -0.359375 -1.3125q0 -0.796875 0.4375 -1.484375q0.453125 -0.6875 1.3125 -1.046875q0.875 -0.359375 1.9375 -0.359375q1.171875 0 2.0625 0.375q0.890625 0.375 1.359375 1.109375q0.484375 0.734375 0.515625 1.65625l-1.328125 0.09375q-0.109375 -1.0 -0.734375 -1.5q-0.609375 -0.515625 -1.8125 -0.515625q-1.265625 0 -1.84375 0.46875q-0.578125 0.46875 -0.578125 1.109375q0 0.5625 0.421875 0.9375q0.390625 0.359375 2.078125 0.75q1.703125 0.375 2.328125 0.65625q0.921875 0.421875 1.359375 1.078125q0.4375 0.640625 0.4375 1.484375q0 0.84375 -0.484375 1.59375q-0.484375 0.734375 -1.390625 1.140625q-0.890625 0.40625 -2.015625 0.40625q-1.421875 0 -2.390625 -0.40625q-0.953125 -0.421875 -1.5 -1.25q-0.546875 -0.828125 -0.578125 -1.890625zm15.291229 0.921875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.0056458 0l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.421875 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.1667175 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm8.296387 0l0 -1.28125l5.375 -6.734375q0.5625 -0.703125 1.078125 -1.234375l-5.84375 0l0 -1.234375l7.515625 0l0 1.234375l-5.890625 7.28125l-0.640625 0.734375l6.703125 0l0 1.234375l-8.296875 0zm9.343231 -9.125l0 -1.234375l6.796875 0l0 1.0q-1.0 1.078125 -1.984375 2.84375q-0.984375 1.765625 -1.515625 3.625q-0.390625 1.328125 -0.5 2.890625l-1.328125 0q0.03125 -1.234375 0.484375 -2.984375q0.46875 -1.765625 1.34375 -3.390625q0.875 -1.625 1.84375 -2.75l-5.140625 0zm10.057373 3.4375q-0.796875 -0.296875 -1.1875 -0.84375q-0.390625 -0.546875 -0.390625 -1.296875q0 -1.140625 0.8125 -1.921875q0.828125 -0.78125 2.203125 -0.78125q1.375 0 2.203125 0.796875q0.84375 0.796875 0.84375 1.9375q0 0.734375 -0.390625 1.28125q-0.375 0.53125 -1.15625 0.828125q0.96875 0.3125 1.46875 1.015625q0.5 0.703125 0.5 1.671875q0 1.34375 -0.953125 2.265625q-0.9375 0.90625 -2.5 0.90625q-1.546875 0 -2.5 -0.90625q-0.953125 -0.921875 -0.953125 -2.296875q0 -1.03125 0.515625 -1.71875q0.515625 -0.6875 1.484375 -0.9375zm-0.265625 -2.1875q0 0.75 0.484375 1.21875q0.484375 0.46875 1.25 0.46875q0.734375 0 1.203125 -0.46875q0.484375 -0.46875 0.484375 -1.140625q0 -0.71875 -0.5 -1.1875q-0.484375 -0.484375 -1.203125 -0.484375q-0.734375 0 -1.234375 0.46875q-0.484375 0.46875 -0.484375 1.125zm-0.40625 4.84375q0 0.5625 0.25 1.078125q0.265625 0.5 0.78125 0.796875q0.515625 0.28125 1.109375 0.28125q0.921875 0 1.515625 -0.59375q0.609375 -0.59375 0.609375 -1.515625q0 -0.9375 -0.625 -1.53125q-0.609375 -0.609375 -1.546875 -0.609375q-0.90625 0 -1.5 0.609375q-0.59375 0.59375 -0.59375 1.484375zm7.0260925 0.609375l1.25 -0.125q0.15625 0.875 0.59375 1.28125q0.4375 0.390625 1.140625 0.390625q0.59375 0 1.03125 -0.265625q0.453125 -0.28125 0.734375 -0.734375q0.296875 -0.453125 0.484375 -1.21875q0.1875 -0.78125 0.1875 -1.59375q0 -0.078125 0 -0.25q-0.390625 0.609375 -1.0625 1.0q-0.65625 0.375 -1.4375 0.375q-1.3125 0 -2.21875 -0.9375q-0.890625 -0.953125 -0.890625 -2.484375q0 -1.609375 0.9375 -2.578125q0.9375 -0.96875 2.359375 -0.96875q1.03125 0 1.875 0.546875q0.84375 0.546875 1.28125 1.578125q0.4375 1.015625 0.4375 2.953125q0 2.0 -0.4375 3.203125q-0.421875 1.1875 -1.296875 1.8125q-0.859375 0.609375 -2.015625 0.609375q-1.234375 0 -2.015625 -0.671875q-0.78125 -0.6875 -0.9375 -1.921875zm5.28125 -4.640625q0 -1.109375 -0.59375 -1.75q-0.59375 -0.65625 -1.421875 -0.65625q-0.859375 0 -1.5 0.703125q-0.625 0.703125 -0.625 1.8125q0 1.0 0.59375 1.640625q0.609375 0.625 1.5 0.625q0.890625 0 1.46875 -0.625q0.578125 -0.640625 0.578125 -1.75z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m258.3517 113.8189l81.543304 169.13385" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m258.3517 113.8189l78.93759 163.72919" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m335.80145 278.2654l3.4586792 3.3704834l-0.4829712 -4.8051147z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m581.33215 2.6403973l140.5669 0l0 33.511814l-140.5669 0z" fill-rule="evenodd"/><path fill="#000000" d="m590.3009 29.560396l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm16.162292 1.9375l1.609375 0.21875q-0.265625 1.65625 -1.359375 2.609375q-1.078125 0.9375 -2.671875 0.9375q-1.984375 0 -3.1875 -1.296875q-1.203125 -1.296875 -1.203125 -3.71875q0 -1.578125 0.515625 -2.75q0.515625 -1.171875 1.578125 -1.75q1.0625 -0.59375 2.3125 -0.59375q1.578125 0 2.578125 0.796875q1.0 0.796875 1.28125 2.265625l-1.59375 0.234375q-0.234375 -0.96875 -0.8125 -1.453125q-0.578125 -0.5 -1.390625 -0.5q-1.234375 0 -2.015625 0.890625q-0.78125 0.890625 -0.78125 2.8125q0 1.953125 0.75 2.84375q0.75 0.875 1.953125 0.875q0.96875 0 1.609375 -0.59375q0.65625 -0.59375 0.828125 -1.828125zm6.59375 2.078125l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625zm1.6052246 -10.0l0 -1.890625l1.640625 0l0 1.890625l-1.640625 0zm0 11.46875l0 -9.671875l1.640625 0l0 9.671875l-1.640625 0zm3.5354004 -4.84375q0 -2.6875 1.484375 -3.96875q1.25 -1.078125 3.046875 -1.078125q2.0 0 3.265625 1.3125q1.265625 1.296875 1.265625 3.609375q0 1.859375 -0.5625 2.9375q-0.5625 1.0625 -1.640625 1.65625q-1.0625 0.59375 -2.328125 0.59375q-2.03125 0 -3.28125 -1.296875q-1.25 -1.3125 -1.25 -3.765625zm1.6875 0q0 1.859375 0.796875 2.796875q0.8125 0.921875 2.046875 0.921875q1.21875 0 2.03125 -0.921875q0.8125 -0.9375 0.8125 -2.84375q0 -1.796875 -0.8125 -2.71875q-0.8125 -0.921875 -2.03125 -0.921875q-1.234375 0 -2.046875 0.921875q-0.796875 0.90625 -0.796875 2.765625zm9.297607 4.84375l0 -9.671875l1.46875 0l0 1.375q1.0625 -1.59375 3.078125 -1.59375q0.875 0 1.609375 0.3125q0.734375 0.3125 1.09375 0.828125q0.375 0.5 0.515625 1.203125q0.09375 0.453125 0.09375 1.59375l0 5.953125l-1.640625 0l0 -5.890625q0 -1.0 -0.203125 -1.484375q-0.1875 -0.5 -0.671875 -0.796875q-0.484375 -0.296875 -1.140625 -0.296875q-1.046875 0 -1.8125 0.671875q-0.75 0.65625 -0.75 2.515625l0 5.28125l-1.640625 0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m557.41504 161.08923l139.37012 0l0 44.157486l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m557.41504 161.08923l139.37012 0l0 44.157486l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m567.36816 181.60924l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m571.0088 188.60924l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m615.7627 184.74596l8.003906 0l0 13.798828l-8.003906 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m620.5752 195.60924l-1.765625 0l0.703125 -3.34375l-2.375 -5.25l1.890625 0l1.0625 2.421875q0.375 0.875 0.5 1.265625q0.21875 -0.375 0.515625 -0.8125l0.8125 -1.125l1.203125 -1.75l2.0625 0l-3.9375 5.40625l-0.671875 3.1875z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m623.7666 184.74596l20.021484 0l0 13.798828l-20.021484 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m625.1885 190.67174l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m649.0283 188.21861l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m615.7627 196.38924l28.02539 0l0 1.0800018l-28.02539 0l0 -1.0800018z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m557.41504 260.88977l139.37012 0l0 44.15747l-139.37012 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m557.41504 260.88977l139.37012 0l0 44.15747l-139.37012 0z" fill-rule="evenodd"/><path fill="#000000" d="m567.36816 281.40976l0 -8.59375l6.203125 0l0 1.015625l-5.0625 0l0 2.625l4.75 0l0 1.015625l-4.75 0l0 2.921875l5.265625 0l0 1.015625l-6.40625 0zm7.8476562 0l0 -6.21875l0.9375 0l0 0.875q0.296875 -0.46875 0.78125 -0.734375q0.484375 -0.28125 1.109375 -0.28125q0.6875 0 1.125 0.28125q0.453125 0.28125 0.625 0.796875q0.75 -1.078125 1.921875 -1.078125q0.9375 0 1.421875 0.515625q0.5 0.5 0.5 1.578125l0 4.265625l-1.046875 0l0 -3.921875q0 -0.625 -0.109375 -0.90625q-0.09375 -0.28125 -0.359375 -0.453125q-0.265625 -0.171875 -0.640625 -0.171875q-0.65625 0 -1.09375 0.4375q-0.421875 0.4375 -0.421875 1.40625l0 3.609375l-1.0625 0l0 -4.046875q0 -0.703125 -0.265625 -1.046875q-0.25 -0.359375 -0.828125 -0.359375q-0.453125 0 -0.828125 0.234375q-0.375 0.234375 -0.546875 0.6875q-0.171875 0.453125 -0.171875 1.296875l0 3.234375l-1.046875 0zm14.058594 -0.765625q-0.59375 0.5 -1.140625 0.703125q-0.53125 0.203125 -1.15625 0.203125q-1.03125 0 -1.578125 -0.5q-0.546875 -0.5 -0.546875 -1.28125q0 -0.453125 0.203125 -0.828125q0.203125 -0.390625 0.546875 -0.609375q0.34375 -0.234375 0.765625 -0.34375q0.296875 -0.09375 0.9375 -0.171875q1.265625 -0.140625 1.875 -0.359375q0 -0.21875 0 -0.265625q0 -0.65625 -0.296875 -0.921875q-0.40625 -0.34375 -1.203125 -0.34375q-0.734375 0 -1.09375 0.265625q-0.359375 0.25 -0.53125 0.90625l-1.03125 -0.140625q0.140625 -0.65625 0.46875 -1.0625q0.328125 -0.40625 0.9375 -0.625q0.609375 -0.21875 1.40625 -0.21875q0.796875 0 1.296875 0.1875q0.5 0.1875 0.734375 0.46875q0.234375 0.28125 0.328125 0.71875q0.046875 0.265625 0.046875 0.96875l0 1.40625q0 1.46875 0.0625 1.859375q0.078125 0.390625 0.28125 0.75l-1.109375 0q-0.15625 -0.328125 -0.203125 -0.765625zm-0.09375 -2.359375q-0.578125 0.234375 -1.71875 0.40625q-0.65625 0.09375 -0.921875 0.21875q-0.265625 0.109375 -0.421875 0.328125q-0.140625 0.21875 -0.140625 0.5q0 0.421875 0.3125 0.703125q0.328125 0.28125 0.9375 0.28125q0.609375 0 1.078125 -0.265625q0.484375 -0.265625 0.703125 -0.734375q0.171875 -0.359375 0.171875 -1.046875l0 -0.390625zm2.7050781 -4.25l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.6347656 0l0 -8.59375l1.0625 0l0 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m571.0088 288.40976l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#010000" fill-opacity="0.0" d="m615.7627 284.54648l7.330078 0l0 13.798828l-7.330078 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m616.0596 295.40976l0.28125 -1.359375l4.953125 -5.796875l-4.0 0l0.296875 -1.4375l6.1875 0l-0.25 1.34375l-5.0 5.84375q0.796875 -0.015625 0.921875 -0.015625q0.5625 0 1.546875 -0.015625l2.03125 0l-0.296875 1.4375l-6.671875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m623.0928 284.54648l20.021484 0l0 13.798828l-20.021484 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m624.51465 290.47226l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m648.3545 288.01913l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m615.7627 296.18976l27.351562 0l0 1.0800171l-27.351562 0l0 -1.0800171z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m480.4672 183.16798l76.944855 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m480.4672 183.16798l70.944855 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m551.41205 184.81972l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m479.27036 90.968506l78.14169 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m479.27036 90.968506l72.14169 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m551.41205 92.62024l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m480.4672 282.9681l76.944855 0" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m480.4672 282.9681l70.944855 0" fill-rule="evenodd"/><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m551.41205 284.61984l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"/></g></svg> \ No newline at end of file diff --git a/docs/user/alerting/images/alert-types-index-threshold-conditions.png b/docs/user/alerting/images/alert-types-index-threshold-conditions.png new file mode 100644 index 0000000000000..356732dfb9777 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-conditions.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png b/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png new file mode 100644 index 0000000000000..fc40da7436547 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-aggregation.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png b/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png new file mode 100644 index 0000000000000..5e7c65e1247d8 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-comparison.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png b/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png new file mode 100644 index 0000000000000..ea3a3849c8927 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-grouping.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-index.png b/docs/user/alerting/images/alert-types-index-threshold-example-index.png new file mode 100644 index 0000000000000..8f818f7001278 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-index.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-preview.png b/docs/user/alerting/images/alert-types-index-threshold-example-preview.png new file mode 100644 index 0000000000000..b5d9c38d99810 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-preview.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png b/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png new file mode 100644 index 0000000000000..9c51807b8d219 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-threshold.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png b/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png new file mode 100644 index 0000000000000..24e4e03f829ce Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-timefield.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-example-window.png b/docs/user/alerting/images/alert-types-index-threshold-example-window.png new file mode 100644 index 0000000000000..5405415958485 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-example-window.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-preview.png b/docs/user/alerting/images/alert-types-index-threshold-preview.png new file mode 100644 index 0000000000000..3709f162b612b Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-preview.png differ diff --git a/docs/user/alerting/images/alert-types-index-threshold-select.png b/docs/user/alerting/images/alert-types-index-threshold-select.png new file mode 100644 index 0000000000000..0c2776e01b962 Binary files /dev/null and b/docs/user/alerting/images/alert-types-index-threshold-select.png differ diff --git a/docs/user/alerting/images/alerting-overview.png b/docs/user/alerting/images/alerting-overview.png new file mode 100644 index 0000000000000..383bc8c2ce015 Binary files /dev/null and b/docs/user/alerting/images/alerting-overview.png differ diff --git a/docs/user/alerting/images/what-is-an-action.svg b/docs/user/alerting/images/what-is-an-action.svg new file mode 100644 index 0000000000000..7675f717a6c84 --- /dev/null +++ b/docs/user/alerting/images/what-is-an-action.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 985.5511811023622 337.08923884514434" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l985.5512 0l0 337.08923l-985.5512 0l0 -337.08923z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l985.5512 0l0 337.08923l-985.5512 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m13.120735 28.889763l451.9685 0l0 282.2677l-451.9685 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m13.120735 28.889763l451.9685 0l0 282.2677l-451.9685 0z" fill-rule="evenodd"/><path fill="#000000" d="m22.089485 55.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 73.062996l418.2677 0l0 33.51181l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 73.062996l418.2677 0l0 33.51181l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m43.750084 93.40737l1.515625 0.375q-0.46875 1.875 -1.71875 2.859375q-1.234375 0.984375 -3.015625 0.984375q-1.859375 0 -3.015625 -0.75q-1.15625 -0.765625 -1.765625 -2.1875q-0.609375 -1.4375 -0.609375 -3.078125q0 -1.796875 0.6875 -3.125q0.6875 -1.328125 1.9375 -2.015625q1.265625 -0.703125 2.78125 -0.703125q1.71875 0 2.890625 0.875q1.171875 0.875 1.640625 2.46875l-1.5 0.34375q-0.390625 -1.25 -1.15625 -1.8125q-0.75 -0.578125 -1.90625 -0.578125q-1.3125 0 -2.203125 0.640625q-0.890625 0.625 -1.25 1.703125q-0.359375 1.0625 -0.359375 2.1875q0 1.46875 0.421875 2.5625q0.4375 1.078125 1.328125 1.625q0.90625 0.53125 1.953125 0.53125q1.265625 0 2.140625 -0.734375q0.890625 -0.734375 1.203125 -2.171875zm2.6796875 -0.140625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm14.2734375 0l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm7.9609375 -5.703125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm6.6171875 -1.265625l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0z" fill-rule="nonzero"/><path fill="#000000" d="m131.0157 94.57925l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125zm13.953125 0.015625l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm7.421875 0l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm12.0 -2.828125l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm15.3671875 -1.03125q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm4.8671875 4.203125l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm5.828125 0.75l1.4375 0.140625q-0.015625 0.484375 0.109375 0.71875q0.140625 0.25 0.421875 0.375q0.390625 0.171875 1.0 0.171875q1.28125 0 1.84375 -0.65625q0.359375 -0.453125 0.671875 -1.953125l0.140625 -0.671875q-1.09375 1.125 -2.34375 1.125q-1.25 0 -2.109375 -0.921875q-0.84375 -0.9375 -0.84375 -2.625q0 -1.40625 0.671875 -2.578125q0.671875 -1.171875 1.59375 -1.765625q0.921875 -0.59375 1.890625 -0.59375q1.640625 0 2.515625 1.546875l0.28125 -1.359375l1.296875 0l-1.671875 8.0q-0.265625 1.328125 -0.71875 2.0625q-0.4375 0.75 -1.234375 1.15625q-0.796875 0.40625 -1.828125 0.40625q-1.0 0 -1.734375 -0.265625q-0.71875 -0.25 -1.078125 -0.75q-0.34375 -0.5 -0.34375 -1.140625q0 -0.1875 0.03125 -0.421875zm1.765625 -4.421875q0 0.84375 0.171875 1.28125q0.234375 0.59375 0.65625 0.921875q0.4375 0.3125 0.96875 0.3125q0.703125 0 1.390625 -0.484375q0.6875 -0.5 1.109375 -1.515625q0.421875 -1.03125 0.421875 -1.953125q0 -1.03125 -0.5625 -1.625q-0.5625 -0.609375 -1.40625 -0.609375q-0.515625 0 -1.0 0.28125q-0.484375 0.265625 -0.90625 0.84375q-0.40625 0.5625 -0.625 1.359375q-0.21875 0.78125 -0.21875 1.1875zm20.78125 -0.359375l1.515625 0.203125q-0.71875 1.984375 -2.09375 3.015625q-1.375 1.015625 -3.09375 1.015625q-2.078125 0 -3.3125 -1.28125q-1.21875 -1.28125 -1.21875 -3.65625q0 -3.09375 1.859375 -5.109375q1.65625 -1.8125 4.125 -1.8125q1.8125 0 2.9375 0.984375q1.140625 0.96875 1.3125 2.625l-1.421875 0.125q-0.234375 -1.234375 -0.9375 -1.84375q-0.703125 -0.625 -1.828125 -0.625q-2.09375 0 -3.390625 1.875q-1.125 1.609375 -1.125 3.8125q0 1.765625 0.859375 2.703125q0.875 0.921875 2.265625 0.921875q1.1875 0 2.140625 -0.765625q0.96875 -0.78125 1.40625 -2.1875zm2.5859375 4.03125l2.40625 -11.453125l4.78125 0q1.234375 0 1.859375 0.28125q0.625 0.28125 1.03125 0.984375q0.40625 0.6875 0.40625 1.546875q0 0.703125 -0.296875 1.4375q-0.28125 0.734375 -0.734375 1.21875q-0.4375 0.46875 -0.890625 0.71875q-0.453125 0.234375 -0.96875 0.359375q-1.09375 0.25 -2.21875 0.25l-2.875 0l-0.96875 4.65625l-1.53125 0zm2.78125 -5.953125l2.515625 0q1.46875 0 2.15625 -0.3125q0.6875 -0.3125 1.09375 -0.953125q0.421875 -0.65625 0.421875 -1.390625q0 -0.5625 -0.21875 -0.90625q-0.21875 -0.359375 -0.625 -0.53125q-0.390625 -0.171875 -1.515625 -0.171875l-2.9375 0l-0.890625 4.265625zm10.375 -5.5l1.53125 0l-1.46875 7.03125q-0.171875 0.875 -0.171875 1.296875q0 0.921875 0.71875 1.484375q0.734375 0.5625 1.828125 0.5625q0.875 0 1.625 -0.390625q0.765625 -0.40625 1.203125 -1.1875q0.4375 -0.78125 0.78125 -2.5l1.328125 -6.296875l1.53125 0l-1.40625 6.71875q-0.359375 1.71875 -0.953125 2.71875q-0.578125 1.0 -1.625 1.609375q-1.03125 0.609375 -2.40625 0.609375q-1.296875 0 -2.25 -0.421875q-0.9375 -0.4375 -1.421875 -1.1875q-0.46875 -0.765625 -0.46875 -1.734375q0 -0.59375 0.328125 -2.0625l1.296875 -6.25zm21.85939 6.4375l-7.5937653 3.25l0 -1.40625l6.015625 -2.484375l-6.015625 -2.46875l0 -1.40625l7.5937653 3.203125l0 1.3125zm5.8984375 1.25q0 -1.453125 0.421875 -2.953125q0.4375 -1.5 0.96875 -2.390625q0.53125 -0.90625 1.09375 -1.40625q0.578125 -0.515625 1.125 -0.75q0.5625 -0.234375 1.234375 -0.234375q1.3125 0 2.1875 0.984375q0.875 0.96875 0.875 2.8125q0 1.890625 -0.609375 3.75q-0.71875 2.203125 -2.0 3.3125q-0.984375 0.84375 -2.234375 0.84375q-1.296875 0 -2.1875 -1.015625q-0.875 -1.015625 -0.875 -2.953125zm1.359375 0.359375q0 1.0625 0.359375 1.65625q0.46875 0.8125 1.40625 0.8125q0.828125 0 1.5 -0.734375q0.96875 -1.046875 1.453125 -3.0625q0.484375 -2.03125 0.484375 -3.3125q0 -1.234375 -0.46875 -1.78125q-0.46875 -0.546875 -1.25 -0.546875q-0.5625 0 -1.046875 0.296875q-0.484375 0.28125 -0.9375 0.984375q-0.625 1.0 -1.09375 2.96875q-0.40625 1.6875 -0.40625 2.71875zm7.3203125 3.40625l0.34375 -1.609375l1.59375 0l-0.34375 1.609375l-1.59375 0zm4.6015625 -2.625l1.328125 -0.140625q0.140625 0.96875 0.546875 1.375q0.421875 0.40625 0.984375 0.40625q0.8125 0 1.515625 -0.703125q1.015625 -1.03125 1.5 -2.96875q-0.703125 0.53125 -1.265625 0.765625q-0.546875 0.21875 -1.125 0.21875q-1.046875 0 -1.875 -0.703125q-1.09375 -0.90625 -1.09375 -2.625q0 -1.9375 1.265625 -3.3125q1.09375 -1.1875 2.671875 -1.1875q1.421875 0 2.359375 1.046875q0.9375 1.046875 0.9375 2.96875q0 1.875 -0.625 3.6875q-0.75 2.140625 -2.015625 3.15625q-1.03125 0.84375 -2.3125 0.84375q-1.1875 0 -1.953125 -0.734375q-0.75 -0.75 -0.84375 -2.09375zm1.890625 -4.53125q0 1.078125 0.5625 1.71875q0.578125 0.640625 1.375 0.640625q0.578125 0 1.15625 -0.390625q0.578125 -0.40625 0.984375 -1.203125q0.421875 -0.796875 0.421875 -1.625q0 -0.65625 -0.28125 -1.21875q-0.265625 -0.5625 -0.734375 -0.84375q-0.46875 -0.296875 -0.953125 -0.296875q-0.46875 0 -0.921875 0.25q-0.453125 0.25 -0.84375 0.734375q-0.390625 0.484375 -0.578125 1.125q-0.1875 0.625 -0.1875 1.109375zm11.109375 7.15625l1.5 -7.203125l-1.265625 0l0.234375 -1.09375l1.265625 0l0.234375 -1.1875q0.1875 -0.875 0.390625 -1.265625q0.203125 -0.390625 0.640625 -0.640625q0.453125 -0.265625 1.234375 -0.265625q0.53125 0 1.5625 0.234375l-0.265625 1.234375q-0.71875 -0.1875 -1.203125 -0.1875q-0.40625 0 -0.625 0.203125q-0.21875 0.203125 -0.375 0.984375l-0.1875 0.890625l1.578125 0l-0.21875 1.09375l-1.578125 0l-1.515625 7.203125l-1.40625 0zm4.4921875 -3.15625q0 -2.421875 1.4375 -4.015625q1.171875 -1.3125 3.09375 -1.3125q1.5 0 2.40625 0.9375q0.921875 0.9375 0.921875 2.53125q0 1.421875 -0.578125 2.65625q-0.578125 1.234375 -1.640625 1.890625q-1.0625 0.65625 -2.25 0.65625q-0.96875 0 -1.765625 -0.40625q-0.78125 -0.421875 -1.203125 -1.171875q-0.421875 -0.765625 -0.421875 -1.765625zm1.421875 -0.140625q0 1.171875 0.5625 1.78125q0.5625 0.609375 1.421875 0.609375q0.453125 0 0.890625 -0.1875q0.453125 -0.1875 0.828125 -0.5625q0.390625 -0.375 0.65625 -0.84375q0.28125 -0.484375 0.4375 -1.046875q0.25 -0.765625 0.25 -1.484375q0 -1.125 -0.578125 -1.734375q-0.5625 -0.625 -1.421875 -0.625q-0.65625 0 -1.203125 0.3125q-0.546875 0.3125 -1.0 0.921875q-0.4375 0.609375 -0.640625 1.421875q-0.203125 0.8125 -0.203125 1.4375zm7.2265625 3.296875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm9.6640625 0l2.390625 -11.453125l1.421875 0l-2.390625 11.453125l-1.421875 0zm9.2578125 -1.03125q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm2.9140625 1.359375l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125zm11.171875 1.6875l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm5.984375 1.15625q0.21875 -1.03125 0.609375 -1.71875q0.390625 -0.6875 1.03125 -1.3125q0.640625 -0.625 2.46875 -2.078125q1.109375 -0.890625 1.515625 -1.3125q0.578125 -0.609375 0.84375 -1.1875q0.1875 -0.40625 0.1875 -0.875q0 -0.78125 -0.5625 -1.328125q-0.5625 -0.5625 -1.375 -0.5625q-0.796875 0 -1.40625 0.5625q-0.59375 0.5625 -0.859375 1.796875l-1.375 -0.203125q0.203125 -1.53125 1.171875 -2.40625q0.984375 -0.875 2.453125 -0.875q0.96875 0 1.765625 0.40625q0.796875 0.40625 1.1875 1.140625q0.40625 0.734375 0.40625 1.515625q0 1.140625 -0.8125 2.1875q-0.5 0.65625 -2.9375 2.59375q-1.046875 0.828125 -1.5625 1.359375q-0.515625 0.53125 -0.765625 1.0l5.125 0l-0.28125 1.296875l-6.828125 0zm12.9375 0l1.734375 -8.296875l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.34375l-1.40625 0l1.140625 -5.484375q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.03125l-1.421875 0l1.171875 -5.609375q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.921875l-1.40625 0zm15.34375 -9.859375l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859375l1.734375 -8.296875l1.40625 0l-1.734375 8.296875l-1.40625 0zm3.6015625 0l1.734375 -8.296875l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.03125l-1.40625 0l1.09375 -5.265625q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.859375l-1.421875 0zm14.5703125 -1.5q-1.5 1.6875 -3.0625 1.6875q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5625 -0.59375 -1.359375q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296875l-1.296875 0l0.3125 -1.5zm6.5390625 0.34375l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm7.0546875 2.03125l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 120.07612l418.2677 0l0 39.30709l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 120.07612l418.2677 0l0 39.30709l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m35.062584 140.74861l1.4375 -0.125q0.09375 0.859375 0.46875 1.421875q0.375 0.546875 1.15625 0.890625q0.78125 0.328125 1.75 0.328125q0.875 0 1.53125 -0.25q0.671875 -0.265625 0.984375 -0.703125q0.328125 -0.453125 0.328125 -0.984375q0 -0.546875 -0.3125 -0.9375q-0.3125 -0.40625 -1.03125 -0.6875q-0.453125 -0.171875 -2.03125 -0.546875q-1.578125 -0.390625 -2.21875 -0.71875q-0.8125 -0.4375 -1.21875 -1.0625q-0.40625 -0.640625 -0.40625 -1.4375q0 -0.859375 0.484375 -1.609375q0.5 -0.765625 1.4375 -1.15625q0.953125 -0.390625 2.109375 -0.390625q1.28125 0 2.25 0.421875q0.96875 0.40625 1.484375 1.203125q0.53125 0.796875 0.578125 1.796875l-1.453125 0.109375q-0.125 -1.078125 -0.796875 -1.625q-0.671875 -0.5625 -2.0 -0.5625q-1.375 0 -2.0 0.5q-0.625 0.5 -0.625 1.21875q0 0.609375 0.4375 1.015625q0.4375 0.390625 2.28125 0.8125q1.859375 0.421875 2.546875 0.734375q1.0 0.453125 1.46875 1.171875q0.484375 0.703125 0.484375 1.625q0 0.90625 -0.53125 1.71875q-0.515625 0.8125 -1.5 1.265625q-0.984375 0.453125 -2.203125 0.453125q-1.5625 0 -2.609375 -0.453125q-1.046875 -0.46875 -1.65625 -1.375q-0.59375 -0.90625 -0.625 -2.0625zm16.421875 0.640625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm2.59375 3.046875l0 -11.453125l1.40625 0l0 4.109375q0.984375 -1.140625 2.484375 -1.140625q0.921875 0 1.59375 0.359375q0.6875 0.359375 0.96875 1.0q0.296875 0.640625 0.296875 1.859375l0 5.265625l-1.40625 0l0 -5.265625q0 -1.046875 -0.453125 -1.53125q-0.453125 -0.484375 -1.296875 -0.484375q-0.625 0 -1.171875 0.328125q-0.546875 0.328125 -0.78125 0.890625q-0.234375 0.546875 -0.234375 1.515625l0 4.546875l-1.40625 0zm14.5703125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875zm13.2109375 4.953125l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm13.3984375 4.140625l0 -1.21875q-0.96875 1.40625 -2.640625 1.40625q-0.734375 0 -1.375 -0.28125q-0.625 -0.28125 -0.9375 -0.703125q-0.3125 -0.4375 -0.4375 -1.046875q-0.078125 -0.421875 -0.078125 -1.3125l0 -5.140625l1.40625 0l0 4.59375q0 1.109375 0.078125 1.484375q0.140625 0.5625 0.5625 0.875q0.4375 0.3125 1.0625 0.3125q0.640625 0 1.1875 -0.3125q0.5625 -0.328125 0.78125 -0.890625q0.234375 -0.5625 0.234375 -1.625l0 -4.4375l1.40625 0l0 8.296875l-1.25 0zm3.4296875 0l0 -11.453125l1.40625 0l0 11.453125l-1.40625 0zm9.2578125 -2.671875l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.703125 -2.359375 0.703125q-1.828125 0 -2.890625 -1.125q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875z" fill-rule="nonzero"/><path fill="#000000" d="m136.96883 141.60799l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm9.0078125 4.875l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm12.0 -2.828125l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm4.796875 3.203125l0.09375 -1.328125q0.4375 0.125 0.84375 0.125q0.4375 0 0.703125 -0.1875q0.34375 -0.265625 0.75 -0.96875l0.453125 -0.8125l-1.390625 -8.328125l1.390625 0l0.625 4.1875q0.1875 1.25 0.328125 2.484375l3.703125 -6.671875l1.484375 0l-5.296875 9.40625q-0.765625 1.375 -1.359375 1.8125q-0.59375 0.453125 -1.359375 0.453125q-0.5 0 -0.96875 -0.171875zm12.9765625 -3.203125l1.734375 -8.296875l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.34375l-1.40625 0l1.140625 -5.484375q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.03125l-1.421875 0l1.171875 -5.609375q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.921875l-1.40625 0zm15.34375 -9.859375l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859375l1.734375 -8.296875l1.40625 0l-1.734375 8.296875l-1.40625 0zm3.6015625 0l1.734375 -8.296875l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.03125l-1.40625 0l1.09375 -5.265625q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.859375l-1.421875 0zm14.5703125 -1.5q-1.5 1.6875 -3.0625 1.6875q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5625 -0.59375 -1.359375q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296875l-1.296875 0l0.3125 -1.5zm6.5390625 0.34375l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 168.92389l418.2677 0l0 129.07086l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 168.92389l418.2677 0l0 129.07086l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m34.312584 193.28389l4.40625 -11.453125l1.640625 0l4.6875 11.453125l-1.734375 0l-1.328125 -3.46875l-4.796875 0l-1.25 3.46875l-1.625 0zm3.3125 -4.703125l3.890625 0l-1.203125 -3.171875q-0.546875 -1.453125 -0.8125 -2.375q-0.21875 1.09375 -0.609375 2.1875l-1.265625 3.359375zm13.859375 1.65625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm5.65625 1.78125l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm8.3359375 -2.484375l1.390625 -0.21875q0.109375 0.84375 0.640625 1.296875q0.546875 0.4375 1.5 0.4375q0.96875 0 1.4375 -0.390625q0.46875 -0.40625 0.46875 -0.9375q0 -0.46875 -0.40625 -0.75q-0.296875 -0.1875 -1.4375 -0.46875q-1.546875 -0.390625 -2.15625 -0.671875q-0.59375 -0.296875 -0.90625 -0.796875q-0.296875 -0.5 -0.296875 -1.109375q0 -0.5625 0.25 -1.03125q0.25 -0.46875 0.6875 -0.78125q0.328125 -0.25 0.890625 -0.40625q0.578125 -0.171875 1.21875 -0.171875q0.984375 0 1.71875 0.28125q0.734375 0.28125 1.078125 0.765625q0.359375 0.46875 0.5 1.28125l-1.375 0.1875q-0.09375 -0.640625 -0.546875 -1.0q-0.453125 -0.359375 -1.265625 -0.359375q-0.96875 0 -1.390625 0.328125q-0.40625 0.3125 -0.40625 0.734375q0 0.28125 0.171875 0.5q0.171875 0.21875 0.53125 0.375q0.21875 0.078125 1.25 0.359375q1.484375 0.390625 2.078125 0.65625q0.59375 0.25 0.921875 0.734375q0.34375 0.484375 0.34375 1.203125q0 0.703125 -0.421875 1.328125q-0.40625 0.609375 -1.1875 0.953125q-0.765625 0.34375 -1.734375 0.34375q-1.625 0 -2.46875 -0.671875q-0.84375 -0.671875 -1.078125 -2.0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m131.97372 179.3517l296.9449 0l0 106.92915l-296.9449 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m131.97372 179.3517l296.9449 0l0 106.92915l-296.9449 0z" fill-rule="evenodd"/><path fill="#000000" d="m144.0831 199.8717l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m241.94247 197.76233l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m148.03622 215.85608l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.2753906 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.955078 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m237.37997 218.8717l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.861328 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533203 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm3.9824219 2.4375l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m236.84872 235.26233l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.298828 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm4.435547 -0.015625l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m141.8956 252.8717l0 -8.59375l3.25 0q0.84375 0 1.296875 0.078125q0.640625 0.109375 1.0625 0.40625q0.4375 0.296875 0.6875 0.828125q0.265625 0.53125 0.265625 1.171875q0 1.09375 -0.703125 1.859375q-0.6875 0.75 -2.515625 0.75l-2.203125 0l0 3.5l-1.140625 0zm1.140625 -4.5l2.21875 0q1.109375 0 1.5625 -0.40625q0.46875 -0.421875 0.46875 -1.171875q0 -0.53125 -0.28125 -0.90625q-0.265625 -0.390625 -0.703125 -0.515625q-0.296875 -0.078125 -1.0625 -0.078125l-2.203125 0l0 3.078125zm6.7226562 4.5l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm3.6210938 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 5.5l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.861328 3.703125l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm6.3085938 -0.9375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm6.9160156 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.455078 1.84375l1.03125 -0.15625q0.09375 0.625 0.484375 0.953125q0.40625 0.328125 1.140625 0.328125q0.71875 0 1.0625 -0.28125q0.359375 -0.296875 0.359375 -0.703125q0 -0.359375 -0.3125 -0.5625q-0.21875 -0.140625 -1.078125 -0.359375q-1.15625 -0.296875 -1.609375 -0.5q-0.4375 -0.21875 -0.671875 -0.59375q-0.234375 -0.375 -0.234375 -0.84375q0 -0.40625 0.1875 -0.765625q0.1875 -0.359375 0.515625 -0.59375q0.25 -0.171875 0.671875 -0.296875q0.421875 -0.125 0.921875 -0.125q0.71875 0 1.265625 0.21875q0.5625 0.203125 0.828125 0.5625q0.265625 0.359375 0.359375 0.953125l-1.03125 0.140625q-0.0625 -0.46875 -0.40625 -0.734375q-0.328125 -0.28125 -0.953125 -0.28125q-0.71875 0 -1.03125 0.25q-0.3125 0.234375 -0.3125 0.5625q0 0.203125 0.125 0.359375q0.140625 0.171875 0.40625 0.28125q0.15625 0.0625 0.9375 0.265625q1.125 0.3125 1.5625 0.5q0.4375 0.1875 0.6875 0.546875q0.25 0.359375 0.25 0.90625q0 0.53125 -0.3125 1.0q-0.296875 0.453125 -0.875 0.71875q-0.578125 0.25 -1.3125 0.25q-1.21875 0 -1.859375 -0.5q-0.625 -0.515625 -0.796875 -1.5z" fill-rule="nonzero"/><path fill="#000000" d="m237.47372 250.7467l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.140625 1.0q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.4394531 1.125l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm6.611328 -4.828125l0.25 -1.203125l1.046875 0l-0.25 1.203125l-1.046875 0zm-3.359375 9.734375l0.1875 -0.90625q0.359375 0.09375 0.640625 0.09375q0.34375 0 0.546875 -0.234375q0.203125 -0.21875 0.421875 -1.234375l1.296875 -6.28125l1.0625 0l-1.34375 6.46875q-0.25 1.21875 -0.578125 1.65625q-0.4375 0.578125 -1.234375 0.578125q-0.40625 0 -1.0 -0.140625zm9.087891 -4.453125l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm9.470703 1.390625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm4.1875 1.40625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm1.6835938 7.0l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm16.835938 -3.03125l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm7.9160156 1.234375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m237.37997 266.8717l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm5.298828 0.203125q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm9.626953 1.5625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm4.986328 5.015625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm16.083984 -7.453125l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm10.4296875 -3.59375q0.453125 0 0.78125 -0.234375q0.34375 -0.234375 0.546875 -0.703125q0.171875 -0.34375 0.375 -1.3125q0.21875 -0.984375 0.34375 -1.34375q0.15625 -0.484375 0.375 -0.78125q0.21875 -0.3125 0.46875 -0.46875q0.25 -0.171875 0.625 -0.25q0.203125 -0.046875 0.671875 -0.046875l0.328125 0l-0.203125 0.921875l-0.171875 0q-0.5 0 -0.71875 0.125q-0.21875 0.109375 -0.34375 0.375q-0.109375 0.25 -0.3125 1.125q-0.234375 1.171875 -0.453125 1.6875q-0.203125 0.5 -0.53125 0.828125q-0.3125 0.3125 -0.90625 0.5625q0.421875 0.203125 0.625 0.53125q0.203125 0.328125 0.203125 0.875q0 0.453125 -0.265625 1.671875q-0.1875 0.859375 -0.1875 1.078125q0 0.21875 0.09375 0.34375q0.0625 0.109375 0.21875 0.15625q0.171875 0.0625 0.703125 0.0625l-0.1875 0.921875l-0.328125 0q-0.546875 0 -0.765625 -0.078125q-0.34375 -0.125 -0.546875 -0.40625q-0.1875 -0.265625 -0.1875 -0.734375q0 -0.390625 0.265625 -1.671875q0.203125 -0.96875 0.203125 -1.3125q0 -0.46875 -0.234375 -0.703125q-0.234375 -0.25 -0.6875 -0.25l0.203125 -0.96875zm4.0078125 0q0.453125 0 0.78125 -0.234375q0.34375 -0.234375 0.546875 -0.703125q0.171875 -0.34375 0.375 -1.3125q0.21875 -0.984375 0.34375 -1.34375q0.15625 -0.484375 0.375 -0.78125q0.21875 -0.3125 0.46875 -0.46875q0.25 -0.171875 0.625 -0.25q0.203125 -0.046875 0.671875 -0.046875l0.328125 0l-0.203125 0.921875l-0.171875 0q-0.5 0 -0.71875 0.125q-0.21875 0.109375 -0.34375 0.375q-0.109375 0.25 -0.3125 1.125q-0.234375 1.171875 -0.453125 1.6875q-0.203125 0.5 -0.53125 0.828125q-0.3125 0.3125 -0.90625 0.5625q0.421875 0.203125 0.625 0.53125q0.203125 0.328125 0.203125 0.875q0 0.453125 -0.265625 1.671875q-0.1875 0.859375 -0.1875 1.078125q0 0.21875 0.09375 0.34375q0.0625 0.109375 0.21875 0.15625q0.171875 0.0625 0.703125 0.0625l-0.1875 0.921875l-0.328125 0q-0.546875 0 -0.765625 -0.078125q-0.34375 -0.125 -0.546875 -0.40625q-0.1875 -0.265625 -0.1875 -0.734375q0 -0.390625 0.265625 -1.671875q0.203125 -0.96875 0.203125 -1.3125q0 -0.46875 -0.234375 -0.703125q-0.234375 -0.25 -0.6875 -0.25l0.203125 -0.96875zm3.6796875 1.46875l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.46875 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm5.5585938 0l-1.015625 -6.21875l1.03125 0l0.53125 3.421875q0.09375 0.5625 0.21875 1.828125q0.296875 -0.65625 0.78125 -1.515625l2.078125 -3.734375l1.109375 0l-3.5625 6.21875l-1.171875 0zm9.0 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm7.2929688 -3.59375l-0.203125 0.96875q-0.4375 0 -0.78125 0.234375q-0.328125 0.234375 -0.515625 0.640625q-0.1875 0.40625 -0.40625 1.390625q-0.21875 0.984375 -0.3125 1.3125q-0.171875 0.5 -0.390625 0.796875q-0.21875 0.3125 -0.484375 0.46875q-0.25 0.171875 -0.609375 0.265625q-0.203125 0.046875 -0.6875 0.046875l-0.328125 0l0.203125 -0.921875l0.1875 0q0.5 0 0.71875 -0.125q0.21875 -0.125 0.359375 -0.421875q0.09375 -0.21875 0.28125 -1.09375q0.234375 -1.109375 0.40625 -1.546875q0.234375 -0.59375 0.59375 -0.953125q0.359375 -0.359375 0.890625 -0.578125q-0.453125 -0.234375 -0.640625 -0.546875q-0.171875 -0.3125 -0.171875 -0.859375q0 -0.453125 0.25 -1.671875q0.1875 -0.84375 0.1875 -1.078125q0 -0.296875 -0.15625 -0.421875q-0.15625 -0.125 -0.671875 -0.125l-0.1875 0l0.203125 -0.921875l0.328125 0q0.546875 0 0.765625 0.078125q0.34375 0.109375 0.53125 0.390625q0.203125 0.265625 0.203125 0.734375q0 0.390625 -0.203125 1.296875q-0.28125 1.359375 -0.28125 1.6875q0 0.46875 0.234375 0.71875q0.234375 0.234375 0.6875 0.234375zm4.0078125 0l-0.203125 0.96875q-0.4375 0 -0.78125 0.234375q-0.328125 0.234375 -0.515625 0.640625q-0.1875 0.40625 -0.40625 1.390625q-0.21875 0.984375 -0.3125 1.3125q-0.171875 0.5 -0.390625 0.796875q-0.21875 0.3125 -0.484375 0.46875q-0.25 0.171875 -0.609375 0.265625q-0.203125 0.046875 -0.6875 0.046875l-0.328125 0l0.203125 -0.921875l0.1875 0q0.5 0 0.71875 -0.125q0.21875 -0.125 0.359375 -0.421875q0.09375 -0.21875 0.28125 -1.09375q0.234375 -1.109375 0.40625 -1.546875q0.234375 -0.59375 0.59375 -0.953125q0.359375 -0.359375 0.890625 -0.578125q-0.453125 -0.234375 -0.640625 -0.546875q-0.171875 -0.3125 -0.171875 -0.859375q0 -0.453125 0.25 -1.671875q0.1875 -0.84375 0.1875 -1.078125q0 -0.296875 -0.15625 -0.421875q-0.15625 -0.125 -0.671875 -0.125l-0.1875 0l0.203125 -0.921875l0.328125 0q0.546875 0 0.765625 0.078125q0.34375 0.109375 0.53125 0.390625q0.203125 0.265625 0.203125 0.734375q0 0.390625 -0.203125 1.296875q-0.28125 1.359375 -0.28125 1.6875q0 0.46875 0.234375 0.71875q0.234375 0.234375 0.6875 0.234375zm5.544922 -3.796875l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m673.95276 96.70677l283.68506 0l0 106.92914l-283.68506 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m673.95276 96.70677l283.68506 0l0 106.92914l-283.68506 0z" fill-rule="evenodd"/><path fill="#000000" d="m686.06213 117.22677l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m783.9215 115.11739l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m690.01526 133.21115l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.5156326 2.09375 -0.5156326q1.28125 0 2.15625 0.6562576q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.6250076l0 2.1718826l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.2187576l1.0625 0l0 1.2187576l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.2753906 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.955078 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m779.359 136.22678l1.78125 -8.593758l1.0625 0l-0.6875 3.2968826q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.861328 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533203 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.7343826l-0.46875 2.2656326l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm3.9824219 2.4375l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m778.82776 152.6174l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.298828 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm4.435547 -0.015625l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m683.87463 170.22676l0 -8.59375l3.25 0q0.84375 0 1.296875 0.078125q0.640625 0.109375 1.0625 0.40625q0.4375 0.296875 0.6875 0.828125q0.265625 0.53125 0.265625 1.171875q0 1.09375 -0.703125 1.859375q-0.6875 0.75 -2.515625 0.75l-2.203125 0l0 3.5l-1.140625 0zm1.140625 -4.5l2.21875 0q1.109375 0 1.5625 -0.40625q0.46875 -0.421875 0.46875 -1.171875q0 -0.53125 -0.28125 -0.90625q-0.265625 -0.390625 -0.703125 -0.515625q-0.296875 -0.078125 -1.0625 -0.078125l-2.203125 0l0 3.078125zm6.7226562 4.5l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm3.6210938 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 5.5l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.861328 3.703125l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm6.3085938 -0.9375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm6.9160156 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.455078 1.84375l1.03125 -0.15625q0.09375 0.625 0.484375 0.953125q0.40625 0.328125 1.140625 0.328125q0.71875 0 1.0625 -0.28125q0.359375 -0.296875 0.359375 -0.703125q0 -0.359375 -0.3125 -0.5625q-0.21875 -0.140625 -1.078125 -0.359375q-1.15625 -0.296875 -1.609375 -0.5q-0.4375 -0.21875 -0.671875 -0.59375q-0.234375 -0.375 -0.234375 -0.84375q0 -0.40625 0.1875 -0.765625q0.1875 -0.359375 0.515625 -0.59375q0.25 -0.171875 0.671875 -0.296875q0.421875 -0.125 0.921875 -0.125q0.71875 0 1.265625 0.21875q0.5625 0.203125 0.828125 0.5625q0.265625 0.359375 0.359375 0.953125l-1.03125 0.140625q-0.0625 -0.46875 -0.40625 -0.734375q-0.328125 -0.28125 -0.953125 -0.28125q-0.71875 0 -1.03125 0.25q-0.3125 0.234375 -0.3125 0.5625q0 0.203125 0.125 0.359375q0.140625 0.171875 0.40625 0.28125q0.15625 0.0625 0.9375 0.265625q1.125 0.3125 1.5625 0.5q0.4375 0.1875 0.6875 0.546875q0.25 0.359375 0.25 0.90625q0 0.53125 -0.3125 1.0q-0.296875 0.453125 -0.875 0.71875q-0.578125 0.25 -1.3125 0.25q-1.21875 0 -1.859375 -0.5q-0.625 -0.515625 -0.796875 -1.5z" fill-rule="nonzero"/><path fill="#000000" d="m779.45276 168.10176l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.140625 1.0q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.4394531 1.125l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm6.611328 -4.828125l0.25 -1.203125l1.046875 0l-0.25 1.203125l-1.046875 0zm-3.359375 9.734375l0.1875 -0.90625q0.359375 0.09375 0.640625 0.09375q0.34375 0 0.546875 -0.234375q0.203125 -0.21875 0.421875 -1.234375l1.296875 -6.28125l1.0625 0l-1.34375 6.46875q-0.25 1.21875 -0.578125 1.65625q-0.4375 0.578125 -1.234375 0.578125q-0.40625 0 -1.0 -0.140625zm9.087891 -4.453125l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm9.470703 1.390625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm4.1875 1.40625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm1.6835938 7.0l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm16.835938 -3.03125l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm7.9160156 1.234375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m779.359 184.22676l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm5.298828 0.203125q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm9.626953 1.5625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm4.986328 5.015625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm16.083984 -7.453125l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m867.9977 173.36348l28.02539 0l0 13.798828l-28.02539 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m869.91956 184.22676l-2.28125 0l3.78125 -4.34375l-2.125 -4.25l1.84375 0l0.84375 1.609375q0.03125 0.09375 0.5625 1.1875q0.046875 0.0625 0.078125 0.171875q0.71875 -0.875 1.203125 -1.4375l1.359375 -1.53125l2.21875 0l-3.9375 4.53125l2.125 4.0625l-2.0 0l-0.640625 -1.296875q-0.5 -1.03125 -0.671875 -1.46875q-0.21875 0.34375 -1.171875 1.421875l-1.1875 1.34375zm7.5039062 -4.9375l0.3125 -1.5q2.1875 -0.953125 3.375 -2.203125l1.015625 0l-1.8125 8.640625l-1.6875 0l1.25 -5.953125q-0.53125 0.34375 -1.21875 0.625q-0.6875 0.28125 -1.234375 0.390625zm8.423828 -0.96875l-1.640625 -0.25q0.1875 -1.203125 0.921875 -1.828125q0.734375 -0.640625 1.828125 -0.640625q1.203125 0 1.875 0.65625q0.6875 0.640625 0.6875 1.640625q0 0.515625 -0.21875 1.03125q-0.203125 0.515625 -0.671875 1.078125q-0.34375 0.390625 -1.140625 1.125q-0.78125 0.71875 -1.046875 1.0q-0.25 0.265625 -0.484375 0.5625l2.984375 0l-0.3125 1.53125l-5.21875 0q0.078125 -0.640625 0.359375 -1.203125q0.296875 -0.578125 0.71875 -1.0625q0.4375 -0.5 1.59375 -1.59375q0.875 -0.828125 1.09375 -1.078125q0.421875 -0.453125 0.5625 -0.78125q0.15625 -0.34375 0.15625 -0.609375q0 -0.4375 -0.25 -0.703125q-0.25 -0.28125 -0.65625 -0.28125q-0.390625 0 -0.6875 0.3125q-0.296875 0.296875 -0.453125 1.09375zm4.111328 3.65625l1.609375 -0.1875q0.109375 0.6875 0.359375 0.953125q0.265625 0.265625 0.703125 0.265625q0.5625 0 0.9375 -0.390625q0.390625 -0.390625 0.390625 -1.0q0 -0.515625 -0.3125 -0.828125q-0.296875 -0.3125 -0.8125 -0.3125q-0.125 0 -0.265625 0.03125l0.28125 -1.40625q0.09375 0.015625 0.171875 0.015625q0.671875 0 1.015625 -0.34375q0.359375 -0.34375 0.359375 -0.921875q0 -0.421875 -0.234375 -0.65625q-0.234375 -0.25 -0.625 -0.25q-0.359375 0 -0.65625 0.265625q-0.28125 0.265625 -0.453125 0.921875l-1.53125 -0.3125q0.296875 -0.953125 0.8125 -1.453125q0.796875 -0.765625 1.953125 -0.765625q1.171875 0 1.78125 0.65625q0.625 0.65625 0.625 1.578125q0 0.671875 -0.390625 1.21875q-0.390625 0.53125 -1.078125 0.78125q0.546875 0.28125 0.796875 0.75q0.265625 0.453125 0.265625 0.953125q0 0.953125 -0.671875 1.75q-0.921875 1.078125 -2.375 1.078125q-1.09375 0 -1.796875 -0.625q-0.703125 -0.625 -0.859375 -1.765625z" fill-rule="nonzero"/><path fill="#000000" d="m901.2633 176.83614l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m867.9977 185.00676l28.02539 0l0 1.0800018l-28.02539 0l0 -1.0800018z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m673.95276 213.52304l283.68506 0l0 106.92914l-283.68506 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m673.95276 213.52304l283.68506 0l0 106.92914l-283.68506 0z" fill-rule="evenodd"/><path fill="#000000" d="m686.06213 234.04305l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m783.9215 231.93367l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m690.01526 250.02742l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.2753906 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.955078 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m779.359 253.04305l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.861328 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533203 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm3.9824219 2.4375l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m778.82776 269.43365l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.298828 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm4.435547 -0.015625l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m683.87463 287.04303l0 -8.59375l3.25 0q0.84375 0 1.296875 0.078125q0.640625 0.109375 1.0625 0.40625q0.4375 0.296875 0.6875 0.828125q0.265625 0.53125 0.265625 1.171875q0 1.09375 -0.703125 1.859375q-0.6875 0.75 -2.515625 0.75l-2.203125 0l0 3.5l-1.140625 0zm1.140625 -4.5l2.21875 0q1.109375 0 1.5625 -0.40625q0.46875 -0.421875 0.46875 -1.171875q0 -0.53125 -0.28125 -0.90625q-0.265625 -0.390625 -0.703125 -0.515625q-0.296875 -0.078125 -1.0625 -0.078125l-2.203125 0l0 3.078125zm6.7226562 4.5l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm3.6210938 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 5.5l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.861328 3.703125l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm6.3085938 -0.9375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm6.9160156 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.455078 1.84375l1.03125 -0.15625q0.09375 0.625 0.484375 0.953125q0.40625 0.328125 1.140625 0.328125q0.71875 0 1.0625 -0.28125q0.359375 -0.296875 0.359375 -0.703125q0 -0.359375 -0.3125 -0.5625q-0.21875 -0.140625 -1.078125 -0.359375q-1.15625 -0.296875 -1.609375 -0.5q-0.4375 -0.21875 -0.671875 -0.59375q-0.234375 -0.375 -0.234375 -0.84375q0 -0.40625 0.1875 -0.765625q0.1875 -0.359375 0.515625 -0.59375q0.25 -0.171875 0.671875 -0.296875q0.421875 -0.125 0.921875 -0.125q0.71875 0 1.265625 0.21875q0.5625 0.203125 0.828125 0.5625q0.265625 0.359375 0.359375 0.953125l-1.03125 0.140625q-0.0625 -0.46875 -0.40625 -0.734375q-0.328125 -0.28125 -0.953125 -0.28125q-0.71875 0 -1.03125 0.25q-0.3125 0.234375 -0.3125 0.5625q0 0.203125 0.125 0.359375q0.140625 0.171875 0.40625 0.28125q0.15625 0.0625 0.9375 0.265625q1.125 0.3125 1.5625 0.5q0.4375 0.1875 0.6875 0.546875q0.25 0.359375 0.25 0.90625q0 0.53125 -0.3125 1.0q-0.296875 0.453125 -0.875 0.71875q-0.578125 0.25 -1.3125 0.25q-1.21875 0 -1.859375 -0.5q-0.625 -0.515625 -0.796875 -1.5z" fill-rule="nonzero"/><path fill="#000000" d="m779.45276 284.91803l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.140625 1.0q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.4394531 1.125l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm6.611328 -4.828125l0.25 -1.203125l1.046875 0l-0.25 1.203125l-1.046875 0zm-3.359375 9.734375l0.1875 -0.90625q0.359375 0.09375 0.640625 0.09375q0.34375 0 0.546875 -0.234375q0.203125 -0.21875 0.421875 -1.234375l1.296875 -6.28125l1.0625 0l-1.34375 6.46875q-0.25 1.21875 -0.578125 1.65625q-0.4375 0.578125 -1.234375 0.578125q-0.40625 0 -1.0 -0.140625zm9.087891 -4.453125l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm9.470703 1.390625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm4.1875 1.40625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm1.6835938 7.0l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm16.835938 -3.03125l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm7.9160156 1.234375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m779.359 301.04303l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm5.298828 0.203125q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm9.626953 1.5625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm4.986328 5.015625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm16.083984 -7.453125l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m867.9977 290.17975l28.02539 0l0 13.798828l-28.02539 0l0 -13.798828z" fill-rule="nonzero"/><path fill="#000000" d="m872.8102 301.04303l-1.765625 0l0.703125 -3.34375l-2.375 -5.25l1.890625 0l1.0625 2.421875q0.375 0.875 0.5 1.265625q0.21875 -0.375 0.515625 -0.8125l0.8125 -1.125l1.203125 -1.75l2.0625 0l-3.9375 5.40625l-0.671875 3.1875zm6.8945312 -1.75l-3.375 0l0.296875 -1.40625l4.640625 -5.4375l1.453125 0l-1.125 5.40625l1.046875 0l-0.3125 1.4375l-1.03125 0l-0.375 1.75l-1.578125 0l0.359375 -1.75zm0.3125 -1.4375l0.546875 -2.671875l-2.265625 2.671875l1.71875 0zm3.4238281 0.71875l1.625 -0.140625q0 0.125 0 0.171875q0 0.609375 0.265625 0.90625q0.265625 0.296875 0.703125 0.296875q0.59375 0 1.078125 -0.5625q0.484375 -0.578125 0.484375 -1.59375q0 -0.59375 -0.28125 -0.890625q-0.265625 -0.3125 -0.71875 -0.3125q-0.328125 0 -0.640625 0.15625q-0.296875 0.140625 -0.59375 0.453125l-1.375 -0.09375l1.296875 -4.390625l4.328125 0l-0.328125 1.53125l-2.84375 0l-0.390625 1.328125q0.234375 -0.109375 0.484375 -0.171875q0.25 -0.0625 0.484375 -0.0625q0.984375 0 1.609375 0.671875q0.640625 0.65625 0.640625 1.765625q0 0.890625 -0.4375 1.765625q-0.4375 0.859375 -1.234375 1.328125q-0.78125 0.453125 -1.640625 0.453125q-1.09375 0 -1.796875 -0.703125q-0.703125 -0.703125 -0.71875 -1.90625zm12.814453 -4.03125l-1.578125 0.140625q-0.046875 -0.515625 -0.25 -0.71875q-0.1875 -0.203125 -0.515625 -0.203125q-0.4375 0 -0.765625 0.34375q-0.46875 0.484375 -0.765625 1.5625q0.546875 -0.359375 1.15625 -0.359375q1.0 0 1.640625 0.6875q0.640625 0.671875 0.640625 1.84375q0 0.9375 -0.453125 1.765625q-0.4375 0.828125 -1.125 1.21875q-0.671875 0.375 -1.421875 0.375q-0.71875 0 -1.296875 -0.359375q-0.578125 -0.359375 -0.890625 -1.046875q-0.3125 -0.703125 -0.3125 -1.859375q0 -2.3125 1.015625 -3.90625q1.03125 -1.609375 2.703125 -1.609375q0.953125 0 1.515625 0.53125q0.578125 0.515625 0.703125 1.59375zm-4.3125 3.96875q0 0.6875 0.265625 1.015625q0.265625 0.3125 0.671875 0.3125q0.484375 0 0.84375 -0.453125q0.46875 -0.625 0.46875 -1.65625q0 -0.671875 -0.265625 -0.984375q-0.265625 -0.328125 -0.640625 -0.328125q-0.328125 0 -0.65625 0.25q-0.328125 0.25 -0.515625 0.78125q-0.171875 0.515625 -0.171875 1.0625z" fill-rule="nonzero"/><path fill="#000000" d="m901.2633 293.6524l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m867.9977 301.82303l28.02539 0l0 1.0800171l-28.02539 0l0 -1.0800171z" fill-rule="nonzero"/><path fill="#000000" fill-opacity="0.0" d="m428.9186 232.81627l245.03934 -82.64566" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m428.9186 232.81627l245.03934 -82.64566" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m428.9186 232.81627l245.03934 34.173233" fill-rule="evenodd"/><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m428.9186 232.81627l245.03934 34.173233" fill-rule="evenodd"/><path fill="#000000" fill-opacity="0.0" d="m667.3228 18.233574l296.9449 0l0 28.031494l-296.9449 0z" fill-rule="evenodd"/><path fill="#000000" d="m679.29156 41.313572l-2.796875 -10.484373l1.4375 0l1.59375 6.874998q0.25 1.078125 0.4375 2.140625q0.40625 -1.6875 0.46875 -1.9375l2.0 -7.078123l1.671875 0l1.5 5.296873q0.578125 1.984375 0.828125 3.71875q0.203125 -1.0 0.515625 -2.28125l1.640625 -6.734373l1.40625 0l-2.875 10.484373l-1.34375 0l-2.203125 -8.0q-0.28125 -1.0 -0.34375 -1.21875q-0.15625 0.71875 -0.296875 1.21875l-2.234375 8.0l-1.40625 0zm11.833313 0l0 -10.484373l1.28125 0l0 3.749998q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354187 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.182373 4.53125l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm17.176208 -0.9375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm12.3324585 1.03125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm1.890625 -1.015625q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072998 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.749998l1.28125 0l0 10.484373l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.291687 -5.21875l0 -1.4687481l1.296875 0l0 1.4687481l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686646 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.8906231l1.28125 -0.765625l0 2.656248l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594604 -7.859375l0 -1.4687481l1.296875 0l0 1.4687481l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717896 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm12.2230835 -9.015625l0 -1.4687481l1.296875 0l0 1.4687481l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7405396 -2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125zm16.837585 2.265625l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.749998l1.28125 0l0 10.484373l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.494873 1.34375l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm9.994812 3.375l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.8906231l1.28125 -0.765625l0 2.656248l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm6.4626465 -1.296875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.135437 1.75l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.8906231l1.28125 -0.765625l0 2.656248l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm6.4626465 -1.296875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104187 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.749998l1.28125 0l0 10.484373l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.619873 3.796875l0 -1.46875l1.46875 0l0 1.46875q0 0.8125 -0.28125 1.296875q-0.28125 0.5 -0.90625 0.78125l-0.359375 -0.546875q0.40625 -0.1875 0.59375 -0.53125q0.203125 -0.34375 0.21875 -1.0l-0.734375 0zm10.628357 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.8906231l1.28125 -0.765625l0 2.656248l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2594604 1.15625l0 -10.484373l1.28125 0l0 3.749998q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm13.354248 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm16.207458 3.59375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm8.260437 1.03125l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm5.1875 1.625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.8906231l1.28125 -0.765625l0 2.656248l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2595215 -7.859375l0 -1.4687481l1.296875 0l0 1.4687481l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7717285 -3.796875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 3.796875l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm12.2230835 -9.015625l0 -1.4687481l1.296875 0l0 1.4687481l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm2.7405396 -2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125z" fill-rule="nonzero"/><path fill="#000000" d="m677.29156 62.219826l0 -10.5l1.171875 0l0 0.984375q0.421875 -0.578125 0.9375 -0.859375q0.515625 -0.296875 1.265625 -0.296875q0.96875 0 1.71875 0.5q0.75 0.5 1.125 1.421875q0.375 0.90625 0.375 1.984375q0 1.171875 -0.421875 2.109375q-0.40625 0.921875 -1.21875 1.421875q-0.796875 0.5 -1.671875 0.5q-0.640625 0 -1.15625 -0.265625q-0.515625 -0.28125 -0.84375 -0.6875l0 3.6875l-1.28125 0zm1.15625 -6.65625q0 1.453125 0.59375 2.15625q0.609375 0.703125 1.453125 0.703125q0.859375 0 1.46875 -0.71875q0.609375 -0.734375 0.609375 -2.25q0 -1.453125 -0.609375 -2.171875q-0.59375 -0.734375 -1.421875 -0.734375q-0.8125 0 -1.453125 0.78125q-0.640625 0.765625 -0.640625 2.234375zm6.510498 -0.046875q0 -2.109375 1.171875 -3.125q0.984375 -0.84375 2.390625 -0.84375q1.578125 0 2.5625 1.03125q1.0 1.015625 1.0 2.828125q0 1.46875 -0.4375 2.3125q-0.4375 0.828125 -1.28125 1.296875q-0.84375 0.46875 -1.84375 0.46875q-1.59375 0 -2.578125 -1.015625q-0.984375 -1.03125 -0.984375 -2.953125zm1.328125 0q0 1.453125 0.625 2.1875q0.640625 0.71875 1.609375 0.71875q0.96875 0 1.59375 -0.71875q0.640625 -0.734375 0.640625 -2.234375q0 -1.40625 -0.640625 -2.125q-0.640625 -0.734375 -1.59375 -0.734375q-0.96875 0 -1.609375 0.71875q-0.625 0.71875 -0.625 2.1875zm7.307373 6.703125l0 -10.5l1.171875 0l0 0.984375q0.421875 -0.578125 0.9375 -0.859375q0.515625 -0.296875 1.265625 -0.296875q0.96875 0 1.71875 0.5q0.75 0.5 1.125 1.421875q0.375 0.90625 0.375 1.984375q0 1.171875 -0.421875 2.109375q-0.40625 0.921875 -1.21875 1.421875q-0.796875 0.5 -1.671875 0.5q-0.640625 0 -1.15625 -0.265625q-0.515625 -0.28125 -0.84375 -0.6875l0 3.6875l-1.28125 0zm1.15625 -6.65625q0 1.453125 0.59375 2.15625q0.609375 0.703125 1.453125 0.703125q0.859375 0 1.46875 -0.71875q0.609375 -0.734375 0.609375 -2.25q0 -1.453125 -0.609375 -2.171875q-0.59375 -0.734375 -1.421875 -0.734375q-0.8125 0 -1.453125 0.78125q-0.640625 0.765625 -0.640625 2.234375zm11.979248 3.75l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm3.135437 0l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.24054 -0.9375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm6.119873 2.65625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm6.4625854 -1.296875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104248 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm12.7699585 3.796875l-2.328125 -7.59375l1.328125 0l1.203125 4.375l0.453125 1.640625q0.03125 -0.125 0.390625 -1.578125l1.21875 -4.4375l1.328125 0l1.125 4.40625l0.390625 1.453125l0.4375 -1.46875l1.296875 -4.390625l1.25 0l-2.375 7.59375l-1.34375 0l-1.203125 -4.546875l-0.296875 -1.296875l-1.53125 5.84375l-1.34375 0zm9.17804 -9.015625l0 -1.46875l1.296875 0l0 1.46875l-1.296875 0zm0 9.015625l0 -7.59375l1.296875 0l0 7.59375l-1.296875 0zm6.0686035 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm1.2595215 1.15625l0 -10.484375l1.28125 0l0 3.75q0.90625 -1.03125 2.28125 -1.03125q0.84375 0 1.46875 0.328125q0.625 0.328125 0.890625 0.921875q0.265625 0.578125 0.265625 1.703125l0 4.8125l-1.28125 0l0 -4.8125q0 -0.96875 -0.421875 -1.40625q-0.421875 -0.4375 -1.1875 -0.4375q-0.578125 0 -1.078125 0.296875q-0.5 0.296875 -0.71875 0.8125q-0.21875 0.5 -0.21875 1.390625l0 4.15625l-1.28125 0zm17.176208 -0.9375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm3.276062 3.8125l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.49054 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm7.166748 4.53125l0 -7.59375l1.15625 0l0 1.140625q0.453125 -0.796875 0.828125 -1.046875q0.375 -0.265625 0.8125 -0.265625q0.65625 0 1.328125 0.40625l-0.4375 1.203125q-0.46875 -0.28125 -0.953125 -0.28125q-0.421875 0 -0.765625 0.25q-0.328125 0.25 -0.46875 0.703125q-0.21875 0.6875 -0.21875 1.5l0 3.984375l-1.28125 0zm7.70874 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm7.440857 1.15625l-2.890625 -7.59375l1.359375 0l1.625 4.546875q0.265625 0.734375 0.5 1.53125q0.15625 -0.609375 0.46875 -1.453125l1.6875 -4.625l1.328125 0l-2.875 7.59375l-1.203125 0zm10.171875 -0.9375q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm3.276123 3.8125l0 -10.484375l1.28125 0l0 10.484375l-1.28125 0zm8.2717285 0l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm8.369873 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm6.666748 2.265625l1.265625 -0.203125q0.109375 0.765625 0.59375 1.171875q0.5 0.40625 1.375 0.40625q0.890625 0 1.3125 -0.359375q0.4375 -0.359375 0.4375 -0.84375q0 -0.4375 -0.375 -0.6875q-0.265625 -0.171875 -1.3125 -0.4375q-1.421875 -0.359375 -1.96875 -0.609375q-0.546875 -0.265625 -0.828125 -0.734375q-0.28125 -0.46875 -0.28125 -1.015625q0 -0.515625 0.21875 -0.9375q0.234375 -0.4375 0.640625 -0.734375q0.296875 -0.21875 0.8125 -0.359375q0.53125 -0.15625 1.125 -0.15625q0.890625 0 1.5625 0.265625q0.671875 0.25 1.0 0.6875q0.328125 0.4375 0.4375 1.171875l-1.25 0.171875q-0.09375 -0.578125 -0.5 -0.90625q-0.40625 -0.34375 -1.15625 -0.34375q-0.890625 0 -1.28125 0.296875q-0.375 0.296875 -0.375 0.6875q0 0.25 0.15625 0.453125q0.15625 0.203125 0.5 0.34375q0.1875 0.078125 1.140625 0.328125q1.359375 0.359375 1.890625 0.59375q0.546875 0.234375 0.859375 0.6875q0.3125 0.4375 0.3125 1.09375q0 0.640625 -0.375 1.21875q-0.375 0.5625 -1.09375 0.875q-0.703125 0.3125 -1.59375 0.3125q-1.484375 0 -2.265625 -0.609375q-0.765625 -0.625 -0.984375 -1.828125zm14.368835 5.34375q-1.0625 -1.34375 -1.796875 -3.140625q-0.734375 -1.8125 -0.734375 -3.734375q0 -1.703125 0.546875 -3.265625q0.640625 -1.8125 1.984375 -3.609375l0.921875 0q-0.859375 1.484375 -1.140625 2.125q-0.4375 0.984375 -0.6875 2.0625q-0.296875 1.34375 -0.296875 2.6875q0 3.453125 2.125 6.875l-0.921875 0zm5.5932617 -3.078125l4.0625 -5.46875l-3.578125 -5.015625l1.65625 0l1.890625 2.6875q0.59375 0.828125 0.84375 1.28125q0.359375 -0.5625 0.84375 -1.1875l2.109375 -2.78125l1.5 0l-3.6875 4.9375l3.984375 5.546875l-1.71875 0l-2.640625 -3.75q-0.21875 -0.3125 -0.46875 -0.6875q-0.34375 0.5625 -0.5 0.78125l-2.625 3.65625l-1.671875 0zm15.166199 0l-1.28125 0l0 -8.203125q-0.46875 0.4375 -1.21875 0.890625q-0.75 0.4375 -1.359375 0.65625l0 -1.25q1.078125 -0.5 1.890625 -1.21875q0.8125 -0.734375 1.140625 -1.40625l0.828125 0l0 10.53125zm10.072998 -1.234375l0 1.234375l-6.9375 0q-0.015625 -0.46875 0.15625 -0.890625q0.265625 -0.71875 0.84375 -1.40625q0.59375 -0.6875 1.6875 -1.578125q1.71875 -1.40625 2.3125 -2.21875q0.609375 -0.828125 0.609375 -1.5625q0 -0.765625 -0.5625 -1.28125q-0.546875 -0.53125 -1.421875 -0.53125q-0.921875 0 -1.484375 0.5625q-0.5625 0.5625 -0.5625 1.546875l-1.328125 -0.140625q0.140625 -1.484375 1.015625 -2.25q0.890625 -0.78125 2.390625 -0.78125q1.515625 0 2.390625 0.84375q0.875 0.828125 0.875 2.0625q0 0.640625 -0.265625 1.25q-0.25 0.59375 -0.84375 1.265625q-0.59375 0.671875 -1.984375 1.859375q-1.15625 0.96875 -1.484375 1.3125q-0.328125 0.34375 -0.546875 0.703125l5.140625 0zm1.385498 -1.53125l1.296875 -0.171875q0.21875 1.09375 0.75 1.578125q0.53125 0.484375 1.296875 0.484375q0.90625 0 1.53125 -0.625q0.640625 -0.640625 0.640625 -1.5625q0 -0.890625 -0.59375 -1.46875q-0.578125 -0.578125 -1.46875 -0.578125q-0.359375 0 -0.90625 0.140625l0.140625 -1.125q0.125 0.015625 0.203125 0.015625q0.828125 0 1.484375 -0.421875q0.65625 -0.4375 0.65625 -1.34375q0 -0.703125 -0.484375 -1.15625q-0.46875 -0.46875 -1.234375 -0.46875q-0.75 0 -1.25 0.46875q-0.5 0.46875 -0.640625 1.421875l-1.28125 -0.234375q0.234375 -1.296875 1.0625 -2.0q0.84375 -0.71875 2.09375 -0.71875q0.859375 0 1.578125 0.375q0.71875 0.359375 1.09375 1.0q0.390625 0.640625 0.390625 1.34375q0 0.6875 -0.375 1.25q-0.359375 0.546875 -1.0625 0.875q0.921875 0.21875 1.4375 0.90625q0.515625 0.671875 0.515625 1.6875q0 1.375 -1.0 2.328125q-1.0 0.953125 -2.53125 0.953125q-1.390625 0 -2.296875 -0.8125q-0.90625 -0.828125 -1.046875 -2.140625zm17.535583 1.828125q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm3.307373 3.8125l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072937 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125z" fill-rule="nonzero"/><path fill="#000000" d="m680.41656 77.313576l0 -4.4375l-4.046875 -6.046875l1.6875 0l2.0625 3.15625q0.578125 0.890625 1.0625 1.78125q0.484375 -0.828125 1.15625 -1.859375l2.03125 -3.078125l1.609375 0l-4.1875 6.046875l0 4.4375l-1.375 0zm10.41626 0l0 -2.515625l-4.546875 0l0 -1.171875l4.78125 -6.796875l1.0625 0l0 6.796875l1.40625 0l0 1.171875l-1.40625 0l0 2.515625l-1.296875 0zm0 -3.6875l0 -4.734375l-3.28125 4.734375l3.28125 0zm4.026123 0.9375l1.34375 -0.109375q0.15625 0.984375 0.703125 1.484375q0.546875 0.5 1.328125 0.5q0.921875 0 1.5625 -0.703125q0.65625 -0.703125 0.65625 -1.859375q0 -1.109375 -0.625 -1.734375q-0.625 -0.640625 -1.625 -0.640625q-0.625 0 -1.125 0.28125q-0.5 0.28125 -0.78125 0.734375l-1.203125 -0.15625l1.015625 -5.390625l5.21875 0l0 1.21875l-4.1875 0l-0.578125 2.828125q0.953125 -0.65625 1.984375 -0.65625q1.375 0 2.3125 0.953125q0.953125 0.953125 0.953125 2.4375q0 1.4375 -0.828125 2.46875q-1.015625 1.265625 -2.75 1.265625q-1.4375 0 -2.34375 -0.796875q-0.90625 -0.796875 -1.03125 -2.125zm14.838562 -5.171875l-1.28125 0.09375q-0.171875 -0.75 -0.484375 -1.09375q-0.53125 -0.546875 -1.296875 -0.546875q-0.609375 0 -1.078125 0.34375q-0.609375 0.4375 -0.96875 1.296875q-0.34375 0.84375 -0.359375 2.421875q0.46875 -0.71875 1.140625 -1.0625q0.671875 -0.34375 1.40625 -0.34375q1.296875 0 2.203125 0.953125q0.90625 0.953125 0.90625 2.453125q0 0.984375 -0.4375 1.84375q-0.421875 0.84375 -1.171875 1.296875q-0.734375 0.4375 -1.6875 0.4375q-1.609375 0 -2.625 -1.171875q-1.015625 -1.1875 -1.015625 -3.90625q0 -3.046875 1.125 -4.421875q0.984375 -1.203125 2.640625 -1.203125q1.234375 0 2.03125 0.703125q0.796875 0.6875 0.953125 1.90625zm-5.265625 4.515625q0 0.671875 0.28125 1.28125q0.28125 0.609375 0.78125 0.9375q0.515625 0.3125 1.078125 0.3125q0.8125 0 1.390625 -0.65625q0.59375 -0.671875 0.59375 -1.796875q0 -1.09375 -0.578125 -1.71875q-0.578125 -0.625 -1.453125 -0.625q-0.875 0 -1.484375 0.625q-0.609375 0.625 -0.609375 1.640625zm7.932373 6.484375l-0.921875 0q2.140625 -3.421875 2.140625 -6.875q0 -1.34375 -0.3125 -2.671875q-0.25 -1.0625 -0.671875 -2.046875q-0.28125 -0.65625 -1.15625 -2.15625l0.921875 0q1.34375 1.796875 1.984375 3.609375q0.546875 1.5625 0.546875 3.265625q0 1.921875 -0.734375 3.734375q-0.734375 1.796875 -1.796875 3.140625zm13.062012 -4.015625q-0.71875 0.609375 -1.375 0.859375q-0.65625 0.25 -1.421875 0.25q-1.25 0 -1.921875 -0.609375q-0.671875 -0.609375 -0.671875 -1.5625q0 -0.5625 0.25 -1.015625q0.25 -0.46875 0.65625 -0.75q0.421875 -0.28125 0.9375 -0.421875q0.375 -0.09375 1.140625 -0.1875q1.5625 -0.1875 2.296875 -0.453125q0.015625 -0.265625 0.015625 -0.328125q0 -0.796875 -0.375 -1.109375q-0.484375 -0.4375 -1.453125 -0.4375q-0.921875 0 -1.359375 0.328125q-0.421875 0.3125 -0.625 1.109375l-1.265625 -0.171875q0.171875 -0.796875 0.5625 -1.296875q0.390625 -0.5 1.140625 -0.765625q0.75 -0.265625 1.71875 -0.265625q0.984375 0 1.59375 0.234375q0.609375 0.21875 0.890625 0.5625q0.28125 0.34375 0.40625 0.875q0.0625 0.328125 0.0625 1.1875l0 1.71875q0 1.796875 0.078125 2.28125q0.078125 0.46875 0.328125 0.90625l-1.34375 0q-0.203125 -0.40625 -0.265625 -0.9375zm-0.109375 -2.875q-0.703125 0.28125 -2.09375 0.484375q-0.796875 0.109375 -1.125 0.265625q-0.328125 0.140625 -0.515625 0.421875q-0.171875 0.265625 -0.171875 0.59375q0 0.515625 0.390625 0.859375q0.390625 0.34375 1.140625 0.34375q0.734375 0 1.3125 -0.3125q0.59375 -0.328125 0.859375 -0.890625q0.203125 -0.4375 0.203125 -1.296875l0 -0.46875zm3.307373 3.8125l0 -7.59375l1.15625 0l0 1.078125q0.84375 -1.25 2.421875 -1.25q0.6875 0 1.265625 0.25q0.578125 0.234375 0.859375 0.640625q0.28125 0.40625 0.40625 0.953125q0.0625 0.359375 0.0625 1.25l0 4.671875l-1.28125 0l0 -4.625q0 -0.78125 -0.15625 -1.171875q-0.15625 -0.390625 -0.546875 -0.625q-0.375 -0.234375 -0.890625 -0.234375q-0.8125 0 -1.421875 0.53125q-0.59375 0.515625 -0.59375 1.96875l0 4.15625l-1.28125 0zm13.072937 0l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm16.566833 1.34375l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm6.322998 4.53125l2.78125 -3.953125l-2.578125 -3.640625l1.609375 0l1.171875 1.78125q0.328125 0.5 0.53125 0.84375q0.3125 -0.46875 0.578125 -0.828125l1.28125 -1.796875l1.53125 0l-2.625 3.578125l2.828125 4.015625l-1.578125 0l-1.5625 -2.359375l-0.40625 -0.640625l-2.0 3.0l-1.5625 0zm13.390625 -2.453125l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.135498 1.75l1.265625 0.15625q-0.203125 1.3125 -1.0625 2.0625q-0.84375 0.734375 -2.09375 0.734375q-1.5625 0 -2.515625 -1.015625q-0.9375 -1.03125 -0.9375 -2.921875q0 -1.234375 0.40625 -2.15625q0.40625 -0.921875 1.234375 -1.375q0.84375 -0.46875 1.8125 -0.46875q1.25 0 2.03125 0.625q0.78125 0.625 1.015625 1.765625l-1.265625 0.203125q-0.171875 -0.765625 -0.625 -1.15625q-0.453125 -0.390625 -1.09375 -0.390625q-0.984375 0 -1.59375 0.703125q-0.609375 0.703125 -0.609375 2.203125q0 1.53125 0.578125 2.234375q0.59375 0.6875 1.546875 0.6875q0.75 0 1.265625 -0.453125q0.515625 -0.46875 0.640625 -1.4375zm7.359375 2.78125l0 -1.109375q-0.890625 1.28125 -2.421875 1.28125q-0.671875 0 -1.25 -0.25q-0.578125 -0.265625 -0.875 -0.65625q-0.28125 -0.390625 -0.390625 -0.953125q-0.078125 -0.375 -0.078125 -1.203125l0 -4.703125l1.28125 0l0 4.203125q0 1.015625 0.078125 1.359375q0.125 0.515625 0.515625 0.8125q0.40625 0.28125 0.984375 0.28125q0.578125 0 1.078125 -0.296875q0.515625 -0.296875 0.71875 -0.8125q0.21875 -0.515625 0.21875 -1.484375l0 -4.0625l1.28125 0l0 7.59375l-1.140625 0zm5.979248 -1.15625l0.1875 1.140625q-0.546875 0.109375 -0.984375 0.109375q-0.6875 0 -1.078125 -0.21875q-0.390625 -0.21875 -0.546875 -0.578125q-0.15625 -0.359375 -0.15625 -1.515625l0 -4.375l-0.953125 0l0 -1.0l0.953125 0l0 -1.890625l1.28125 -0.765625l0 2.65625l1.296875 0l0 1.0l-1.296875 0l0 4.4375q0 0.546875 0.0625 0.71875q0.078125 0.15625 0.21875 0.25q0.15625 0.078125 0.453125 0.078125q0.203125 0 0.5625 -0.046875zm6.4625854 -1.296875l1.328125 0.171875q-0.3125 1.171875 -1.171875 1.8125q-0.84375 0.640625 -2.171875 0.640625q-1.671875 0 -2.65625 -1.015625q-0.96875 -1.03125 -0.96875 -2.890625q0 -1.921875 0.984375 -2.96875q1.0 -1.0625 2.578125 -1.0625q1.515625 0 2.484375 1.03125q0.96875 1.03125 0.96875 2.921875q0 0.109375 -0.015625 0.34375l-5.65625 0q0.0625 1.25 0.703125 1.921875q0.640625 0.65625 1.59375 0.65625q0.703125 0 1.203125 -0.359375q0.5 -0.375 0.796875 -1.203125zm-4.234375 -2.078125l4.25 0q-0.09375 -0.953125 -0.484375 -1.4375q-0.625 -0.75 -1.609375 -0.75q-0.875 0 -1.484375 0.59375q-0.609375 0.59375 -0.671875 1.59375zm12.104248 4.53125l0 -0.953125q-0.71875 1.125 -2.125 1.125q-0.90625 0 -1.671875 -0.5q-0.75 -0.5 -1.171875 -1.390625q-0.421875 -0.90625 -0.421875 -2.078125q0 -1.140625 0.375 -2.0625q0.390625 -0.921875 1.140625 -1.40625q0.765625 -0.5 1.703125 -0.5q0.6875 0 1.21875 0.296875q0.53125 0.28125 0.875 0.734375l0 -3.75l1.28125 0l0 10.484375l-1.203125 0zm-4.0625 -3.796875q0 1.46875 0.609375 2.1875q0.625 0.71875 1.453125 0.71875q0.84375 0 1.4375 -0.6875q0.59375 -0.6875 0.59375 -2.109375q0 -1.5625 -0.609375 -2.28125q-0.59375 -0.734375 -1.484375 -0.734375q-0.84375 0 -1.421875 0.703125q-0.578125 0.703125 -0.578125 2.203125zm7.651062 3.796875l0 -1.46875l1.46875 0l0 1.46875l-1.46875 0z" fill-rule="nonzero"/></g></svg> \ No newline at end of file diff --git a/docs/user/alerting/images/what-is-an-alert.svg b/docs/user/alerting/images/what-is-an-alert.svg new file mode 100644 index 0000000000000..b4dc02fae39a5 --- /dev/null +++ b/docs/user/alerting/images/what-is-an-alert.svg @@ -0,0 +1 @@ +<svg version="1.1" viewBox="0.0 0.0 484.2257217847769 307.87139107611546" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><clipPath id="p.0"><path d="m0 0l484.2257 0l0 307.8714l-484.2257 0l0 -307.8714z" clip-rule="nonzero"/></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l484.2257 0l0 307.8714l-484.2257 0z" fill-rule="evenodd"/><path fill="#ffffff" d="m13.120735 12.889764l451.9685 0l0 282.2677l-451.9685 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m13.120735 12.889764l451.9685 0l0 282.2677l-451.9685 0z" fill-rule="evenodd"/><path fill="#000000" d="m22.089485 39.80976l5.125 -13.359375l1.90625 0l5.46875 13.359375l-2.015625 0l-1.546875 -4.046875l-5.59375 0l-1.46875 4.046875l-1.875 0zm3.859375 -5.484375l4.53125 0l-1.40625 -3.703125q-0.625 -1.6875 -0.9375 -2.765625q-0.265625 1.28125 -0.71875 2.546875l-1.46875 3.921875zm9.802948 5.484375l0 -13.359375l1.640625 0l0 13.359375l-1.640625 0zm10.816696 -3.109375l1.6875 0.203125q-0.40625 1.484375 -1.484375 2.3125q-1.078125 0.8125 -2.765625 0.8125q-2.125 0 -3.375 -1.296875q-1.234375 -1.3125 -1.234375 -3.671875q0 -2.453125 1.25 -3.796875q1.265625 -1.34375 3.265625 -1.34375q1.9375 0 3.15625 1.328125q1.234375 1.3125 1.234375 3.703125q0 0.15625 0 0.4375l-7.21875 0q0.09375 1.59375 0.90625 2.453125q0.8125 0.84375 2.015625 0.84375q0.90625 0 1.546875 -0.46875q0.640625 -0.484375 1.015625 -1.515625zm-5.390625 -2.65625l5.40625 0q-0.109375 -1.21875 -0.625 -1.828125q-0.78125 -0.953125 -2.03125 -0.953125q-1.125 0 -1.90625 0.765625q-0.765625 0.75 -0.84375 2.015625zm9.125717 5.765625l0 -9.671875l1.46875 0l0 1.46875q0.5625 -1.03125 1.03125 -1.359375q0.484375 -0.328125 1.0625 -0.328125q0.828125 0 1.6875 0.53125l-0.5625 1.515625q-0.609375 -0.359375 -1.203125 -0.359375q-0.546875 0 -0.96875 0.328125q-0.421875 0.328125 -0.609375 0.890625q-0.28125 0.875 -0.28125 1.921875l0 5.0625l-1.625 0zm9.806427 -1.46875l0.234375 1.453125q-0.6875 0.140625 -1.234375 0.140625q-0.890625 0 -1.390625 -0.28125q-0.484375 -0.28125 -0.6875 -0.734375q-0.203125 -0.46875 -0.203125 -1.9375l0 -5.578125l-1.203125 0l0 -1.265625l1.203125 0l0 -2.390625l1.625 -0.984375l0 3.375l1.65625 0l0 1.265625l-1.65625 0l0 5.671875q0 0.6875 0.078125 0.890625q0.09375 0.203125 0.28125 0.328125q0.203125 0.109375 0.578125 0.109375q0.265625 0 0.71875 -0.0625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 57.062992l418.2677 0l0 33.511814l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 57.062992l418.2677 0l0 33.511814l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m43.750084 77.40737l1.515625 0.375q-0.46875 1.875 -1.71875 2.859375q-1.234375 0.984375 -3.015625 0.984375q-1.859375 0 -3.015625 -0.75q-1.15625 -0.765625 -1.765625 -2.1875q-0.609375 -1.4375 -0.609375 -3.078125q0 -1.796875 0.6875 -3.125q0.6875 -1.328125 1.9375 -2.015625q1.265625 -0.703125 2.78125 -0.703125q1.71875 0 2.890625 0.875q1.171875 0.875 1.640625 2.46875l-1.5 0.34375q-0.390625 -1.25 -1.15625 -1.8125q-0.75 -0.578125 -1.90625 -0.578125q-1.3125 0 -2.203125 0.640625q-0.890625 0.625 -1.25 1.703125q-0.359375 1.0625 -0.359375 2.1875q0 1.46875 0.421875 2.5625q0.4375 1.078125 1.328125 1.625q0.90625 0.53125 1.953125 0.53125q1.265625 0 2.140625 -0.734375q0.890625 -0.734375 1.203125 -2.171875zm2.6796875 -0.140625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm14.2734375 0l0 -1.046875q-0.78125 1.234375 -2.3125 1.234375q-1.0 0 -1.828125 -0.546875q-0.828125 -0.546875 -1.296875 -1.53125q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453125l-1.3125 0zm-4.4375 -4.140625q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm7.9609375 -5.703125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm6.6171875 -1.265625l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0z" fill-rule="nonzero"/><path fill="#000000" d="m131.0157 78.57925l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125zm13.953125 0.015625l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm7.421875 0l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm12.0 -2.828125l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm15.3671875 -1.03125q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm4.8671875 4.203125l-1.359375 -8.296875l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296875l-1.578125 0zm5.828125 0.75l1.4375 0.140625q-0.015625 0.484375 0.109375 0.71875q0.140625 0.25 0.421875 0.375q0.390625 0.171875 1.0 0.171875q1.28125 0 1.84375 -0.65625q0.359375 -0.453125 0.671875 -1.953125l0.140625 -0.671875q-1.09375 1.125 -2.34375 1.125q-1.25 0 -2.109375 -0.921875q-0.84375 -0.9375 -0.84375 -2.625q0 -1.40625 0.671875 -2.578125q0.671875 -1.171875 1.59375 -1.765625q0.921875 -0.59375 1.890625 -0.59375q1.640625 0 2.515625 1.546875l0.28125 -1.359375l1.296875 0l-1.671875 8.0q-0.265625 1.328125 -0.71875 2.0625q-0.4375 0.75 -1.234375 1.15625q-0.796875 0.40625 -1.828125 0.40625q-1.0 0 -1.734375 -0.265625q-0.71875 -0.25 -1.078125 -0.75q-0.34375 -0.5 -0.34375 -1.140625q0 -0.1875 0.03125 -0.421875zm1.765625 -4.421875q0 0.84375 0.171875 1.28125q0.234375 0.59375 0.65625 0.921875q0.4375 0.3125 0.96875 0.3125q0.703125 0 1.390625 -0.484375q0.6875 -0.5 1.109375 -1.515625q0.421875 -1.03125 0.421875 -1.953125q0 -1.03125 -0.5625 -1.625q-0.5625 -0.609375 -1.40625 -0.609375q-0.515625 0 -1.0 0.28125q-0.484375 0.265625 -0.90625 0.84375q-0.40625 0.5625 -0.625 1.359375q-0.21875 0.78125 -0.21875 1.1875zm20.78125 -0.359375l1.515625 0.203125q-0.71875 1.984375 -2.09375 3.015625q-1.375 1.015625 -3.09375 1.015625q-2.078125 0 -3.3125 -1.28125q-1.21875 -1.28125 -1.21875 -3.65625q0 -3.09375 1.859375 -5.109375q1.65625 -1.8125 4.125 -1.8125q1.8125 0 2.9375 0.984375q1.140625 0.96875 1.3125 2.625l-1.421875 0.125q-0.234375 -1.234375 -0.9375 -1.84375q-0.703125 -0.625 -1.828125 -0.625q-2.09375 0 -3.390625 1.875q-1.125 1.609375 -1.125 3.8125q0 1.765625 0.859375 2.703125q0.875 0.921875 2.265625 0.921875q1.1875 0 2.140625 -0.765625q0.96875 -0.78125 1.40625 -2.1875zm2.5859375 4.03125l2.40625 -11.453125l4.78125 0q1.234375 0 1.859375 0.28125q0.625 0.28125 1.03125 0.984375q0.40625 0.6875 0.40625 1.546875q0 0.703125 -0.296875 1.4375q-0.28125 0.734375 -0.734375 1.21875q-0.4375 0.46875 -0.890625 0.71875q-0.453125 0.234375 -0.96875 0.359375q-1.09375 0.25 -2.21875 0.25l-2.875 0l-0.96875 4.65625l-1.53125 0zm2.78125 -5.953125l2.515625 0q1.46875 0 2.15625 -0.3125q0.6875 -0.3125 1.09375 -0.953125q0.421875 -0.65625 0.421875 -1.390625q0 -0.5625 -0.21875 -0.90625q-0.21875 -0.359375 -0.625 -0.53125q-0.390625 -0.171875 -1.515625 -0.171875l-2.9375 0l-0.890625 4.265625zm10.375 -5.5l1.53125 0l-1.46875 7.03125q-0.171875 0.875 -0.171875 1.296875q0 0.921875 0.71875 1.484375q0.734375 0.5625 1.828125 0.5625q0.875 0 1.625 -0.390625q0.765625 -0.40625 1.203125 -1.1875q0.4375 -0.78125 0.78125 -2.5l1.328125 -6.296875l1.53125 0l-1.40625 6.71875q-0.359375 1.71875 -0.953125 2.71875q-0.578125 1.0 -1.625 1.609375q-1.03125 0.609375 -2.40625 0.609375q-1.296875 0 -2.25 -0.421875q-0.9375 -0.4375 -1.421875 -1.1875q-0.46875 -0.765625 -0.46875 -1.734375q0 -0.59375 0.328125 -2.0625l1.296875 -6.25zm21.85939 6.4375l-7.5937653 3.25l0 -1.40625l6.015625 -2.484375l-6.015625 -2.46875l0 -1.40625l7.5937653 3.203125l0 1.3125zm5.8984375 1.25q0 -1.453125 0.421875 -2.953125q0.4375 -1.5 0.96875 -2.390625q0.53125 -0.90625 1.09375 -1.40625q0.578125 -0.515625 1.125 -0.75q0.5625 -0.234375 1.234375 -0.234375q1.3125 0 2.1875 0.984375q0.875 0.96875 0.875 2.8125q0 1.890625 -0.609375 3.75q-0.71875 2.203125 -2.0 3.3125q-0.984375 0.84375 -2.234375 0.84375q-1.296875 0 -2.1875 -1.015625q-0.875 -1.015625 -0.875 -2.953125zm1.359375 0.359375q0 1.0625 0.359375 1.65625q0.46875 0.8125 1.40625 0.8125q0.828125 0 1.5 -0.734375q0.96875 -1.046875 1.453125 -3.0625q0.484375 -2.03125 0.484375 -3.3125q0 -1.234375 -0.46875 -1.78125q-0.46875 -0.546875 -1.25 -0.546875q-0.5625 0 -1.046875 0.296875q-0.484375 0.28125 -0.9375 0.984375q-0.625 1.0 -1.09375 2.96875q-0.40625 1.6875 -0.40625 2.71875zm7.3203125 3.40625l0.34375 -1.609375l1.59375 0l-0.34375 1.609375l-1.59375 0zm4.6015625 -2.625l1.328125 -0.140625q0.140625 0.96875 0.546875 1.375q0.421875 0.40625 0.984375 0.40625q0.8125 0 1.515625 -0.703125q1.015625 -1.03125 1.5 -2.96875q-0.703125 0.53125 -1.265625 0.765625q-0.546875 0.21875 -1.125 0.21875q-1.046875 0 -1.875 -0.703125q-1.09375 -0.90625 -1.09375 -2.625q0 -1.9375 1.265625 -3.3125q1.09375 -1.1875 2.671875 -1.1875q1.421875 0 2.359375 1.046875q0.9375 1.046875 0.9375 2.96875q0 1.875 -0.625 3.6875q-0.75 2.140625 -2.015625 3.15625q-1.03125 0.84375 -2.3125 0.84375q-1.1875 0 -1.953125 -0.734375q-0.75 -0.75 -0.84375 -2.09375zm1.890625 -4.53125q0 1.078125 0.5625 1.71875q0.578125 0.640625 1.375 0.640625q0.578125 0 1.15625 -0.390625q0.578125 -0.40625 0.984375 -1.203125q0.421875 -0.796875 0.421875 -1.625q0 -0.65625 -0.28125 -1.21875q-0.265625 -0.5625 -0.734375 -0.84375q-0.46875 -0.296875 -0.953125 -0.296875q-0.46875 0 -0.921875 0.25q-0.453125 0.25 -0.84375 0.734375q-0.390625 0.484375 -0.578125 1.125q-0.1875 0.625 -0.1875 1.109375zm11.109375 7.15625l1.5 -7.203125l-1.265625 0l0.234375 -1.09375l1.265625 0l0.234375 -1.1875q0.1875 -0.875 0.390625 -1.265625q0.203125 -0.390625 0.640625 -0.640625q0.453125 -0.265625 1.234375 -0.265625q0.53125 0 1.5625 0.234375l-0.265625 1.234375q-0.71875 -0.1875 -1.203125 -0.1875q-0.40625 0 -0.625 0.203125q-0.21875 0.203125 -0.375 0.984375l-0.1875 0.890625l1.578125 0l-0.21875 1.09375l-1.578125 0l-1.515625 7.203125l-1.40625 0zm4.4921875 -3.15625q0 -2.421875 1.4375 -4.015625q1.171875 -1.3125 3.09375 -1.3125q1.5 0 2.40625 0.9375q0.921875 0.9375 0.921875 2.53125q0 1.421875 -0.578125 2.65625q-0.578125 1.234375 -1.640625 1.890625q-1.0625 0.65625 -2.25 0.65625q-0.96875 0 -1.765625 -0.40625q-0.78125 -0.421875 -1.203125 -1.171875q-0.421875 -0.765625 -0.421875 -1.765625zm1.421875 -0.140625q0 1.171875 0.5625 1.78125q0.5625 0.609375 1.421875 0.609375q0.453125 0 0.890625 -0.1875q0.453125 -0.1875 0.828125 -0.5625q0.390625 -0.375 0.65625 -0.84375q0.28125 -0.484375 0.4375 -1.046875q0.25 -0.765625 0.25 -1.484375q0 -1.125 -0.578125 -1.734375q-0.5625 -0.625 -1.421875 -0.625q-0.65625 0 -1.203125 0.3125q-0.546875 0.3125 -1.0 0.921875q-0.4375 0.609375 -0.640625 1.421875q-0.203125 0.8125 -0.203125 1.4375zm7.2265625 3.296875l1.734375 -8.296875l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.328125l-1.34375 0zm9.6640625 0l2.390625 -11.453125l1.421875 0l-2.390625 11.453125l-1.421875 0zm9.2578125 -1.03125q-0.734375 0.625 -1.421875 0.921875q-0.671875 0.296875 -1.4375 0.296875q-1.15625 0 -1.859375 -0.671875q-0.703125 -0.6875 -0.703125 -1.734375q0 -0.703125 0.3125 -1.234375q0.328125 -0.53125 0.84375 -0.859375q0.53125 -0.328125 1.28125 -0.46875q0.484375 -0.09375 1.8125 -0.140625q1.328125 -0.0625 1.90625 -0.28125q0.171875 -0.578125 0.171875 -0.96875q0 -0.484375 -0.359375 -0.765625q-0.5 -0.390625 -1.4375 -0.390625q-0.890625 0 -1.46875 0.390625q-0.5625 0.390625 -0.8125 1.125l-1.4375 -0.125q0.4375 -1.234375 1.390625 -1.890625q0.953125 -0.65625 2.390625 -0.65625q1.546875 0 2.4375 0.734375q0.6875 0.546875 0.6875 1.421875q0 0.65625 -0.1875 1.53125l-0.46875 2.0625q-0.21875 0.984375 -0.21875 1.609375q0 0.390625 0.171875 1.125l-1.421875 0q-0.125 -0.40625 -0.171875 -1.03125zm0.53125 -3.171875q-0.296875 0.109375 -0.640625 0.171875q-0.34375 0.0625 -1.140625 0.140625q-1.234375 0.109375 -1.75 0.28125q-0.5 0.15625 -0.765625 0.53125q-0.25 0.359375 -0.25 0.8125q0 0.59375 0.40625 0.984375q0.421875 0.375 1.171875 0.375q0.703125 0 1.34375 -0.375q0.65625 -0.375 1.03125 -1.03125q0.375 -0.671875 0.59375 -1.890625zm2.9140625 1.359375l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125zm11.171875 1.6875l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm5.984375 1.15625q0.21875 -1.03125 0.609375 -1.71875q0.390625 -0.6875 1.03125 -1.3125q0.640625 -0.625 2.46875 -2.078125q1.109375 -0.890625 1.515625 -1.3125q0.578125 -0.609375 0.84375 -1.1875q0.1875 -0.40625 0.1875 -0.875q0 -0.78125 -0.5625 -1.328125q-0.5625 -0.5625 -1.375 -0.5625q-0.796875 0 -1.40625 0.5625q-0.59375 0.5625 -0.859375 1.796875l-1.375 -0.203125q0.203125 -1.53125 1.171875 -2.40625q0.984375 -0.875 2.453125 -0.875q0.96875 0 1.765625 0.40625q0.796875 0.40625 1.1875 1.140625q0.40625 0.734375 0.40625 1.515625q0 1.140625 -0.8125 2.1875q-0.5 0.65625 -2.9375 2.59375q-1.046875 0.828125 -1.5625 1.359375q-0.515625 0.53125 -0.765625 1.0l5.125 0l-0.28125 1.296875l-6.828125 0zm12.9375 0l1.734375 -8.296875l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.34375l-1.40625 0l1.140625 -5.484375q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.03125l-1.421875 0l1.171875 -5.609375q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.921875l-1.40625 0zm15.34375 -9.859375l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859375l1.734375 -8.296875l1.40625 0l-1.734375 8.296875l-1.40625 0zm3.6015625 0l1.734375 -8.296875l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.03125l-1.40625 0l1.09375 -5.265625q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.859375l-1.421875 0zm14.5703125 -1.5q-1.5 1.6875 -3.0625 1.6875q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5625 -0.59375 -1.359375q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296875l-1.296875 0l0.3125 -1.5zm6.5390625 0.34375l-0.234375 1.171875q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.3125 -0.375 -0.84375q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.921875 -2.546875 0.921875q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.4375 -1.171875 -1.25q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm7.0546875 2.03125l1.40625 -0.078125q0 0.609375 0.1875 1.046875q0.1875 0.421875 0.6875 0.703125q0.515625 0.265625 1.1875 0.265625q0.9375 0 1.40625 -0.375q0.46875 -0.375 0.46875 -0.890625q0 -0.359375 -0.28125 -0.6875q-0.296875 -0.328125 -1.421875 -0.8125q-1.109375 -0.484375 -1.421875 -0.671875q-0.53125 -0.328125 -0.796875 -0.75q-0.265625 -0.4375 -0.265625 -1.0q0 -0.984375 0.78125 -1.6875q0.78125 -0.703125 2.1875 -0.703125q1.5625 0 2.375 0.71875q0.828125 0.71875 0.859375 1.90625l-1.390625 0.09375q-0.03125 -0.75 -0.53125 -1.1875q-0.5 -0.4375 -1.40625 -0.4375q-0.734375 0 -1.140625 0.34375q-0.40625 0.328125 -0.40625 0.71875q0 0.390625 0.34375 0.6875q0.234375 0.203125 1.21875 0.625q1.625 0.703125 2.046875 1.109375q0.671875 0.640625 0.671875 1.578125q0 0.609375 -0.390625 1.203125q-0.375 0.59375 -1.15625 0.953125q-0.765625 0.359375 -1.828125 0.359375q-1.4375 0 -2.4375 -0.71875q-1.015625 -0.703125 -0.953125 -2.3125z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 104.07612l418.2677 0l0 39.30709l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 104.07612l418.2677 0l0 39.30709l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m35.062584 124.74862l1.4375 -0.125q0.09375 0.859375 0.46875 1.421875q0.375 0.546875 1.15625 0.890625q0.78125 0.328125 1.75 0.328125q0.875 0 1.53125 -0.25q0.671875 -0.265625 0.984375 -0.703125q0.328125 -0.453125 0.328125 -0.984375q0 -0.546875 -0.3125 -0.9375q-0.3125 -0.40625 -1.03125 -0.6875q-0.453125 -0.171875 -2.03125 -0.546875q-1.578125 -0.390625 -2.21875 -0.71875q-0.8125 -0.4375 -1.21875 -1.0625q-0.40625 -0.640625 -0.40625 -1.4375q0 -0.859375 0.484375 -1.609375q0.5 -0.765625 1.4375 -1.15625q0.953125 -0.390625 2.109375 -0.390625q1.28125 0 2.25 0.421875q0.96875 0.40625 1.484375 1.203125q0.53125 0.796875 0.578125 1.796875l-1.453125 0.109375q-0.125 -1.078125 -0.796875 -1.625q-0.671875 -0.5625 -2.0 -0.5625q-1.375 0 -2.0 0.5q-0.625 0.5 -0.625 1.21875q0 0.609375 0.4375 1.015625q0.4375 0.390625 2.28125 0.8125q1.859375 0.421875 2.546875 0.734375q1.0 0.453125 1.46875 1.171875q0.484375 0.703125 0.484375 1.625q0 0.90625 -0.53125 1.71875q-0.515625 0.8125 -1.5 1.2656174q-0.984375 0.453125 -2.203125 0.453125q-1.5625 0 -2.609375 -0.453125q-1.046875 -0.46874237 -1.65625 -1.3749924q-0.59375 -0.90625 -0.625 -2.0625zm16.421875 0.640625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8124924 -2.28125 0.8124924q-1.703125 0 -2.75 -1.1093674q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm2.59375 3.0468674l0 -11.453117l1.40625 0l0 4.109375q0.984375 -1.140625 2.484375 -1.140625q0.921875 0 1.59375 0.359375q0.6875 0.359375 0.96875 1.0q0.296875 0.640625 0.296875 1.859375l0 5.2656174l-1.40625 0l0 -5.2656174q0 -1.046875 -0.453125 -1.53125q-0.453125 -0.484375 -1.296875 -0.484375q-0.625 0 -1.171875 0.328125q-0.546875 0.328125 -0.78125 0.890625q-0.234375 0.546875 -0.234375 1.515625l0 4.5468674l-1.40625 0zm14.5703125 -2.6718674l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.7031174 -2.359375 0.7031174q-1.828125 0 -2.890625 -1.1249924q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875zm13.2109375 4.9531174l0 -1.0468674q-0.78125 1.2343674 -2.3125 1.2343674q-1.0 0 -1.828125 -0.546875q-0.828125 -0.5468674 -1.296875 -1.5312424q-0.453125 -0.984375 -0.453125 -2.25q0 -1.25 0.40625 -2.25q0.421875 -1.015625 1.25 -1.546875q0.828125 -0.546875 1.859375 -0.546875q0.75 0 1.328125 0.3125q0.59375 0.3125 0.953125 0.828125l0 -4.109375l1.40625 0l0 11.453117l-1.3125 0zm-4.4375 -4.1406174q0 1.59375 0.671875 2.390625q0.671875 0.78125 1.578125 0.78125q0.921875 0 1.5625 -0.75q0.65625 -0.765625 0.65625 -2.3125q0 -1.703125 -0.65625 -2.5q-0.65625 -0.796875 -1.625 -0.796875q-0.9375 0 -1.5625 0.765625q-0.625 0.765625 -0.625 2.421875zm13.3984375 4.1406174l0 -1.2187424q-0.96875 1.4062424 -2.640625 1.4062424q-0.734375 0 -1.375 -0.28125q-0.625 -0.28125 -0.9375 -0.7031174q-0.3125 -0.4375 -0.4375 -1.046875q-0.078125 -0.421875 -0.078125 -1.3125l0 -5.140625l1.40625 0l0 4.59375q0 1.109375 0.078125 1.484375q0.140625 0.5625 0.5625 0.875q0.4375 0.3125 1.0625 0.3125q0.640625 0 1.1875 -0.3125q0.5625 -0.328125 0.78125 -0.890625q0.234375 -0.5625 0.234375 -1.625l0 -4.4375l1.40625 0l0 8.296867l-1.25 0zm3.4296875 0l0 -11.453117l1.40625 0l0 11.453117l-1.40625 0zm9.2578125 -2.6718674l1.453125 0.171875q-0.34375 1.28125 -1.28125 1.984375q-0.921875 0.7031174 -2.359375 0.7031174q-1.828125 0 -2.890625 -1.1249924q-1.0625 -1.125 -1.0625 -3.140625q0 -2.09375 1.078125 -3.25q1.078125 -1.15625 2.796875 -1.15625q1.65625 0 2.703125 1.140625q1.0625 1.125 1.0625 3.171875q0 0.125 0 0.375l-6.1875 0q0.078125 1.375 0.765625 2.109375q0.703125 0.71875 1.734375 0.71875q0.78125 0 1.328125 -0.40625q0.546875 -0.40625 0.859375 -1.296875zm-4.609375 -2.28125l4.625 0q-0.09375 -1.046875 -0.53125 -1.5625q-0.671875 -0.8125 -1.734375 -0.8125q-0.96875 0 -1.640625 0.65625q-0.65625 0.640625 -0.71875 1.71875z" fill-rule="nonzero"/><path fill="#000000" d="m136.96883 125.607994l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.9218674 -2.546875 0.9218674q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.43749237 -1.171875 -1.2499924q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm9.0078125 4.8749924l-1.359375 -8.296867l1.375 0l0.71875 4.5625q0.109375 0.75 0.28125 2.453125q0.40625 -0.890625 1.046875 -2.03125l2.765625 -4.984375l1.5 0l-4.75 8.296867l-1.578125 0zm12.0 -2.8281174l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.9218674 -2.546875 0.9218674q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.43749237 -1.171875 -1.2499924q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625zm6.9140625 4.8749924l1.734375 -8.296867l1.25 0l-0.34375 1.6875q0.640625 -0.953125 1.25 -1.40625q0.609375 -0.46875 1.25 -0.46875q0.421875 0 1.046875 0.296875l-0.578125 1.3125q-0.375 -0.265625 -0.8125 -0.265625q-0.734375 0 -1.515625 0.828125q-0.78125 0.828125 -1.234375 2.984375l-0.703125 3.3281174l-1.34375 0zm4.796875 3.203125l0.09375 -1.328125q0.4375 0.125 0.84375 0.125q0.4375 0 0.703125 -0.1875q0.34375 -0.265625 0.75 -0.96875l0.453125 -0.8125l-1.390625 -8.328117l1.390625 0l0.625 4.1875q0.1875 1.25 0.328125 2.484375l3.703125 -6.671875l1.484375 0l-5.296875 9.406242q-0.765625 1.375 -1.359375 1.8125q-0.59375 0.453125 -1.359375 0.453125q-0.5 0 -0.96875 -0.171875zm12.9765625 -3.203125l1.734375 -8.296867l1.40625 0l-0.28125 1.359375q0.78125 -0.875 1.40625 -1.203125q0.625 -0.34375 1.34375 -0.34375q0.78125 0 1.296875 0.40625q0.515625 0.40625 0.6875 1.140625q0.625 -0.78125 1.328125 -1.15625q0.703125 -0.390625 1.46875 -0.390625q1.046875 0 1.5625 0.5q0.515625 0.484375 0.515625 1.375q0 0.375 -0.171875 1.265625l-1.125 5.3437424l-1.40625 0l1.140625 -5.4843674q0.140625 -0.671875 0.140625 -0.96875q0 -0.40625 -0.265625 -0.640625q-0.25 -0.234375 -0.71875 -0.234375q-0.625 0 -1.28125 0.390625q-0.65625 0.375 -1.03125 1.0q-0.359375 0.625 -0.625 1.90625l-0.84375 4.0312424l-1.421875 0l1.171875 -5.6093674q0.125 -0.5625 0.125 -0.8125q0 -0.40625 -0.25 -0.65625q-0.25 -0.25 -0.65625 -0.25q-0.609375 0 -1.265625 0.390625q-0.65625 0.375 -1.078125 1.0625q-0.40625 0.6875 -0.671875 1.953125l-0.828125 3.9218674l-1.40625 0zm15.34375 -9.859367l0.328125 -1.59375l1.40625 0l-0.328125 1.59375l-1.40625 0zm-2.0625 9.859367l1.734375 -8.296867l1.40625 0l-1.734375 8.296867l-1.40625 0zm3.6015625 0l1.734375 -8.296867l1.28125 0l-0.296875 1.4375q0.828125 -0.84375 1.546875 -1.234375q0.734375 -0.390625 1.5 -0.390625q1.0 0 1.578125 0.546875q0.578125 0.546875 0.578125 1.453125q0 0.46875 -0.203125 1.453125l-1.0625 5.0312424l-1.40625 0l1.09375 -5.2656174q0.171875 -0.765625 0.171875 -1.125q0 -0.421875 -0.296875 -0.671875q-0.28125 -0.265625 -0.8125 -0.265625q-1.09375 0 -1.9375 0.78125q-0.84375 0.78125 -1.25 2.6875l-0.796875 3.8593674l-1.421875 0zm14.5703125 -1.4999924q-1.5 1.6874924 -3.0625 1.6874924q-0.953125 0 -1.546875 -0.546875q-0.59375 -0.5624924 -0.59375 -1.3593674q0 -0.515625 0.265625 -1.796875l1.0 -4.78125l1.421875 0l-1.109375 5.296875q-0.140625 0.671875 -0.140625 1.03125q0 0.46875 0.28125 0.734375q0.28125 0.265625 0.84375 0.265625q0.59375 0 1.15625 -0.28125q0.5625 -0.296875 0.96875 -0.78125q0.421875 -0.5 0.671875 -1.171875q0.171875 -0.4375 0.40625 -1.515625l0.75 -3.578125l1.40625 0l-1.734375 8.296867l-1.296875 0l0.3125 -1.4999924zm6.5390625 0.34375l-0.234375 1.1718674q-0.515625 0.125 -0.984375 0.125q-0.84375 0 -1.34375 -0.421875q-0.375 -0.31249237 -0.375 -0.8437424q0 -0.28125 0.203125 -1.265625l1.0 -4.8125l-1.109375 0l0.21875 -1.09375l1.125 0l0.421875 -2.046875l1.625 -0.96875l-0.640625 3.015625l1.390625 0l-0.234375 1.09375l-1.375 0l-0.96875 4.578125q-0.171875 0.875 -0.171875 1.046875q0 0.25 0.140625 0.390625q0.140625 0.125 0.46875 0.125q0.46875 0 0.84375 -0.09375zm7.2265625 -1.671875l1.375 0.140625q-0.296875 1.03125 -1.359375 1.953125q-1.0625 0.9218674 -2.546875 0.9218674q-0.921875 0 -1.6875 -0.421875q-0.765625 -0.43749237 -1.171875 -1.2499924q-0.40625 -0.8125 -0.40625 -1.84375q0 -1.359375 0.625 -2.640625q0.640625 -1.28125 1.640625 -1.890625q1.0 -0.625 2.15625 -0.625q1.484375 0 2.375 0.921875q0.890625 0.921875 0.890625 2.515625q0 0.609375 -0.109375 1.25l-6.109375 0q-0.03125 0.234375 -0.03125 0.4375q0 1.15625 0.53125 1.78125q0.53125 0.609375 1.3125 0.609375q0.71875 0 1.421875 -0.46875q0.703125 -0.484375 1.09375 -1.390625zm-4.109375 -2.046875l4.65625 0q0.015625 -0.21875 0.015625 -0.3125q0 -1.0625 -0.53125 -1.625q-0.53125 -0.578125 -1.375 -0.578125q-0.90625 0 -1.65625 0.625q-0.734375 0.625 -1.109375 1.890625z" fill-rule="nonzero"/><path fill="#f3f3f3" d="m25.343832 152.92389l418.2677 0l0 129.07086l-418.2677 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m25.343832 152.92389l418.2677 0l0 129.07086l-418.2677 0z" fill-rule="evenodd"/><path fill="#000000" d="m34.312584 177.28389l4.40625 -11.453125l1.640625 0l4.6875 11.453125l-1.734375 0l-1.328125 -3.46875l-4.796875 0l-1.25 3.46875l-1.625 0zm3.3125 -4.703125l3.890625 0l-1.203125 -3.171875q-0.546875 -1.453125 -0.8125 -2.375q-0.21875 1.09375 -0.609375 2.1875l-1.265625 3.359375zm13.859375 1.65625l1.390625 0.1875q-0.234375 1.421875 -1.171875 2.234375q-0.921875 0.8125 -2.28125 0.8125q-1.703125 0 -2.75 -1.109375q-1.03125 -1.125 -1.03125 -3.203125q0 -1.34375 0.4375 -2.34375q0.453125 -1.015625 1.359375 -1.515625q0.921875 -0.5 1.984375 -0.5q1.359375 0 2.21875 0.6875q0.859375 0.671875 1.09375 1.9375l-1.359375 0.203125q-0.203125 -0.828125 -0.703125 -1.25q-0.484375 -0.421875 -1.1875 -0.421875q-1.0625 0 -1.734375 0.765625q-0.65625 0.75 -0.65625 2.40625q0 1.671875 0.640625 2.4375q0.640625 0.75 1.671875 0.75q0.828125 0 1.375 -0.5q0.5625 -0.515625 0.703125 -1.578125zm5.65625 1.78125l0.203125 1.25q-0.59375 0.125 -1.0625 0.125q-0.765625 0 -1.1875 -0.234375q-0.421875 -0.25 -0.59375 -0.640625q-0.171875 -0.40625 -0.171875 -1.671875l0 -4.765625l-1.03125 0l0 -1.09375l1.03125 0l0 -2.0625l1.40625 -0.84375l0 2.90625l1.40625 0l0 1.09375l-1.40625 0l0 4.84375q0 0.609375 0.0625 0.78125q0.078125 0.171875 0.25 0.28125q0.171875 0.09375 0.484375 0.09375q0.234375 0 0.609375 -0.0625zm1.3828125 -8.578125l0 -1.609375l1.40625 0l0 1.609375l-1.40625 0zm0 9.84375l0 -8.296875l1.40625 0l0 8.296875l-1.40625 0zm3.0234375 -4.15625q0 -2.296875 1.28125 -3.40625q1.078125 -0.921875 2.609375 -0.921875q1.71875 0 2.796875 1.125q1.09375 1.109375 1.09375 3.09375q0 1.59375 -0.484375 2.515625q-0.484375 0.921875 -1.40625 1.4375q-0.90625 0.5 -2.0 0.5q-1.734375 0 -2.8125 -1.109375q-1.078125 -1.125 -1.078125 -3.234375zm1.453125 0q0 1.59375 0.6875 2.390625q0.703125 0.796875 1.75 0.796875q1.046875 0 1.734375 -0.796875q0.703125 -0.796875 0.703125 -2.4375q0 -1.53125 -0.703125 -2.328125q-0.6875 -0.796875 -1.734375 -0.796875q-1.046875 0 -1.75 0.796875q-0.6875 0.78125 -0.6875 2.375zm7.9765625 4.15625l0 -8.296875l1.265625 0l0 1.171875q0.90625 -1.359375 2.640625 -1.359375q0.75 0 1.375 0.265625q0.625 0.265625 0.9375 0.703125q0.3125 0.4375 0.4375 1.046875q0.078125 0.390625 0.078125 1.359375l0 5.109375l-1.40625 0l0 -5.046875q0 -0.859375 -0.171875 -1.28125q-0.15625 -0.4375 -0.578125 -0.6875q-0.40625 -0.25 -0.96875 -0.25q-0.90625 0 -1.5625 0.578125q-0.640625 0.5625 -0.640625 2.15625l0 4.53125l-1.40625 0zm8.3359375 -2.484375l1.390625 -0.21875q0.109375 0.84375 0.640625 1.296875q0.546875 0.4375 1.5 0.4375q0.96875 0 1.4375 -0.390625q0.46875 -0.40625 0.46875 -0.9375q0 -0.46875 -0.40625 -0.75q-0.296875 -0.1875 -1.4375 -0.46875q-1.546875 -0.390625 -2.15625 -0.671875q-0.59375 -0.296875 -0.90625 -0.796875q-0.296875 -0.5 -0.296875 -1.109375q0 -0.5625 0.25 -1.03125q0.25 -0.46875 0.6875 -0.78125q0.328125 -0.25 0.890625 -0.40625q0.578125 -0.171875 1.21875 -0.171875q0.984375 0 1.71875 0.28125q0.734375 0.28125 1.078125 0.765625q0.359375 0.46875 0.5 1.28125l-1.375 0.1875q-0.09375 -0.640625 -0.546875 -1.0q-0.453125 -0.359375 -1.265625 -0.359375q-0.96875 0 -1.390625 0.328125q-0.40625 0.3125 -0.40625 0.734375q0 0.28125 0.171875 0.5q0.171875 0.21875 0.53125 0.375q0.21875 0.078125 1.25 0.359375q1.484375 0.390625 2.078125 0.65625q0.59375 0.25 0.921875 0.734375q0.34375 0.484375 0.34375 1.203125q0 0.703125 -0.421875 1.328125q-0.40625 0.609375 -1.1875 0.953125q-0.765625 0.34375 -1.734375 0.34375q-1.625 0 -2.46875 -0.671875q-0.84375 -0.671875 -1.078125 -2.0z" fill-rule="nonzero"/><path fill="#d9d9d9" d="m131.97372 163.3517l296.9449 0l0 106.92915l-296.9449 0z" fill-rule="evenodd"/><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m131.97372 163.3517l296.9449 0l0 106.92915l-296.9449 0z" fill-rule="evenodd"/><path fill="#000000" d="m144.0831 183.8717l0 -7.578125l-2.828125 0l0 -1.015625l6.8125 0l0 1.015625l-2.84375 0l0 7.578125l-1.140625 0zm4.3085938 2.390625l-0.125 -0.984375q0.34375 0.09375 0.609375 0.09375q0.34375 0 0.546875 -0.125q0.21875 -0.109375 0.359375 -0.3125q0.09375 -0.171875 0.328125 -0.796875q0.015625 -0.078125 0.09375 -0.25l-2.375 -6.234375l1.140625 0l1.296875 3.59375q0.25 0.6875 0.453125 1.453125q0.1875 -0.734375 0.4375 -1.421875l1.328125 -3.625l1.046875 0l-2.359375 6.328125q-0.390625 1.015625 -0.59375 1.40625q-0.28125 0.53125 -0.65625 0.765625q-0.359375 0.25 -0.859375 0.25q-0.296875 0 -0.671875 -0.140625zm6.046875 0l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm6.158203 -1.3125l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m241.94247 181.76233l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.173828 3.65625l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm14.199219 -0.78125q-0.546875 0.484375 -1.0625 0.703125q-0.5 0.21875 -1.09375 0.21875q-0.859375 0 -1.390625 -0.5q-0.515625 -0.515625 -0.515625 -1.3125q0 -0.515625 0.234375 -0.90625q0.234375 -0.40625 0.625 -0.640625q0.390625 -0.25 0.96875 -0.359375q0.359375 -0.078125 1.359375 -0.109375q1.0 -0.046875 1.421875 -0.21875q0.125 -0.4375 0.125 -0.71875q0 -0.375 -0.265625 -0.578125q-0.375 -0.296875 -1.078125 -0.296875q-0.671875 0 -1.09375 0.296875q-0.421875 0.296875 -0.625 0.84375l-1.0625 -0.09375q0.328125 -0.921875 1.03125 -1.40625q0.71875 -0.5 1.796875 -0.5q1.15625 0 1.828125 0.546875q0.515625 0.40625 0.515625 1.0625q0 0.5 -0.140625 1.15625l-0.34375 1.546875q-0.171875 0.734375 -0.171875 1.203125q0 0.296875 0.140625 0.84375l-1.078125 0q-0.09375 -0.3125 -0.125 -0.78125zm0.390625 -2.375q-0.21875 0.09375 -0.484375 0.140625q-0.25 0.046875 -0.84375 0.09375q-0.921875 0.078125 -1.3125 0.21875q-0.375 0.125 -0.578125 0.40625q-0.1875 0.265625 -0.1875 0.59375q0 0.453125 0.3125 0.734375q0.3125 0.28125 0.875 0.28125q0.53125 0 1.015625 -0.265625q0.484375 -0.28125 0.765625 -0.78125q0.28125 -0.5 0.4375 -1.421875zm3.5957031 -4.234375l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6191406 0l1.796875 -8.59375l1.0625 0l-1.796875 8.59375l-1.0625 0z" fill-rule="nonzero"/><path fill="#000000" d="m148.03622 199.85608l1.125 0.296875q-0.359375 1.390625 -1.28125 2.125q-0.921875 0.734375 -2.265625 0.734375q-1.390625 0 -2.265625 -0.5625q-0.875 -0.5625 -1.328125 -1.625q-0.453125 -1.078125 -0.453125 -2.3125q0 -1.34375 0.515625 -2.34375q0.515625 -1.0 1.453125 -1.515625q0.953125 -0.515625 2.09375 -0.515625q1.28125 0 2.15625 0.65625q0.890625 0.65625 1.234375 1.84375l-1.125 0.265625q-0.296875 -0.9375 -0.875 -1.359375q-0.5625 -0.4375 -1.421875 -0.4375q-0.984375 0 -1.65625 0.484375q-0.65625 0.46875 -0.9375 1.265625q-0.265625 0.796875 -0.265625 1.65625q0 1.09375 0.3125 1.90625q0.328125 0.8125 1.0 1.21875q0.671875 0.40625 1.46875 0.40625q0.953125 0 1.609375 -0.546875q0.671875 -0.546875 0.90625 -1.640625zm2.0097656 -0.09375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.673828 0l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm10.923828 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm9.939453 1.421875l1.03125 0.140625q-0.171875 1.0625 -0.875 1.671875q-0.703125 0.609375 -1.71875 0.609375q-1.28125 0 -2.0625 -0.828125q-0.765625 -0.84375 -0.765625 -2.40625q0 -1.0 0.328125 -1.75q0.34375 -0.765625 1.015625 -1.140625q0.6875 -0.375 1.5 -0.375q1.0 0 1.640625 0.515625q0.65625 0.5 0.84375 1.453125l-1.03125 0.15625q-0.140625 -0.625 -0.515625 -0.9375q-0.375 -0.328125 -0.90625 -0.328125q-0.796875 0 -1.296875 0.578125q-0.5 0.5625 -0.5 1.796875q0 1.265625 0.484375 1.828125q0.484375 0.5625 1.25 0.5625q0.625 0 1.03125 -0.375q0.421875 -0.375 0.546875 -1.171875zm4.234375 1.34375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm2.2753906 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 3.109375l0 -6.21875l0.9375 0l0 0.875q0.6875 -1.015625 1.984375 -1.015625q0.5625 0 1.03125 0.203125q0.484375 0.203125 0.71875 0.53125q0.234375 0.328125 0.328125 0.765625q0.046875 0.296875 0.046875 1.03125l0 3.828125l-1.046875 0l0 -3.78125q0 -0.65625 -0.125 -0.96875q-0.125 -0.3125 -0.4375 -0.5q-0.3125 -0.203125 -0.734375 -0.203125q-0.671875 0 -1.171875 0.4375q-0.484375 0.421875 -0.484375 1.609375l0 3.40625l-1.046875 0zm6.955078 -5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0zm0 5.015625l0 -1.203125l1.203125 0l0 1.203125l-1.203125 0z" fill-rule="nonzero"/><path fill="#000000" d="m237.37997 202.8717l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm6.861328 -2.359375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.533203 0.34375l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm8.375 1.265625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm3.9824219 2.4375l1.296875 -6.21875l1.0625 0l-0.21875 1.015625q0.59375 -0.65625 1.0625 -0.90625q0.46875 -0.25 1.015625 -0.25q0.578125 0 0.96875 0.3125q0.390625 0.296875 0.515625 0.84375q0.46875 -0.578125 0.984375 -0.859375q0.53125 -0.296875 1.109375 -0.296875q0.78125 0 1.171875 0.375q0.390625 0.359375 0.390625 1.03125q0 0.28125 -0.140625 0.9375l-0.828125 4.015625l-1.0625 0l0.859375 -4.109375q0.109375 -0.515625 0.109375 -0.71875q0 -0.3125 -0.203125 -0.484375q-0.1875 -0.171875 -0.53125 -0.171875q-0.484375 0 -0.984375 0.28125q-0.484375 0.28125 -0.765625 0.75q-0.265625 0.46875 -0.46875 1.4375l-0.625 3.015625l-1.0625 0l0.875 -4.203125q0.09375 -0.421875 0.09375 -0.609375q0 -0.296875 -0.1875 -0.484375q-0.1875 -0.1875 -0.5 -0.1875q-0.453125 0 -0.953125 0.28125q-0.484375 0.28125 -0.796875 0.796875q-0.3125 0.515625 -0.515625 1.46875l-0.609375 2.9375l-1.0625 0zm9.605469 2.40625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm5.796875 -2.40625l0.25 -1.203125l1.203125 0l-0.25 1.203125l-1.203125 0zm7.3339844 -2.265625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm1.90625 -0.09375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125z" fill-rule="nonzero"/><path fill="#000000" d="m236.84872 219.26233l1.796875 -8.609375l0.984375 0l-0.1875 0.859375q0.546875 -0.5625 0.96875 -0.78125q0.4375 -0.21875 0.921875 -0.21875q0.890625 0 1.46875 0.65625q0.59375 0.640625 0.59375 1.84375q0 0.96875 -0.328125 1.765625q-0.3125 0.796875 -0.78125 1.296875q-0.46875 0.484375 -0.953125 0.71875q-0.484375 0.21875 -0.984375 0.21875q-1.125 0 -1.734375 -1.140625l-0.703125 3.390625l-1.0625 0zm2.09375 -4.9375q0 0.703125 0.109375 0.96875q0.140625 0.375 0.46875 0.609375q0.34375 0.234375 0.78125 0.234375q0.921875 0 1.484375 -1.015625q0.5625 -1.03125 0.5625 -2.109375q0 -0.78125 -0.390625 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.40625 0 -0.75 0.21875q-0.34375 0.21875 -0.640625 0.640625q-0.296875 0.421875 -0.5 1.046875q-0.1875 0.609375 -0.1875 1.0625zm5.298828 0.1875q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm6.4648438 -0.859375l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm4.435547 -0.015625l1.078125 -0.109375q-0.015625 0.234375 -0.015625 0.28125q0 0.375 0.1875 0.78125q0.203125 0.390625 0.53125 0.59375q0.34375 0.203125 0.71875 0.203125q0.5 0 1.0 -0.328125q0.515625 -0.34375 0.828125 -0.984375q0.3125 -0.65625 0.3125 -1.296875q0 -0.71875 -0.421875 -1.15625q-0.421875 -0.4375 -1.109375 -0.4375q-0.46875 0 -0.890625 0.234375q-0.40625 0.21875 -0.765625 0.65625l-0.921875 -0.0625l1.296875 -4.390625l4.203125 0l-0.21875 0.96875l-3.25 0l-0.65625 2.1875q0.375 -0.265625 0.75 -0.390625q0.390625 -0.140625 0.796875 -0.140625q0.984375 0 1.609375 0.65625q0.640625 0.640625 0.640625 1.78125q0 0.984375 -0.4375 1.828125q-0.4375 0.828125 -1.203125 1.28125q-0.75 0.4375 -1.625 0.4375q-0.75 0 -1.3125 -0.328125q-0.5625 -0.328125 -0.859375 -0.90625q-0.28125 -0.59375 -0.28125 -1.1875q0 -0.0625 0.015625 -0.171875zm8.533203 -2.265625q-0.46875 -0.265625 -0.71875 -0.671875q-0.234375 -0.421875 -0.234375 -0.890625q0 -0.78125 0.5625 -1.453125q0.75 -0.890625 2.03125 -0.890625q1.125 0 1.78125 0.609375q0.65625 0.609375 0.65625 1.484375q0 0.625 -0.359375 1.125q-0.34375 0.5 -1.09375 0.8125q0.515625 0.3125 0.734375 0.671875q0.28125 0.484375 0.28125 1.109375q0 1.15625 -0.8125 2.0625q-0.8125 0.90625 -2.171875 0.90625q-1.09375 0 -1.78125 -0.671875q-0.6875 -0.671875 -0.6875 -1.671875q0 -0.9375 0.484375 -1.609375q0.5 -0.6875 1.328125 -0.921875zm0.09375 -1.515625q0 0.546875 0.34375 0.890625q0.359375 0.328125 0.984375 0.328125q0.71875 0 1.171875 -0.4375q0.453125 -0.453125 0.453125 -1.09375q0 -0.546875 -0.359375 -0.890625q-0.34375 -0.34375 -0.96875 -0.34375q-0.46875 0 -0.859375 0.21875q-0.390625 0.21875 -0.578125 0.59375q-0.1875 0.375 -0.1875 0.734375zm-0.828125 4.140625q0 0.359375 0.171875 0.6875q0.171875 0.328125 0.515625 0.515625q0.359375 0.1875 0.8125 0.1875q0.859375 0 1.390625 -0.796875q0.421875 -0.640625 0.421875 -1.375q0 -0.59375 -0.390625 -0.96875q-0.390625 -0.390625 -1.015625 -0.390625q-0.796875 0 -1.359375 0.59375q-0.546875 0.59375 -0.546875 1.546875zm6.439453 2.09375q0.140625 -0.875 0.609375 -2.09375q0.546875 -1.46875 1.421875 -2.90625q0.890625 -1.453125 1.96875 -2.5l-4.28125 0l0.203125 -0.96875l5.484375 0l-0.203125 0.96875q-1.390625 1.21875 -2.4375 3.15625q-1.203125 2.234375 -1.65625 4.34375l-1.109375 0z" fill-rule="nonzero"/><path fill="#000000" d="m141.8956 236.8717l0 -8.59375l3.25 0q0.84375 0 1.296875 0.078125q0.640625 0.109375 1.0625 0.40625q0.4375 0.296875 0.6875 0.828125q0.265625 0.53125 0.265625 1.171875q0 1.09375 -0.703125 1.859375q-0.6875 0.75 -2.515625 0.75l-2.203125 0l0 3.5l-1.140625 0zm1.140625 -4.5l2.21875 0q1.109375 0 1.5625 -0.40625q0.46875 -0.421875 0.46875 -1.171875q0 -0.53125 -0.28125 -0.90625q-0.265625 -0.390625 -0.703125 -0.515625q-0.296875 -0.078125 -1.0625 -0.078125l-2.203125 0l0 3.078125zm6.7226562 4.5l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm3.6210938 -3.109375q0 -1.734375 0.953125 -2.5625q0.796875 -0.6875 1.953125 -0.6875q1.28125 0 2.09375 0.84375q0.828125 0.828125 0.828125 2.3125q0 1.203125 -0.359375 1.890625q-0.359375 0.6875 -1.0625 1.078125q-0.6875 0.375 -1.5 0.375q-1.296875 0 -2.109375 -0.828125q-0.796875 -0.84375 -0.796875 -2.421875zm1.078125 0q0 1.1875 0.515625 1.78125q0.53125 0.59375 1.3125 0.59375q0.796875 0 1.3125 -0.59375q0.515625 -0.59375 0.515625 -1.8125q0 -1.15625 -0.53125 -1.75q-0.515625 -0.59375 -1.296875 -0.59375q-0.78125 0 -1.3125 0.59375q-0.515625 0.578125 -0.515625 1.78125zm5.986328 5.5l0 -8.609375l0.953125 0l0 0.796875q0.34375 -0.46875 0.765625 -0.703125q0.4375 -0.234375 1.046875 -0.234375q0.796875 0 1.40625 0.40625q0.609375 0.40625 0.90625 1.15625q0.3125 0.75 0.3125 1.640625q0 0.953125 -0.34375 1.71875q-0.328125 0.765625 -0.984375 1.171875q-0.65625 0.40625 -1.375 0.40625q-0.53125 0 -0.953125 -0.21875q-0.421875 -0.234375 -0.6875 -0.5625l0 3.03125l-1.046875 0zm0.953125 -5.46875q0 1.203125 0.484375 1.78125q0.484375 0.5625 1.171875 0.5625q0.703125 0 1.203125 -0.59375q0.5 -0.59375 0.5 -1.84375q0 -1.1875 -0.484375 -1.765625q-0.484375 -0.59375 -1.171875 -0.59375q-0.671875 0 -1.1875 0.625q-0.515625 0.625 -0.515625 1.828125zm9.970703 1.078125l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.861328 3.703125l0 -6.21875l0.953125 0l0 0.9375q0.359375 -0.65625 0.65625 -0.859375q0.3125 -0.21875 0.6875 -0.21875q0.53125 0 1.078125 0.328125l-0.359375 0.984375q-0.390625 -0.234375 -0.765625 -0.234375q-0.359375 0 -0.640625 0.21875q-0.265625 0.203125 -0.375 0.578125q-0.1875 0.5625 -0.1875 1.21875l0 3.265625l-1.046875 0zm6.3085938 -0.9375l0.15625 0.921875q-0.453125 0.09375 -0.796875 0.09375q-0.578125 0 -0.890625 -0.171875q-0.3125 -0.1875 -0.453125 -0.484375q-0.125 -0.296875 -0.125 -1.25l0 -3.578125l-0.765625 0l0 -0.8125l0.765625 0l0 -1.546875l1.046875 -0.625l0 2.171875l1.0625 0l0 0.8125l-1.0625 0l0 3.640625q0 0.453125 0.046875 0.578125q0.0625 0.125 0.1875 0.203125q0.125 0.078125 0.359375 0.078125q0.1875 0 0.46875 -0.03125zm1.0371094 -6.4375l0 -1.21875l1.0625 0l0 1.21875l-1.0625 0zm0 7.375l0 -6.21875l1.0625 0l0 6.21875l-1.0625 0zm6.9160156 -2.0l1.09375 0.125q-0.25 0.953125 -0.953125 1.484375q-0.703125 0.53125 -1.78125 0.53125q-1.359375 0 -2.171875 -0.84375q-0.796875 -0.84375 -0.796875 -2.359375q0 -1.5625 0.8125 -2.421875q0.8125 -0.875 2.09375 -0.875q1.25 0 2.03125 0.84375q0.796875 0.84375 0.796875 2.390625q0 0.09375 0 0.28125l-4.640625 0q0.0625 1.03125 0.578125 1.578125q0.515625 0.53125 1.296875 0.53125q0.578125 0 0.984375 -0.296875q0.421875 -0.3125 0.65625 -0.96875zm-3.453125 -1.703125l3.46875 0q-0.0625 -0.796875 -0.390625 -1.1875q-0.515625 -0.609375 -1.3125 -0.609375q-0.734375 0 -1.234375 0.484375q-0.484375 0.484375 -0.53125 1.3125zm5.455078 1.84375l1.03125 -0.15625q0.09375 0.625 0.484375 0.953125q0.40625 0.328125 1.140625 0.328125q0.71875 0 1.0625 -0.28125q0.359375 -0.296875 0.359375 -0.703125q0 -0.359375 -0.3125 -0.5625q-0.21875 -0.140625 -1.078125 -0.359375q-1.15625 -0.296875 -1.609375 -0.5q-0.4375 -0.21875 -0.671875 -0.59375q-0.234375 -0.375 -0.234375 -0.84375q0 -0.40625 0.1875 -0.765625q0.1875 -0.359375 0.515625 -0.59375q0.25 -0.171875 0.671875 -0.296875q0.421875 -0.125 0.921875 -0.125q0.71875 0 1.265625 0.21875q0.5625 0.203125 0.828125 0.5625q0.265625 0.359375 0.359375 0.953125l-1.03125 0.140625q-0.0625 -0.46875 -0.40625 -0.734375q-0.328125 -0.28125 -0.953125 -0.28125q-0.71875 0 -1.03125 0.25q-0.3125 0.234375 -0.3125 0.5625q0 0.203125 0.125 0.359375q0.140625 0.171875 0.40625 0.28125q0.15625 0.0625 0.9375 0.265625q1.125 0.3125 1.5625 0.5q0.4375 0.1875 0.6875 0.546875q0.25 0.359375 0.25 0.90625q0 0.53125 -0.3125 1.0q-0.296875 0.453125 -0.875 0.71875q-0.578125 0.25 -1.3125 0.25q-1.21875 0 -1.859375 -0.5q-0.625 -0.515625 -0.796875 -1.5z" fill-rule="nonzero"/><path fill="#000000" d="m237.47372 234.7467l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.140625 1.0q-1.109375 1.265625 -2.28125 1.265625q-0.71875 0 -1.171875 -0.40625q-0.4375 -0.421875 -0.4375 -1.015625q0 -0.390625 0.203125 -1.34375l0.75 -3.59375l1.0625 0l-0.84375 3.96875q-0.09375 0.5 -0.09375 0.78125q0 0.34375 0.203125 0.546875q0.21875 0.1875 0.640625 0.1875q0.4375 0 0.859375 -0.203125q0.4375 -0.21875 0.734375 -0.59375q0.3125 -0.375 0.5 -0.875q0.140625 -0.3125 0.296875 -1.125l0.5625 -2.6875l1.0625 0l-1.296875 6.21875l-0.984375 0l0.234375 -1.125zm2.4394531 1.125l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm6.611328 -4.828125l0.25 -1.203125l1.046875 0l-0.25 1.203125l-1.046875 0zm-3.359375 9.734375l0.1875 -0.90625q0.359375 0.09375 0.640625 0.09375q0.34375 0 0.546875 -0.234375q0.203125 -0.21875 0.421875 -1.234375l1.296875 -6.28125l1.0625 0l-1.34375 6.46875q-0.25 1.21875 -0.578125 1.65625q-0.4375 0.578125 -1.234375 0.578125q-0.40625 0 -1.0 -0.140625zm9.087891 -4.453125l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm9.470703 1.390625l1.0625 0.109375q-0.390625 1.171875 -1.125 1.734375q-0.734375 0.5625 -1.671875 0.5625q-1.015625 0 -1.65625 -0.65625q-0.625 -0.65625 -0.625 -1.828125q0 -1.03125 0.40625 -2.015625q0.40625 -0.984375 1.15625 -1.484375q0.75 -0.515625 1.71875 -0.515625q1.0 0 1.578125 0.5625q0.59375 0.5625 0.59375 1.5l-1.03125 0.0625q-0.015625 -0.59375 -0.359375 -0.921875q-0.328125 -0.328125 -0.875 -0.328125q-0.640625 0 -1.109375 0.40625q-0.46875 0.390625 -0.734375 1.21875q-0.265625 0.828125 -0.265625 1.578125q0 0.796875 0.34375 1.203125q0.359375 0.390625 0.875 0.390625q0.515625 0 0.984375 -0.390625q0.46875 -0.390625 0.734375 -1.1875zm4.1875 1.40625l-0.171875 0.859375q-0.375 0.109375 -0.734375 0.109375q-0.640625 0 -1.015625 -0.3125q-0.28125 -0.234375 -0.28125 -0.640625q0 -0.203125 0.15625 -0.9375l0.75 -3.625l-0.828125 0l0.171875 -0.8125l0.828125 0l0.328125 -1.53125l1.203125 -0.734375l-0.46875 2.265625l1.046875 0l-0.171875 0.8125l-1.046875 0l-0.71875 3.4375q-0.140625 0.65625 -0.140625 0.796875q0 0.1875 0.109375 0.28125q0.109375 0.09375 0.359375 0.09375q0.359375 0 0.625 -0.0625zm10.542969 -4.1875l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm1.6835938 7.0l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm16.835938 -3.03125l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm7.9160156 1.234375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/><path fill="#000000" d="m237.37997 250.8717l1.78125 -8.59375l1.0625 0l-0.640625 3.078125q0.515625 -0.46875 0.921875 -0.65625q0.40625 -0.1875 0.859375 -0.1875q0.859375 0 1.4375 0.65625q0.59375 0.640625 0.59375 1.875q0 0.828125 -0.234375 1.515625q-0.234375 0.6875 -0.578125 1.15625q-0.34375 0.46875 -0.71875 0.75q-0.359375 0.265625 -0.75 0.40625q-0.390625 0.140625 -0.75 0.140625q-0.609375 0 -1.078125 -0.328125q-0.46875 -0.328125 -0.734375 -0.984375l-0.25 1.171875l-0.921875 0zm1.5625 -2.5625l0 0.203125q0 0.796875 0.375 1.21875q0.375 0.40625 0.953125 0.40625q0.546875 0 1.015625 -0.375q0.46875 -0.390625 0.765625 -1.21875q0.296875 -0.828125 0.296875 -1.53125q0 -0.78125 -0.375 -1.21875q-0.375 -0.4375 -0.9375 -0.4375q-0.5625 0 -1.046875 0.453125q-0.484375 0.4375 -0.8125 1.359375q-0.234375 0.6875 -0.234375 1.140625zm5.298828 0.203125q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm9.626953 1.5625q-0.90625 1.046875 -1.890625 1.046875q-0.890625 0 -1.484375 -0.65625q-0.578125 -0.65625 -0.578125 -1.890625q0 -1.140625 0.453125 -2.078125q0.46875 -0.9375 1.171875 -1.40625q0.703125 -0.46875 1.40625 -0.46875q1.15625 0 1.75 1.109375l0.703125 -3.34375l1.046875 0l-1.78125 8.59375l-0.984375 0l0.1875 -0.90625zm-2.90625 -1.703125q0 0.65625 0.125 1.03125q0.140625 0.375 0.4375 0.625q0.3125 0.25 0.75 0.25q0.71875 0 1.3125 -0.75q0.78125 -1.0 0.78125 -2.46875q0 -0.734375 -0.390625 -1.140625q-0.390625 -0.421875 -0.96875 -0.421875q-0.375 0 -0.703125 0.171875q-0.3125 0.15625 -0.625 0.5625q-0.296875 0.40625 -0.515625 1.046875q-0.203125 0.625 -0.203125 1.09375zm4.986328 5.015625l0.0625 -1.0q0.328125 0.09375 0.640625 0.09375q0.328125 0 0.515625 -0.140625q0.265625 -0.203125 0.5625 -0.734375l0.34375 -0.609375l-1.03125 -6.234375l1.046875 0l0.46875 3.140625q0.140625 0.9375 0.234375 1.859375l2.78125 -5.0l1.109375 0l-3.96875 7.046875q-0.578125 1.03125 -1.03125 1.359375q-0.4375 0.34375 -1.015625 0.34375q-0.359375 0 -0.71875 -0.125zm16.083984 -7.453125l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm0 2.609375l-5.671875 0l0 -0.984375l5.671875 0l0 0.984375zm8.185547 -4.5625l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.1875 -0.953125 0.609375 -1.390625q0.421875 -0.4375 0.984375 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.921875 1.28125l0.65625 0zm-1.875 0l-0.25 1.203125l-1.203125 0l0.21875 -1.046875q0.203125 -0.953125 0.609375 -1.390625q0.421875 -0.4375 1.0 -0.5l-0.09375 0.453125q-0.6875 0.1875 -0.9375 1.28125l0.65625 0zm8.511719 3.96875l1.140625 0.171875q-0.546875 1.484375 -1.578125 2.25q-1.03125 0.75 -2.3125 0.75q-1.5625 0 -2.484375 -0.953125q-0.90625 -0.953125 -0.90625 -2.734375q0 -2.3125 1.390625 -3.84375q1.25 -1.34375 3.09375 -1.34375q1.359375 0 2.203125 0.734375q0.84375 0.734375 0.984375 1.96875l-1.078125 0.09375q-0.15625 -0.9375 -0.6875 -1.390625q-0.53125 -0.453125 -1.375 -0.453125q-1.578125 0 -2.546875 1.390625q-0.84375 1.203125 -0.84375 2.875q0 1.3125 0.640625 2.015625q0.65625 0.703125 1.703125 0.703125q0.890625 0 1.609375 -0.578125q0.71875 -0.59375 1.046875 -1.65625zm1.9472656 3.03125l1.796875 -8.59375l3.59375 0q0.921875 0 1.390625 0.21875q0.46875 0.21875 0.765625 0.734375q0.3125 0.515625 0.3125 1.15625q0 0.53125 -0.21875 1.09375q-0.21875 0.546875 -0.546875 0.90625q-0.328125 0.359375 -0.671875 0.546875q-0.34375 0.171875 -0.71875 0.25q-0.828125 0.203125 -1.671875 0.203125l-2.15625 0l-0.71875 3.484375l-1.15625 0zm2.078125 -4.453125l1.890625 0q1.109375 0 1.625 -0.234375q0.515625 -0.25 0.828125 -0.734375q0.3125 -0.484375 0.3125 -1.03125q0 -0.421875 -0.171875 -0.6875q-0.15625 -0.265625 -0.46875 -0.390625q-0.296875 -0.125 -1.140625 -0.125l-2.203125 0l-0.671875 3.203125zm7.7851562 -4.140625l1.15625 0l-1.109375 5.28125q-0.125 0.65625 -0.125 0.96875q0 0.703125 0.53125 1.125q0.546875 0.421875 1.375 0.421875q0.65625 0 1.21875 -0.296875q0.578125 -0.3125 0.90625 -0.890625q0.328125 -0.59375 0.59375 -1.875l0.984375 -4.734375l1.140625 0l-1.046875 5.046875q-0.265625 1.28125 -0.703125 2.046875q-0.4375 0.75 -1.21875 1.203125q-0.78125 0.453125 -1.8125 0.453125q-0.96875 0 -1.6875 -0.328125q-0.703125 -0.328125 -1.0625 -0.890625q-0.359375 -0.5625 -0.359375 -1.28125q0 -0.453125 0.25 -1.5625l0.96875 -4.6875zm10.21875 6.234375q0 -1.828125 1.0625 -3.015625q0.890625 -0.984375 2.328125 -0.984375q1.125 0 1.8125 0.703125q0.6875 0.703125 0.6875 1.890625q0 1.078125 -0.4375 2.0q-0.4375 0.921875 -1.234375 1.421875q-0.796875 0.484375 -1.6875 0.484375q-0.71875 0 -1.3125 -0.3125q-0.59375 -0.3125 -0.90625 -0.875q-0.3125 -0.578125 -0.3125 -1.3125zm1.046875 -0.109375q0 0.875 0.421875 1.328125q0.421875 0.453125 1.078125 0.453125q0.34375 0 0.671875 -0.125q0.34375 -0.140625 0.625 -0.421875q0.28125 -0.28125 0.484375 -0.640625q0.203125 -0.359375 0.328125 -0.78125q0.1875 -0.578125 0.1875 -1.109375q0 -0.84375 -0.4375 -1.3125q-0.421875 -0.46875 -1.0625 -0.46875q-0.5 0 -0.90625 0.25q-0.40625 0.234375 -0.75 0.6875q-0.328125 0.453125 -0.484375 1.0625q-0.15625 0.609375 -0.15625 1.078125zm5.439453 2.46875l1.296875 -6.21875l0.953125 0l-0.21875 1.078125q0.625 -0.640625 1.171875 -0.921875q0.546875 -0.296875 1.109375 -0.296875q0.75 0 1.171875 0.40625q0.4375 0.40625 0.4375 1.09375q0 0.34375 -0.140625 1.09375l-0.796875 3.765625l-1.0625 0l0.828125 -3.9375q0.125 -0.578125 0.125 -0.859375q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.8125 0 -1.453125 0.59375q-0.640625 0.578125 -0.9375 2.0l-0.609375 2.890625l-1.046875 0zm10.4296875 -3.59375q0.453125 0 0.78125 -0.234375q0.34375 -0.234375 0.546875 -0.703125q0.171875 -0.34375 0.375 -1.3125q0.21875 -0.984375 0.34375 -1.34375q0.15625 -0.484375 0.375 -0.78125q0.21875 -0.3125 0.46875 -0.46875q0.25 -0.171875 0.625 -0.25q0.203125 -0.046875 0.671875 -0.046875l0.328125 0l-0.203125 0.921875l-0.171875 0q-0.5 0 -0.71875 0.125q-0.21875 0.109375 -0.34375 0.375q-0.109375 0.25 -0.3125 1.125q-0.234375 1.171875 -0.453125 1.6875q-0.203125 0.5 -0.53125 0.828125q-0.3125 0.3125 -0.90625 0.5625q0.421875 0.203125 0.625 0.53125q0.203125 0.328125 0.203125 0.875q0 0.453125 -0.265625 1.671875q-0.1875 0.859375 -0.1875 1.078125q0 0.21875 0.09375 0.34375q0.0625 0.109375 0.21875 0.15625q0.171875 0.0625 0.703125 0.0625l-0.1875 0.921875l-0.328125 0q-0.546875 0 -0.765625 -0.078125q-0.34375 -0.125 -0.546875 -0.40625q-0.1875 -0.265625 -0.1875 -0.734375q0 -0.390625 0.265625 -1.671875q0.203125 -0.96875 0.203125 -1.3125q0 -0.46875 -0.234375 -0.703125q-0.234375 -0.25 -0.6875 -0.25l0.203125 -0.96875zm4.0078125 0q0.453125 0 0.78125 -0.234375q0.34375 -0.234375 0.546875 -0.703125q0.171875 -0.34375 0.375 -1.3125q0.21875 -0.984375 0.34375 -1.34375q0.15625 -0.484375 0.375 -0.78125q0.21875 -0.3125 0.46875 -0.46875q0.25 -0.171875 0.625 -0.25q0.203125 -0.046875 0.671875 -0.046875l0.328125 0l-0.203125 0.921875l-0.171875 0q-0.5 0 -0.71875 0.125q-0.21875 0.109375 -0.34375 0.375q-0.109375 0.25 -0.3125 1.125q-0.234375 1.171875 -0.453125 1.6875q-0.203125 0.5 -0.53125 0.828125q-0.3125 0.3125 -0.90625 0.5625q0.421875 0.203125 0.625 0.53125q0.203125 0.328125 0.203125 0.875q0 0.453125 -0.265625 1.671875q-0.1875 0.859375 -0.1875 1.078125q0 0.21875 0.09375 0.34375q0.0625 0.109375 0.21875 0.15625q0.171875 0.0625 0.703125 0.0625l-0.1875 0.921875l-0.328125 0q-0.546875 0 -0.765625 -0.078125q-0.34375 -0.125 -0.546875 -0.40625q-0.1875 -0.265625 -0.1875 -0.734375q0 -0.390625 0.265625 -1.671875q0.203125 -0.96875 0.203125 -1.3125q0 -0.46875 -0.234375 -0.703125q-0.234375 -0.25 -0.6875 -0.25l0.203125 -0.96875zm3.6796875 1.46875l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm10.46875 0.015625l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm5.5585938 0l-1.015625 -6.21875l1.03125 0l0.53125 3.421875q0.09375 0.5625 0.21875 1.828125q0.296875 -0.65625 0.78125 -1.515625l2.078125 -3.734375l1.109375 0l-3.5625 6.21875l-1.171875 0zm9.0 -2.109375l1.03125 0.09375q-0.21875 0.765625 -1.03125 1.46875q-0.796875 0.6875 -1.890625 0.6875q-0.703125 0 -1.28125 -0.3125q-0.578125 -0.328125 -0.875 -0.9375q-0.296875 -0.609375 -0.296875 -1.390625q0 -1.015625 0.46875 -1.96875q0.46875 -0.96875 1.21875 -1.421875q0.75 -0.46875 1.625 -0.46875q1.109375 0 1.765625 0.6875q0.671875 0.6875 0.671875 1.890625q0 0.453125 -0.078125 0.9375l-4.578125 0q-0.03125 0.171875 -0.03125 0.328125q0 0.875 0.40625 1.328125q0.40625 0.453125 0.984375 0.453125q0.546875 0 1.0625 -0.34375q0.53125 -0.359375 0.828125 -1.03125zm-3.078125 -1.546875l3.484375 0q0.015625 -0.171875 0.015625 -0.234375q0 -0.796875 -0.40625 -1.21875q-0.390625 -0.421875 -1.015625 -0.421875q-0.6875 0 -1.25 0.46875q-0.5625 0.46875 -0.828125 1.40625zm5.189453 3.65625l1.296875 -6.21875l0.9375 0l-0.265625 1.265625q0.484375 -0.71875 0.9375 -1.0625q0.46875 -0.34375 0.9375 -0.34375q0.328125 0 0.78125 0.21875l-0.4375 0.984375q-0.265625 -0.1875 -0.59375 -0.1875q-0.5625 0 -1.15625 0.625q-0.578125 0.609375 -0.90625 2.21875l-0.53125 2.5l-1.0 0zm7.2929688 -3.59375l-0.203125 0.96875q-0.4375 0 -0.78125 0.234375q-0.328125 0.234375 -0.515625 0.640625q-0.1875 0.40625 -0.40625 1.390625q-0.21875 0.984375 -0.3125 1.3125q-0.171875 0.5 -0.390625 0.796875q-0.21875 0.3125 -0.484375 0.46875q-0.25 0.171875 -0.609375 0.265625q-0.203125 0.046875 -0.6875 0.046875l-0.328125 0l0.203125 -0.921875l0.1875 0q0.5 0 0.71875 -0.125q0.21875 -0.125 0.359375 -0.421875q0.09375 -0.21875 0.28125 -1.09375q0.234375 -1.109375 0.40625 -1.546875q0.234375 -0.59375 0.59375 -0.953125q0.359375 -0.359375 0.890625 -0.578125q-0.453125 -0.234375 -0.640625 -0.546875q-0.171875 -0.3125 -0.171875 -0.859375q0 -0.453125 0.25 -1.671875q0.1875 -0.84375 0.1875 -1.078125q0 -0.296875 -0.15625 -0.421875q-0.15625 -0.125 -0.671875 -0.125l-0.1875 0l0.203125 -0.921875l0.328125 0q0.546875 0 0.765625 0.078125q0.34375 0.109375 0.53125 0.390625q0.203125 0.265625 0.203125 0.734375q0 0.390625 -0.203125 1.296875q-0.28125 1.359375 -0.28125 1.6875q0 0.46875 0.234375 0.71875q0.234375 0.234375 0.6875 0.234375zm4.0078125 0l-0.203125 0.96875q-0.4375 0 -0.78125 0.234375q-0.328125 0.234375 -0.515625 0.640625q-0.1875 0.40625 -0.40625 1.390625q-0.21875 0.984375 -0.3125 1.3125q-0.171875 0.5 -0.390625 0.796875q-0.21875 0.3125 -0.484375 0.46875q-0.25 0.171875 -0.609375 0.265625q-0.203125 0.046875 -0.6875 0.046875l-0.328125 0l0.203125 -0.921875l0.1875 0q0.5 0 0.71875 -0.125q0.21875 -0.125 0.359375 -0.421875q0.09375 -0.21875 0.28125 -1.09375q0.234375 -1.109375 0.40625 -1.546875q0.234375 -0.59375 0.59375 -0.953125q0.359375 -0.359375 0.890625 -0.578125q-0.453125 -0.234375 -0.640625 -0.546875q-0.171875 -0.3125 -0.171875 -0.859375q0 -0.453125 0.25 -1.671875q0.1875 -0.84375 0.1875 -1.078125q0 -0.296875 -0.15625 -0.421875q-0.15625 -0.125 -0.671875 -0.125l-0.1875 0l0.203125 -0.921875l0.328125 0q0.546875 0 0.765625 0.078125q0.34375 0.109375 0.53125 0.390625q0.203125 0.265625 0.203125 0.734375q0 0.390625 -0.203125 1.296875q-0.28125 1.359375 -0.28125 1.6875q0 0.46875 0.234375 0.71875q0.234375 0.234375 0.6875 0.234375zm5.544922 -3.796875l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.8066406 -2.125l1.0625 -0.0625q0 0.453125 0.140625 0.78125q0.140625 0.3125 0.515625 0.515625q0.375 0.203125 0.875 0.203125q0.703125 0 1.046875 -0.28125q0.359375 -0.28125 0.359375 -0.65625q0 -0.28125 -0.203125 -0.515625q-0.21875 -0.25 -1.0625 -0.609375q-0.84375 -0.359375 -1.078125 -0.515625q-0.390625 -0.234375 -0.59375 -0.5625q-0.1875 -0.328125 -0.1875 -0.75q0 -0.734375 0.578125 -1.25q0.59375 -0.53125 1.640625 -0.53125q1.171875 0 1.78125 0.546875q0.625 0.53125 0.640625 1.421875l-1.03125 0.0625q-0.03125 -0.5625 -0.40625 -0.890625q-0.375 -0.328125 -1.0625 -0.328125q-0.546875 0 -0.859375 0.25q-0.296875 0.25 -0.296875 0.546875q0 0.296875 0.265625 0.515625q0.171875 0.15625 0.90625 0.46875q1.21875 0.53125 1.53125 0.828125q0.515625 0.5 0.515625 1.1875q0 0.46875 -0.296875 0.921875q-0.28125 0.4375 -0.859375 0.703125q-0.578125 0.265625 -1.375 0.265625q-1.078125 0 -1.828125 -0.53125q-0.765625 -0.53125 -0.71875 -1.734375zm9.240234 2.125l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm8.173828 -7.390625l0.25 -1.203125l1.0625 0l-0.265625 1.203125l-1.046875 0zm-1.546875 7.390625l1.296875 -6.21875l1.0625 0l-1.296875 6.21875l-1.0625 0zm2.6503906 0.5625l1.0625 0.09375q0 0.375 0.09375 0.546875q0.09375 0.1875 0.3125 0.28125q0.296875 0.140625 0.75 0.140625q0.953125 0 1.375 -0.5q0.28125 -0.34375 0.515625 -1.453125l0.109375 -0.515625q-0.828125 0.84375 -1.765625 0.84375q-0.9375 0 -1.578125 -0.6875q-0.625 -0.703125 -0.625 -1.96875q0 -1.046875 0.5 -1.921875q0.5 -0.890625 1.1875 -1.328125q0.6875 -0.453125 1.421875 -0.453125q1.21875 0 1.890625 1.15625l0.203125 -1.015625l0.984375 0l-1.265625 6.0q-0.203125 1.0 -0.546875 1.546875q-0.328125 0.546875 -0.921875 0.84375q-0.59375 0.3125 -1.375 0.3125q-0.75 0 -1.296875 -0.1875q-0.53125 -0.1875 -0.796875 -0.5625q-0.265625 -0.375 -0.265625 -0.859375q0 -0.140625 0.03125 -0.3125zm1.328125 -3.3125q0 0.640625 0.109375 0.953125q0.1875 0.453125 0.5 0.6875q0.328125 0.234375 0.734375 0.234375q0.515625 0 1.03125 -0.359375q0.515625 -0.359375 0.828125 -1.125q0.328125 -0.78125 0.328125 -1.46875q0 -0.765625 -0.421875 -1.21875q-0.421875 -0.46875 -1.046875 -0.46875q-0.390625 0 -0.765625 0.21875q-0.359375 0.203125 -0.671875 0.625q-0.3125 0.421875 -0.46875 1.015625q-0.15625 0.59375 -0.15625 0.90625zm5.408203 2.75l1.78125 -8.59375l1.0625 0l-0.6875 3.296875q0.59375 -0.5625 1.09375 -0.8125q0.515625 -0.25 1.0625 -0.25q0.765625 0 1.1875 0.40625q0.4375 0.40625 0.4375 1.078125q0 0.328125 -0.1875 1.203125l-0.765625 3.671875l-1.0625 0l0.796875 -3.765625q0.171875 -0.828125 0.171875 -1.03125q0 -0.3125 -0.21875 -0.5q-0.203125 -0.1875 -0.609375 -0.1875q-0.578125 0 -1.09375 0.296875q-0.515625 0.296875 -0.8125 0.828125q-0.296875 0.515625 -0.546875 1.6875l-0.5625 2.671875l-1.046875 0zm7.892578 -7.359375l0.25 -1.203125l1.203125 0l-0.21875 1.0625q-0.203125 0.9375 -0.625 1.375q-0.40625 0.4375 -0.984375 0.515625l0.109375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0zm1.921875 0l0.25 -1.203125l1.21875 0l-0.234375 1.0625q-0.1875 0.9375 -0.609375 1.375q-0.421875 0.4375 -0.984375 0.515625l0.09375 -0.46875q0.6875 -0.1875 0.921875 -1.28125l-0.65625 0z" fill-rule="nonzero"/></g></svg> \ No newline at end of file diff --git a/docs/user/alerting/index.asciidoc b/docs/user/alerting/index.asciidoc new file mode 100644 index 0000000000000..b4f7e6af3d61c --- /dev/null +++ b/docs/user/alerting/index.asciidoc @@ -0,0 +1,202 @@ +[role="xpack"] +[[alerting-getting-started]] += Alerting and Actions + +beta[] + +-- + +Alerting allows you to detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, <<xpack-siem,*SIEM*>>, <<xpack-uptime,*Uptime*>>, can be centrally managed from the <<management,*Management*>> UI, and provides a set of built-in <<action-types, actions>> and <<alert-types, alerts>> for you to use. + +image::images/alerting-overview.png[Alerts and actions UI] + +[IMPORTANT] +============================================== +To make sure you can access alerting and actions, see the <<alerting-setup-prerequisites, setup and pre-requisites>> section. +============================================== + +[float] +== Concepts and terminology + +*Alerts* work by running checks on a schedule to detect conditions. When a condition is met, the alert tracks it as an *alert instance* and responds by triggering one or more *actions*. +Actions typically involve interaction with {kib} services or third party integrations. *Connectors* allow actions to talk to these services and integrations. +This section describes all of these elements and how they operate together. + +[float] +=== What is an alert? + +An alert specifies a background task that runs on the {kib} server to check for specific conditions. It consists of three main parts: + +* *Conditions*: what needs to be detected? +* *Schedule*: when/how often should detection checks run? +* *Actions*: what happens when a condition is detected? + +For example, when monitoring a set of servers, an alert might check for average CPU usage > 0.9 on each server for the two minutes (condition), checked every minute (schedule), sending a warning email message via SMTP with subject `CPU on {{server}} is high` (action). + +image::images/what-is-an-alert.svg[Three components of an alert] + +The following sections each part of the alert is described in more detail. + +[float] +[[alerting-concepts-conditions]] +==== Conditions + +Under the hood, {kib} alerts detect conditions by running javascript function on the {kib} server, which gives it flexibility to support a wide range of detections, anything from the results of a simple {es} query to heavy computations involving data from multiple sources or external systems. + +These detections are packaged and exposed as *alert types*. An alert type hides the underlying details of the detection, and exposes a set of parameters +to control the details of the conditions to detect. + +For example, an <<alert-types, index threshold alert type>> lets you specify the index to query, an aggregation field, and a time window, but the details of the underlying {es} query are hidden. + +See <<alert-types>> for the types of alerts provided by {kib} and how they express their conditions. + +[float] +[[alerting-concepts-scheduling]] +==== Schedule + +Alert schedules are defined as an interval between subsequent checks, and can range from a few seconds to months. + +[IMPORTANT] +============================================== +The intervals of alert checks in {kib} are approximate, their timing of their execution is affected by factors such as the frequency at which tasks are claimed and the task load on the system. See <<alerting-scale-performance>> for more information. +============================================== + +[float] +[[alerting-concepts-actions]] +==== Actions + +Actions are invocations of {kib} services or integrations with third-party systems, that run as background tasks on the {kib} server when alert conditions are met. + +When defining actions in an alert, you specify +* the *action type*: the type of service or integration to use> +* the connection for that type by referencing a <<alerting-concepts-connectors, connector>>. +* a mapping of alert values to properties exposed for that type of action. + +The result is a template: all the parameters needed to invoke a service are supplied except for specific values that are only known at the time the alert condition is detected. + +In the server monitoring example, the `email` action type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`. + +When the alert detects the condition, it creates an <<alerting-concepts-alert-instances, alert instance>> containing the details of the condition, renders the template with these details such as server name, and executes the action on the {kib} server by invoking the `email` action type. + +image::images/what-is-an-action.svg[Actions are like templates that are rendered when an alert detects a condition] + +See <<action-types>> for details on the types of actions provided by {kib}. + +[float] +[[alerting-concepts-alert-instances]] +=== Alert instances + +When checking for a condition, an alert might identify multiple occurrences of the condition. {kib} tracks each of these *alert instances* separately and takes action per instance. + +Using the server monitoring example, each server with average CPU > 0.9 is tracked as an alert instance. This means a separate email is sent for each server that exceeds the threshold. + +image::images/alert-instances.svg[{kib} tracks each detected condition as an alert instance and takes action on each instance] + +[float] +[[alerting-concepts-suppressing-duplicate-notifications]] +=== Suppressing duplicate notifications + +Since actions are taken per instance, alerts can end up generating a large number of actions. Take the following example where an alert is monitoring three servers every minute for CPU usage > 0.9: + +* Minute 1: server X123 > 0.9. *One email* is sent for server X123. +* Minute 2: X123 and Y456 > 0.9. *Two emails* are sent, on for X123 and one for Y456. +* Minute 3: X123, Y456, Z789 > 0.9. *Three emails* are sent, one for each of X123, Y456, Z789. + +In the above example, three emails are sent for server X123 in the span of 3 minutes for the same condition. Often it's desirable to suppress frequent re-notification. Operations like muting and re-notification throttling can be applied at the instance level. If we set the alert re-notify interval to 5 minutes, we reduce noise by only getting emails for new servers that exceed the threshold: + +* Minute 1: server X123 > 0.9. *One email* is sent for server X123. +* Minute 2: X123 and Y456 > 0.9. *One email* is sent for Y456 +* Minute 3: X123, Y456, Z789 > 0.9. *One email* is sent for Z789. + +[float] +[[alerting-concepts-connectors]] +=== Connectors + +Actions often involve connecting with services inside {kib} or integrations with third-party systems. +Rather than repeatedly entering connection information and credentials for each action, {kib} simplifies action setup using *connectors*. + +*Connectors* provide a central place to store connection information for services and integrations. For example if four alerts send email notifications via the same SMTP service, +they all reference the same SMTP connector. When the SMTP settings change they are updated once in the connector, instead of having to update four alerts. + +image::images/alert-concepts-connectors.svg[Connectors provide a central place to store service connection settings] + +[float] +=== Summary + +An _alert_ consists of conditions, _actions_, and a schedule. When conditions are met, _alert instances_ are created that render _actions_ and invoke them. To make action setup and update easier, actions refer to _connectors_ that centralize the information used to connect with {kib} services and third-party integrations. + +image::images/alert-concepts-summary.svg[Alerts, actions, alert instances and connectors work together to convert detection into action] + +* *Alert*: a specification of the conditions to be detected, the schedule for detection, and the response when detection occurs. +* *Action*: the response to a detected condition defined in the alert. Typically actions specify a service or third party integration along with alert details that will be sent to it. +* *Alert instance*: state tracked by {kib} for every occurrence of a detected condition. Actions as well as controls like muting and re-notification are controlled at the instance level. +* *Connector*: centralized configurations for services and third party integration that are referenced by actions. + +[float] +[[alerting-concepts-differences]] +== Differences from Watcher + +{kib} alerting and <<watcher-ui, {es} alerting>> are both used to detect conditions and can trigger actions in response, but they are completely independent alerting systems. + +This section will clarify some of the important differences in the function and intent of the two systems. + +Functionally, {kib} alerting differs in that: + +* Scheduled checks are run on {kib} instead of {es} +* {kib} <<alerting-concepts-conditions, alerts hide the details of detecting conditions>> through *alert types*, whereas watches provide low-level control over inputs, conditions, and transformations. +* {kib} alerts tracks and persists the state of each detected condition through *alert instances*. This makes it possible to mute and throttle individual instances, and detect changes in state such as resolution. +* Actions are linked to *alert instances* in {kib} alerting. Actions are fired for each occurrence of a detected condition, rather than for the entire alert. + +At a higher level, {kib} alerts allow rich integrations across use cases like <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, <<xpack-siem,*SIEM*>>, and <<xpack-uptime,*Uptime*>>. +Pre-packaged *alert types* simplify setup, hide the details complex domain-specific detections, while providing a consistent interface across {kib}. + +[float] +[[alerting-setup-prerequisites]] +== Setup and prerequisites + +If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-with-security, *security*>>: + +* TLS must be configured for communication <<configuring-tls-kib-es, between {es} and {kib}>>. {kib} alerting uses <<api-keys, API keys>> to secure background alert checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. +* In the kibana.yml configuration file, add the <<alert-action-settings-kb,`xpack.encrypted_saved_objects.encryptionKey` setting>> + +[float] +[[alerting-security]] +== Security + +To access alerting in a space, a user must have access to one of the following features: +* <<xpack-apm,*APM*>> +* <<xpack-infra,*Metrics*>> +* <<xpack-siem,*SIEM*>> +* <<xpack-uptime,*Uptime*>> + +See <<kibana-feature-privileges, feature privileges>> for more information on configuring roles that provide access to these features. + +[float] +[[alerting-spaces]] +=== Space isolation + +Alerts and connectors are isolated to the {kib} space in which they were created. An alert or connector created in one space will not be visible in another. + +[float] +[[alerting-authorization]] +=== Authorization + +Alerts, including all background detection and the actions they generate are authorized using an <<api-keys, API key>> associated with the last user to edit the alert. Upon creating or modifying an alert, an API key is generated for that user, capturing a snapshot of their privileges at that moment in time. The API key is then used to run all background tasks associated with the alert including detection checks and executing actions. + +[IMPORTANT] +============================================== +If an alert requires certain privileges to run such as index privileges, keep in mind that if a user without those privileges updates the alert, the alert will no longer function. +============================================== + +[float] +[[alerting-restricting-actions]] +=== Restricting actions + +For security reasons you may wish to limit the extent to which {kib} can connect to external services. <<action-settings>> allows you to disable certain <<action-types>> and whitelist the hostnames that {kib} can connect with. + +-- + +include::defining-alerts.asciidoc[] +include::action-types.asciidoc[] +include::alert-types.asciidoc[] +include::alerting-scale-performance.asciidoc[] diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc index 5c5f5c2f80bf9..98033c5a87f6f 100644 --- a/docs/user/canvas.asciidoc +++ b/docs/user/canvas.asciidoc @@ -31,14 +31,8 @@ include::{kib-repo-dir}/canvas/canvas-tutorial.asciidoc[] include::{kib-repo-dir}/canvas/canvas-workpad.asciidoc[] -include::{kib-repo-dir}/canvas/canvas-elements.asciidoc[] - -include::{kib-repo-dir}/canvas/canvas-present-workpad.asciidoc[] - -include::{kib-repo-dir}/canvas/canvas-share-workpad.asciidoc[] - include::{kib-repo-dir}/canvas/canvas-expression-lifecycle.asciidoc[] include::{kib-repo-dir}/canvas/canvas-function-reference.asciidoc[] -include::{kib-repo-dir}/canvas/canvas-tinymath-functions.asciidoc[] \ No newline at end of file +include::{kib-repo-dir}/canvas/canvas-tinymath-functions.asciidoc[] diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc index ff100d0763368..0f53497716552 100644 --- a/docs/user/index.asciidoc +++ b/docs/user/index.asciidoc @@ -40,6 +40,8 @@ include::management.asciidoc[] include::reporting/index.asciidoc[] +include::alerting/index.asciidoc[] + include::api.asciidoc[] include::plugins.asciidoc[] diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index 34a3790529ca3..fa34802abe2a9 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -83,6 +83,10 @@ a| <<advanced-options, *Advanced Settings*>> Customize {kib} to suit your needs. Change the format for displaying dates, turn on dark mode, set the timespan for notification messages, and much more. +| <<managing-alerts-and-actions, *Alerts and Actions*>> + +Centrally manage your alerts from across {kib}. Create and manage re-usable connectors for triggering actions. + | <<managing-fields, *Index Patterns*>> Create and manage the index patterns that help you retrieve your data from {es}. @@ -111,6 +115,14 @@ so you can tailor it to your needs without impacting others. include::{kib-repo-dir}/management/advanced-options.asciidoc[] +include::{kib-repo-dir}/management/alerting/alerts-and-actions-intro.asciidoc[] + +include::{kib-repo-dir}/management/alerting/alert-management.asciidoc[] + +include::{kib-repo-dir}/management/alerting/alert-details.asciidoc[] + +include::{kib-repo-dir}/management/alerting/connector-management.asciidoc[] + include::{kib-repo-dir}/management/managing-beats.asciidoc[] include::{kib-repo-dir}/management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[] diff --git a/examples/alerting_example/public/application.tsx b/examples/alerting_example/public/application.tsx index d71db92d3d421..6ff5a7d0880b8 100644 --- a/examples/alerting_example/public/application.tsx +++ b/examples/alerting_example/public/application.tsx @@ -25,6 +25,7 @@ import { AppMountParameters, CoreStart, IUiSettingsClient, + DocLinksStart, ToastsSetup, } from '../../../src/core/public'; import { DataPublicPluginStart } from '../../../src/plugins/data/public'; @@ -45,6 +46,7 @@ export interface AlertingExampleComponentParams { data: DataPublicPluginStart; charts: ChartsPluginStart; uiSettings: IUiSettingsClient; + docLinks: DocLinksStart; toastNotifications: ToastsSetup; } @@ -88,7 +90,7 @@ const AlertingExampleApp = (deps: AlertingExampleComponentParams) => { }; export const renderApp = ( - { application, notifications, http, uiSettings }: CoreStart, + { application, notifications, http, uiSettings, docLinks }: CoreStart, deps: AlertingExamplePublicStartDeps, { appBasePath, element }: AppMountParameters ) => { @@ -99,6 +101,7 @@ export const renderApp = ( toastNotifications={notifications.toasts} http={http} uiSettings={uiSettings} + docLinks={docLinks} {...deps} />, element diff --git a/examples/alerting_example/public/components/create_alert.tsx b/examples/alerting_example/public/components/create_alert.tsx index 65b8a9412dcda..0541e0b18a2e1 100644 --- a/examples/alerting_example/public/components/create_alert.tsx +++ b/examples/alerting_example/public/components/create_alert.tsx @@ -33,6 +33,7 @@ export const CreateAlert = ({ triggers_actions_ui, charts, uiSettings, + docLinks, data, toastNotifications, }: AlertingExampleComponentParams) => { @@ -56,6 +57,7 @@ export const CreateAlert = ({ alertTypeRegistry: triggers_actions_ui.alertTypeRegistry, toastNotifications, uiSettings, + docLinks, charts, dataFieldsFormats: data.fieldFormats, }} diff --git a/examples/alerting_example/public/plugin.tsx b/examples/alerting_example/public/plugin.tsx index 299806d393446..e3748e3235f47 100644 --- a/examples/alerting_example/public/plugin.tsx +++ b/examples/alerting_example/public/plugin.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'kibana/public'; +import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerting/public'; import { ChartsPluginStart } from '../../../src/plugins/charts/public'; import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public'; @@ -43,17 +43,14 @@ export interface AlertingExamplePublicStartDeps { export class AlertingExamplePlugin implements Plugin<Setup, Start, AlertingExamplePublicSetupDeps> { public setup( - core: CoreSetup<AlertingExamplePublicStartDeps>, + core: CoreSetup<AlertingExamplePublicStartDeps, Start>, { alerting, triggers_actions_ui }: AlertingExamplePublicSetupDeps ) { core.application.register({ id: 'AlertingExample', title: 'Alerting Example', async mount(params: AppMountParameters) { - const [coreStart, depsStart]: [ - CoreStart, - AlertingExamplePublicStartDeps - ] = await core.getStartServices(); + const [coreStart, depsStart] = await core.getStartServices(); const { renderApp } = await import('./application'); return renderApp(coreStart, depsStart, params); }, diff --git a/examples/bfetch_explorer/public/plugin.tsx b/examples/bfetch_explorer/public/plugin.tsx index 3155354c91fd4..fc3202f08bf70 100644 --- a/examples/bfetch_explorer/public/plugin.tsx +++ b/examples/bfetch_explorer/public/plugin.tsx @@ -34,7 +34,10 @@ export interface BfetchExplorerStartPlugins { } export class BfetchExplorerPlugin implements Plugin { - public setup(core: CoreSetup<BfetchExplorerStartPlugins>, plugins: BfetchExplorerSetupPlugins) { + public setup( + core: CoreSetup<BfetchExplorerStartPlugins, void>, + plugins: BfetchExplorerSetupPlugins + ) { const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ url: '/bfetch_explorer/double', }); diff --git a/examples/embeddable_examples/public/index.ts b/examples/embeddable_examples/public/index.ts index 1c2c3911d1006..5fcd454b17a5c 100644 --- a/examples/embeddable_examples/public/index.ts +++ b/examples/embeddable_examples/public/index.ts @@ -26,9 +26,18 @@ export { export { ListContainer, LIST_CONTAINER } from './list_container'; export { TODO_EMBEDDABLE } from './todo'; -import { EmbeddableExamplesPlugin } from './plugin'; +import { + EmbeddableExamplesPlugin, + EmbeddableExamplesSetupDependencies, + EmbeddableExamplesStartDependencies, +} from './plugin'; export { SearchableListContainer, SEARCHABLE_LIST_CONTAINER } from './searchable_list_container'; export { MULTI_TASK_TODO_EMBEDDABLE } from './multi_task_todo'; -export const plugin: PluginInitializer<void, void> = () => new EmbeddableExamplesPlugin(); +export const plugin: PluginInitializer< + void, + void, + EmbeddableExamplesSetupDependencies, + EmbeddableExamplesStartDependencies +> = () => new EmbeddableExamplesPlugin(); diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 3663af68ae2c7..5c202d96ceb1a 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -28,11 +28,11 @@ import { } from './searchable_list_container'; import { LIST_CONTAINER, ListContainerFactory } from './list_container'; -interface EmbeddableExamplesSetupDependencies { +export interface EmbeddableExamplesSetupDependencies { embeddable: EmbeddableSetup; } -interface EmbeddableExamplesStartDependencies { +export interface EmbeddableExamplesStartDependencies { embeddable: EmbeddableStart; } diff --git a/examples/search_explorer/public/plugin.tsx b/examples/search_explorer/public/plugin.tsx index 29b236e82bf46..70b37aa9e626c 100644 --- a/examples/search_explorer/public/plugin.tsx +++ b/examples/search_explorer/public/plugin.tsx @@ -21,7 +21,7 @@ import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; import { AppPluginStartDependencies } from './types'; export class SearchExplorerPlugin implements Plugin { - public setup(core: CoreSetup<AppPluginStartDependencies>) { + public setup(core: CoreSetup<AppPluginStartDependencies, void>) { core.application.register({ id: 'searchExplorer', title: 'Search Explorer', diff --git a/examples/ui_action_examples/public/plugin.ts b/examples/ui_action_examples/public/plugin.ts index d053f7e82862c..c47746d4b3fd6 100644 --- a/examples/ui_action_examples/public/plugin.ts +++ b/examples/ui_action_examples/public/plugin.ts @@ -46,7 +46,7 @@ export class UiActionExamplesPlugin })); uiActions.registerAction(helloWorldAction); - uiActions.addTriggerAction(helloWorldTrigger.id, helloWorldAction); + uiActions.attachAction(helloWorldTrigger.id, helloWorldAction); } public start() {} diff --git a/examples/ui_actions_explorer/public/app.tsx b/examples/ui_actions_explorer/public/app.tsx index f08b8bb29bdd3..462f5c3bf88ba 100644 --- a/examples/ui_actions_explorer/public/app.tsx +++ b/examples/ui_actions_explorer/public/app.tsx @@ -95,7 +95,8 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => { ); }, }); - uiActionsApi.addTriggerAction(HELLO_WORLD_TRIGGER_ID, dynamicAction); + uiActionsApi.registerAction(dynamicAction); + uiActionsApi.attachAction(HELLO_WORLD_TRIGGER_ID, dynamicAction); setConfirmationText( `You've successfully added a new action: ${dynamicAction.getDisplayName( {} diff --git a/examples/ui_actions_explorer/public/plugin.tsx b/examples/ui_actions_explorer/public/plugin.tsx index de86b51aee3a8..f1895905a45e1 100644 --- a/examples/ui_actions_explorer/public/plugin.tsx +++ b/examples/ui_actions_explorer/public/plugin.tsx @@ -79,21 +79,21 @@ export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps const startServices = core.getStartServices(); - deps.uiActions.addTriggerAction( + deps.uiActions.attachAction( USER_TRIGGER, createPhoneUserAction(async () => (await startServices)[1].uiActions) ); - deps.uiActions.addTriggerAction( + deps.uiActions.attachAction( USER_TRIGGER, createEditUserAction(async () => (await startServices)[0].overlays.openModal) ); - deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, viewInMapsAction); - deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, lookUpWeatherAction); - deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, showcasePluggability); - deps.uiActions.addTriggerAction(PHONE_TRIGGER, makePhoneCallAction); - deps.uiActions.addTriggerAction(PHONE_TRIGGER, showcasePluggability); - deps.uiActions.addTriggerAction(USER_TRIGGER, showcasePluggability); + deps.uiActions.attachAction(COUNTRY_TRIGGER, viewInMapsAction); + deps.uiActions.attachAction(COUNTRY_TRIGGER, lookUpWeatherAction); + deps.uiActions.attachAction(COUNTRY_TRIGGER, showcasePluggability); + deps.uiActions.attachAction(PHONE_TRIGGER, makePhoneCallAction); + deps.uiActions.attachAction(PHONE_TRIGGER, showcasePluggability); + deps.uiActions.attachAction(USER_TRIGGER, showcasePluggability); core.application.register({ id: 'uiActionsExplorer', diff --git a/package.json b/package.json index 9bb9b505f54a2..c2763f098b984 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "uiFramework:documentComponent": "cd packages/kbn-ui-framework && yarn documentComponent", "kbn:watch": "node scripts/kibana --dev --logging.json=false", "build:types": "tsc --p tsconfig.types.json", - "docs:acceptApiChanges": "node scripts/check_published_api_changes.js --accept", + "docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept", "kbn:bootstrap": "yarn build:types && node scripts/register_git_hook", "spec_to_console": "node scripts/spec_to_console", "backport-skip-ci": "backport --prDescription \"[skip-ci]\"", @@ -115,12 +115,12 @@ ] }, "dependencies": { - "@babel/core": "^7.5.5", - "@babel/register": "^7.7.0", + "@babel/core": "^7.9.0", + "@babel/register": "^7.9.0", "@elastic/apm-rum": "^4.6.0", - "@elastic/charts": "^18.1.0", + "@elastic/charts": "^18.1.1", "@elastic/datemath": "5.0.2", - "@elastic/ems-client": "7.7.0", + "@elastic/ems-client": "7.7.1", "@elastic/eui": "21.0.1", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", @@ -162,7 +162,7 @@ "color": "1.0.3", "commander": "3.0.2", "compare-versions": "3.5.1", - "core-js": "^3.2.1", + "core-js": "^3.6.4", "css-loader": "^3.4.2", "d3": "3.5.17", "d3-cloud": "1.2.5", @@ -170,8 +170,8 @@ "deepmerge": "^4.2.2", "del": "^5.1.0", "elastic-apm-node": "^3.2.0", - "elasticsearch": "^16.5.0", - "elasticsearch-browser": "^16.5.0", + "elasticsearch": "^16.7.0", + "elasticsearch-browser": "^16.7.0", "execa": "^4.0.0", "expiry-js": "0.1.7", "fast-deep-equal": "^3.1.1", @@ -180,7 +180,7 @@ "fp-ts": "^2.3.1", "getos": "^3.1.0", "glob": "^7.1.2", - "glob-all": "^3.1.0", + "glob-all": "^3.2.1", "globby": "^8.0.1", "h2o2": "^8.1.2", "handlebars": "4.5.3", @@ -284,13 +284,13 @@ "yauzl": "2.10.0" }, "devDependencies": { - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", + "@babel/parser": "^7.9.3", + "@babel/types": "^7.9.0", "@elastic/elasticsearch": "^7.4.0", "@elastic/eslint-config-kibana": "0.15.0", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", - "@elastic/makelogs": "^5.0.0", + "@elastic/makelogs": "^5.0.1", "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", "@kbn/eslint-import-resolver-kibana": "2.0.0", @@ -330,11 +330,13 @@ "@types/glob": "^7.1.1", "@types/globby": "^8.0.0", "@types/graphql": "^0.13.2", + "@types/h2o2": "^8.1.1", "@types/hapi": "^17.0.18", "@types/hapi-auth-cookie": "^9.1.0", "@types/has-ansi": "^3.0.0", "@types/history": "^4.7.3", "@types/hoek": "^4.1.3", + "@types/inert": "^5.1.2", "@types/jest": "24.0.19", "@types/joi": "^13.4.2", "@types/jquery": "^3.3.31", @@ -443,7 +445,7 @@ "jest": "^24.9.0", "jest-cli": "^24.9.0", "jest-raw-loader": "^1.0.1", - "jimp": "0.8.4", + "jimp": "^0.9.6", "json5": "^1.0.1", "karma": "3.1.4", "karma-chrome-launcher": "2.2.0", diff --git a/packages/elastic-datemath/package.json b/packages/elastic-datemath/package.json index 57873d28d372d..8c7c93834adc6 100644 --- a/packages/elastic-datemath/package.json +++ b/packages/elastic-datemath/package.json @@ -11,8 +11,8 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "^7.5.5", - "@babel/preset-env": "^7.5.5", + "@babel/cli": "^7.8.4", + "@babel/preset-env": "^7.9.0", "babel-plugin-add-module-exports": "^1.0.2", "moment": "^2.24.0" }, diff --git a/packages/kbn-analytics/package.json b/packages/kbn-analytics/package.json index 9eefa16aaca01..b7a719e5595e6 100644 --- a/packages/kbn-analytics/package.json +++ b/packages/kbn-analytics/package.json @@ -14,7 +14,7 @@ "kbn:watch": "node scripts/build --source-maps --watch" }, "devDependencies": { - "@babel/cli": "^7.5.5", + "@babel/cli": "^7.8.4", "@kbn/dev-utils": "1.0.0", "@kbn/babel-preset": "1.0.0", "typescript": "3.7.2" diff --git a/packages/kbn-babel-code-parser/package.json b/packages/kbn-babel-code-parser/package.json index a9d373d33ab38..4321cd6ee762c 100755 --- a/packages/kbn-babel-code-parser/package.json +++ b/packages/kbn-babel-code-parser/package.json @@ -15,12 +15,12 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "^7.5.5" + "@babel/cli": "^7.8.4" }, "dependencies": { "@kbn/babel-preset": "1.0.0", - "@babel/parser": "^7.5.5", - "@babel/traverse": "^7.5.5", + "@babel/parser": "^7.9.3", + "@babel/traverse": "^7.9.0", "lodash": "^4.17.15" } } diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 0acafbae59afd..b82c8d0fac897 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -4,14 +4,14 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@babel/plugin-proposal-class-properties": "^7.5.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4", - "@babel/plugin-proposal-optional-chaining": "^7.6.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", - "@babel/preset-env": "^7.5.5", - "@babel/preset-react": "^7.7.4", - "@babel/preset-typescript": "^7.7.4", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@babel/preset-react": "^7.9.1", + "@babel/preset-typescript": "^7.9.0", "babel-plugin-add-module-exports": "^1.0.2", "babel-plugin-filter-imports": "^3.0.0", "babel-plugin-styled-components": "^1.10.6", diff --git a/packages/kbn-es/src/artifact.js b/packages/kbn-es/src/artifact.js index 9ea78386269d9..83dcd1cf36d2e 100644 --- a/packages/kbn-es/src/artifact.js +++ b/packages/kbn-es/src/artifact.js @@ -117,11 +117,14 @@ async function getArtifactSpecForSnapshot(urlVersion, license, log) { const manifest = JSON.parse(json); const platform = process.platform === 'win32' ? 'windows' : process.platform; + const arch = process.arch === 'arm64' ? 'aarch64' : 'x86_64'; + const archive = manifest.archives.find( archive => archive.version === desiredVersion && archive.platform === platform && - archive.license === desiredLicense + archive.license === desiredLicense && + archive.architecture === arch ); if (!archive) { diff --git a/packages/kbn-es/src/artifact.test.js b/packages/kbn-es/src/artifact.test.js index 453eb1a9a7689..02e4d5318f63f 100644 --- a/packages/kbn-es/src/artifact.test.js +++ b/packages/kbn-es/src/artifact.test.js @@ -28,6 +28,7 @@ const log = new ToolingLog(); let MOCKS; const PLATFORM = process.platform === 'win32' ? 'windows' : process.platform; +const ARCHITECTURE = process.arch === 'arm64' ? 'aarch64' : 'x86_64'; const MOCK_VERSION = 'test-version'; const MOCK_URL = 'http://127.0.0.1:12345'; const MOCK_FILENAME = 'test-filename'; @@ -38,13 +39,15 @@ const PERMANENT_SNAPSHOT_BASE_URL = const createArchive = (params = {}) => { const license = params.license || 'default'; + const architecture = params.architecture || ARCHITECTURE; return { license: 'default', + architecture, version: MOCK_VERSION, url: MOCK_URL + `/${license}`, platform: PLATFORM, - filename: MOCK_FILENAME + `.${license}`, + filename: MOCK_FILENAME + `-${architecture}.${license}`, ...params, }; }; @@ -77,6 +80,12 @@ beforeEach(() => { valid: { archives: [createArchive({ license: 'oss' }), createArchive({ license: 'default' })], }, + multipleArch: { + archives: [ + createArchive({ architecture: 'fake_arch', license: 'oss' }), + createArchive({ architecture: ARCHITECTURE, license: 'oss' }), + ], + }, }; }); @@ -95,7 +104,7 @@ const artifactTest = (requestedLicense, expectedLicense, fetchTimesCalled = 1) = expect(artifact.getUrl()).toEqual(MOCK_URL + `/${expectedLicense}`); expect(artifact.getChecksumUrl()).toEqual(MOCK_URL + `/${expectedLicense}.sha512`); expect(artifact.getChecksumType()).toEqual('sha512'); - expect(artifact.getFilename()).toEqual(MOCK_FILENAME + `.${expectedLicense}`); + expect(artifact.getFilename()).toEqual(MOCK_FILENAME + `-${ARCHITECTURE}.${expectedLicense}`); }; }; @@ -153,6 +162,17 @@ describe('Artifact', () => { }); }); + describe('with snapshots for multiple architectures', () => { + beforeEach(() => { + mockFetch(MOCKS.multipleArch); + }); + + it('should return artifact metadata for the correct architecture', async () => { + const artifact = await Artifact.getSnapshot('oss', MOCK_VERSION, log); + expect(artifact.getFilename()).toEqual(MOCK_FILENAME + `-${ARCHITECTURE}.oss`); + }); + }); + describe('with custom snapshot manifest URL', () => { const CUSTOM_URL = 'http://www.creedthoughts.gov.www/creedthoughts'; diff --git a/packages/kbn-i18n/package.json b/packages/kbn-i18n/package.json index bbc5126da1dce..a2b5a2c692645 100644 --- a/packages/kbn-i18n/package.json +++ b/packages/kbn-i18n/package.json @@ -12,8 +12,8 @@ "kbn:watch": "node scripts/build --watch --source-maps" }, "devDependencies": { - "@babel/cli": "^7.5.5", - "@babel/core": "^7.5.5", + "@babel/cli": "^7.8.4", + "@babel/core": "^7.9.0", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/intl-relativeformat": "^2.1.0", diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index 5dede7fbf1aaa..dee35043211f7 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -9,16 +9,16 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { - "@babel/runtime": "^7.5.5", + "@babel/runtime": "^7.9.2", "@kbn/i18n": "1.0.0", "lodash": "npm:@elastic/lodash@3.10.1-kibana4", "lodash.clone": "^4.5.0", "uuid": "3.3.2" }, "devDependencies": { - "@babel/cli": "^7.5.5", - "@babel/core": "^7.5.5", - "@babel/plugin-transform-runtime": "^7.5.5", + "@babel/cli": "^7.8.4", + "@babel/core": "^7.9.0", + "@babel/plugin-transform-runtime": "^7.9.0", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "babel-loader": "^8.0.6", diff --git a/packages/kbn-optimizer/package.json b/packages/kbn-optimizer/package.json index 219b9aaa7f8f2..d32c7489641a0 100644 --- a/packages/kbn-optimizer/package.json +++ b/packages/kbn-optimizer/package.json @@ -10,7 +10,7 @@ "kbn:watch": "yarn build --watch" }, "dependencies": { - "@babel/cli": "^7.5.5", + "@babel/cli": "^7.8.4", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/ui-shared-deps": "1.0.0", diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 5d8ef7626f630..dabfed7f9725c 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -131,12 +131,21 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) { loader: 'resolve-url-loader', options: { join: (_: string, __: any) => (uri: string, base?: string) => { - if (!base) { + // apply only to legacy platform styles + if (!base || !parseDirPath(base).dirs.includes('legacy')) { return null; } + if (uri.startsWith('ui/assets')) { + return Path.resolve( + worker.repoRoot, + 'src/core/server/core_app/', + uri.replace('ui/', '') + ); + } + // manually force ui/* urls in legacy styles to resolve to ui/legacy/public - if (uri.startsWith('ui/') && parseDirPath(base).dirs.includes('legacy')) { + if (uri.startsWith('ui/')) { return Path.resolve( worker.repoRoot, 'src/legacy/ui/public', diff --git a/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js index d7d4dc14519c3..f434d09c6bf81 100644 --- a/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js +++ b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js @@ -17,163 +17,46 @@ * under the License. */ -/* eslint-disable no-restricted-syntax */ import { spawn } from 'child_process'; +import Fs from 'fs'; import { resolve } from 'path'; -import util from 'util'; -import { stat, readFileSync } from 'fs'; -import { snakeCase } from 'lodash'; +import { promisify } from 'util'; + import del from 'del'; -import { ProcRunner, ToolingLog } from '@kbn/dev-utils'; -import { createLegacyEsTestCluster } from '@kbn/test'; -import execa from 'execa'; +import { snakeCase } from 'lodash'; -const statP = util.promisify(stat); +const statAsync = promisify(Fs.stat); const ROOT_DIR = resolve(__dirname, '../../../'); -const oneMinute = 60000; - -describe(`running the plugin-generator via 'node scripts/generate_plugin.js plugin-name' with default config`, () => { - const pluginName = 'ispec-plugin'; - const snakeCased = snakeCase(pluginName); - const generatedPath = resolve(ROOT_DIR, `plugins/${snakeCased}`); - const collect = xs => data => xs.push(data + ''); // Coerce from Buffer to String - - beforeAll(() => { - jest.setTimeout(oneMinute * 10); - }); - - beforeAll(done => { - const create = spawn(process.execPath, ['scripts/generate_plugin.js', pluginName], { - cwd: ROOT_DIR, - }); - create.stdout.on('data', function selectDefaults() { - create.stdin.write('\n'); // Generate a plugin with default options. - }); - create.on('close', done); - }); - - afterAll(() => { - del.sync(generatedPath, { force: true }); - }); - - it(`should succeed on creating a plugin in a directory named 'plugins/${snakeCased}`, async () => { - const stats = await statP(generatedPath); - expect(stats.isDirectory()).toBe(true); - }); - // skipped until internationalization is re-introduced - it.skip(`should create an internationalization config file with a blank line appended to satisfy the parser`, async () => { - // Link to the error that happens when the blank line is not there: - // https://github.com/elastic/kibana/pull/45044#issuecomment-530092627 - const intlFile = `${generatedPath}/.i18nrc.json`; - expect(readFileSync(intlFile, 'utf8').endsWith('\n\n')).toBe(true); - }); - - describe(`then running`, () => { - it(`'yarn test:karma' should exit 0`, async () => { - await execa('yarn', ['test:karma'], { - cwd: generatedPath, - env: { - DISABLE_JUNIT_REPORTER: '1', - }, - }); - }); - - it.skip(`'yarn build' should exit 0`, async () => { - await execa('yarn', ['build'], { cwd: generatedPath }); - }); +const pluginName = 'ispec-plugin'; +const snakeCased = snakeCase(pluginName); +const generatedPath = resolve(ROOT_DIR, `plugins/${snakeCased}`); - describe('with es instance', () => { - const log = new ToolingLog({ - level: 'verbose', - writeTo: process.stdout, - }); - const pr = new ProcRunner(log); - - const es = createLegacyEsTestCluster({ license: 'basic', log }); - beforeAll(es.start); - afterAll(es.stop); - afterAll(() => pr.teardown()); +beforeAll(async () => { + await del(generatedPath, { force: true }); +}); - it(`'yarn start' should result in the spec plugin being initialized on kibana's stdout`, async () => { - await pr.run('kibana', { - cmd: 'yarn', - args: [ - 'start', - '--optimize.enabled=false', - '--logging.json=false', - '--logging.verbose=true', - '--migrations.skip=true', - ], - cwd: generatedPath, - wait: new RegExp('\\[ispecPlugin\\]\\[plugins\\] Setting up plugin'), - }); - await pr.stop('kibana'); - }); - }); +afterAll(async () => { + await del(generatedPath, { force: true }); +}); - it(`'yarn preinstall' should exit 0`, async () => { - await execa('yarn', ['preinstall'], { cwd: generatedPath }); +it('generates a plugin', async () => { + await new Promise((resolve, reject) => { + const proc = spawn(process.execPath, ['scripts/generate_plugin.js', pluginName], { + cwd: ROOT_DIR, + stdio: 'pipe', }); - it.skip(`'yarn lint' should exit 0`, async () => { - await execa('yarn', ['lint'], { cwd: generatedPath }); + proc.stdout.on('data', function selectDefaults() { + proc.stdin.write('\n'); // Generate a plugin with default options. }); - it(`'yarn kbn --help' should print out the kbn help msg`, done => { - const helpMsg = ` -usage: kbn <command> [<args>] - -By default commands are run for Kibana itself, all packages in the 'packages/' -folder and for all plugins in './plugins' and '../kibana-extra'. - -Available commands: - - bootstrap - Install dependencies and crosslink projects - clean - Remove the node_modules and target directories from all projects. - run - Run script defined in package.json in each package that contains that script. - watch - Runs \`kbn:watch\` script for every project. - -Global options: - - -e, --exclude Exclude specified project. Can be specified multiple times to exclude multiple projects, e.g. '-e kibana -e @kbn/pm'. - -i, --include Include only specified projects. If left unspecified, it defaults to including all projects. - --oss Do not include the x-pack when running command. - --skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command. -`; - const outData = []; - const kbnHelp = spawn('yarn', ['kbn', '--help'], { cwd: generatedPath }); - kbnHelp.stdout.on('data', collect(outData)); - kbnHelp.on('close', () => { - expect(outData.join('\n')).toContain(helpMsg); - done(); - }); - }); - - it(`'yarn es --help' should print out the es help msg`, done => { - const helpMsg = ` -usage: es <command> [<args>] - -Assists with running Elasticsearch for Kibana development - -Available commands: - - snapshot - Downloads and run from a nightly snapshot - source - Build and run from source - archive - Install and run from an Elasticsearch tar - build_snapshots - Build and collect ES snapshots - -Global options: - - --help -`; - const outData = []; - const kbnHelp = spawn('yarn', ['es', '--help'], { cwd: generatedPath }); - kbnHelp.stdout.on('data', collect(outData)); - kbnHelp.on('close', () => { - expect(outData.join('\n')).toContain(helpMsg); - done(); - }); - }); + proc.on('close', resolve); + proc.on('error', reject); }); + + const stats = await statAsync(generatedPath); + if (!stats.isDirectory()) { + throw new Error(`Expected [${generatedPath}] to be a directory`); + } }); diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index c348aa43789d1..53c998ddfaac2 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -13,7 +13,7 @@ "@kbn/babel-preset": "1.0.0" }, "dependencies": { - "@babel/core": "^7.5.5", + "@babel/core": "^7.9.0", "argv-split": "^2.0.1", "commander": "^3.0.0", "del": "^5.1.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 62b12e8e38c87..f7aee155c9b1d 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,21 +94,21 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(704); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(703); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return _utils_projects__WEBPACK_IMPORTED_MODULE_2__["getProjects"]; }); -/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(577); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(576); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(577); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(688); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(687); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2506,9 +2506,9 @@ module.exports = require("path"); __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(685); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(686); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(584); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(684); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(685); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2549,10 +2549,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(500); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(584); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(498); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(499); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(583); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4013,6 +4013,7 @@ function mkdirP (p, opts, f, made) { } switch (er.code) { case 'ENOENT': + if (path.dirname(p) === p) return cb(er); mkdirP(path.dirname(p), opts, function (er, made) { if (er) cb(er, made); else mkdirP(p, opts, cb, made); @@ -4493,7 +4494,7 @@ exports.ProcRunner = proc_runner_1.ProcRunner; tslib_1.__exportStar(__webpack_require__(414), exports); var serializers_1 = __webpack_require__(419); exports.createAbsolutePathSerializer = serializers_1.createAbsolutePathSerializer; -var certs_1 = __webpack_require__(444); +var certs_1 = __webpack_require__(443); exports.CA_CERT_PATH = certs_1.CA_CERT_PATH; exports.ES_KEY_PATH = certs_1.ES_KEY_PATH; exports.ES_CERT_PATH = certs_1.ES_CERT_PATH; @@ -4505,7 +4506,7 @@ exports.KBN_KEY_PATH = certs_1.KBN_KEY_PATH; exports.KBN_CERT_PATH = certs_1.KBN_CERT_PATH; exports.KBN_P12_PATH = certs_1.KBN_P12_PATH; exports.KBN_P12_PASSWORD = certs_1.KBN_P12_PASSWORD; -var run_1 = __webpack_require__(445); +var run_1 = __webpack_require__(444); exports.run = run_1.run; exports.createFailError = run_1.createFailError; exports.createFlagError = run_1.createFlagError; @@ -4513,9 +4514,9 @@ exports.combineErrors = run_1.combineErrors; exports.isFailError = run_1.isFailError; var repo_root_1 = __webpack_require__(421); exports.REPO_ROOT = repo_root_1.REPO_ROOT; -var kbn_client_1 = __webpack_require__(450); +var kbn_client_1 = __webpack_require__(449); exports.KbnClient = kbn_client_1.KbnClient; -tslib_1.__exportStar(__webpack_require__(492), exports); +tslib_1.__exportStar(__webpack_require__(491), exports); /***/ }), @@ -38173,17 +38174,11 @@ Object.defineProperty(exports, "__esModule", { exports.codeFrameColumns = codeFrameColumns; exports.default = _default; -function _highlight() { - const data = _interopRequireWildcard(__webpack_require__(434)); +var _highlight = _interopRequireWildcard(__webpack_require__(434)); - _highlight = function () { - return data; - }; +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } - return data; -} - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } let deprecationWarningShown = false; @@ -38202,7 +38197,7 @@ function getMarkerLines(loc, source, opts) { column: 0, line: -1 }, loc.start); - const endLoc = Object.assign({}, startLoc, loc.end); + const endLoc = Object.assign({}, startLoc, {}, loc.end); const { linesAbove = 2, linesBelow = 3 @@ -38261,8 +38256,8 @@ function getMarkerLines(loc, source, opts) { } function codeFrameColumns(rawLines, loc, opts = {}) { - const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight().shouldHighlight)(opts); - const chalk = (0, _highlight().getChalk)(opts); + const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts); + const chalk = (0, _highlight.getChalk)(opts); const defs = getDefs(chalk); const maybeHighlight = (chalkFn, string) => { @@ -38277,7 +38272,7 @@ function codeFrameColumns(rawLines, loc, opts = {}) { } = getMarkerLines(loc, lines, opts); const hasColumns = loc.start && typeof loc.start.column === "number"; const numberMaxWidth = String(end).length; - const highlightedLines = highlighted ? (0, _highlight().default)(rawLines, opts) : rawLines; + const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines; let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { const number = start + 1 + index; const paddedNumber = ` ${number}`.slice(-numberMaxWidth); @@ -38353,39 +38348,17 @@ exports.shouldHighlight = shouldHighlight; exports.getChalk = getChalk; exports.default = highlight; -function _jsTokens() { - const data = _interopRequireWildcard(__webpack_require__(435)); +var _jsTokens = _interopRequireWildcard(__webpack_require__(435)); - _jsTokens = function () { - return data; - }; - - return data; -} +var _helperValidatorIdentifier = __webpack_require__(436); -function _esutils() { - const data = _interopRequireDefault(__webpack_require__(436)); - - _esutils = function () { - return data; - }; - - return data; -} - -function _chalk() { - const data = _interopRequireDefault(__webpack_require__(440)); - - _chalk = function () { - return data; - }; - - return data; -} +var _chalk = _interopRequireDefault(__webpack_require__(439)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function getDefs(chalk) { return { @@ -38407,10 +38380,10 @@ const BRACKET = /^[()[\]{}]$/; function getTokenType(match) { const [offset, text] = match.slice(-2); - const token = (0, _jsTokens().matchToToken)(match); + const token = (0, _jsTokens.matchToToken)(match); if (token.type === "name") { - if (_esutils().default.keyword.isReservedWordES6(token.value)) { + if ((0, _helperValidatorIdentifier.isKeyword)(token.value) || (0, _helperValidatorIdentifier.isReservedWord)(token.value)) { return "keyword"; } @@ -38435,7 +38408,7 @@ function getTokenType(match) { } function highlightTokens(defs, text) { - return text.replace(_jsTokens().default, function (...args) { + return text.replace(_jsTokens.default, function (...args) { const type = getTokenType(args); const colorize = defs[type]; @@ -38448,14 +38421,14 @@ function highlightTokens(defs, text) { } function shouldHighlight(options) { - return _chalk().default.supportsColor || options.forceColor; + return _chalk.default.supportsColor || options.forceColor; } function getChalk(options) { - let chalk = _chalk().default; + let chalk = _chalk.default; if (options.forceColor) { - chalk = new (_chalk().default.constructor)({ + chalk = new _chalk.default.constructor({ enabled: true, level: 1 }); @@ -38507,514 +38480,203 @@ exports.matchToToken = function(match) { /* 436 */ /***/ (function(module, exports, __webpack_require__) { -/* - Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ +"use strict"; -(function () { - 'use strict'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "isIdentifierName", { + enumerable: true, + get: function () { + return _identifier.isIdentifierName; + } +}); +Object.defineProperty(exports, "isIdentifierChar", { + enumerable: true, + get: function () { + return _identifier.isIdentifierChar; + } +}); +Object.defineProperty(exports, "isIdentifierStart", { + enumerable: true, + get: function () { + return _identifier.isIdentifierStart; + } +}); +Object.defineProperty(exports, "isReservedWord", { + enumerable: true, + get: function () { + return _keyword.isReservedWord; + } +}); +Object.defineProperty(exports, "isStrictBindOnlyReservedWord", { + enumerable: true, + get: function () { + return _keyword.isStrictBindOnlyReservedWord; + } +}); +Object.defineProperty(exports, "isStrictBindReservedWord", { + enumerable: true, + get: function () { + return _keyword.isStrictBindReservedWord; + } +}); +Object.defineProperty(exports, "isStrictReservedWord", { + enumerable: true, + get: function () { + return _keyword.isStrictReservedWord; + } +}); +Object.defineProperty(exports, "isKeyword", { + enumerable: true, + get: function () { + return _keyword.isKeyword; + } +}); - exports.ast = __webpack_require__(437); - exports.code = __webpack_require__(438); - exports.keyword = __webpack_require__(439); -}()); -/* vim: set sw=4 ts=4 et tw=80 : */ +var _identifier = __webpack_require__(437); +var _keyword = __webpack_require__(438); /***/ }), /* 437 */ -/***/ (function(module, exports) { - -/* - Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -(function () { - 'use strict'; - - function isExpression(node) { - if (node == null) { return false; } - switch (node.type) { - case 'ArrayExpression': - case 'AssignmentExpression': - case 'BinaryExpression': - case 'CallExpression': - case 'ConditionalExpression': - case 'FunctionExpression': - case 'Identifier': - case 'Literal': - case 'LogicalExpression': - case 'MemberExpression': - case 'NewExpression': - case 'ObjectExpression': - case 'SequenceExpression': - case 'ThisExpression': - case 'UnaryExpression': - case 'UpdateExpression': - return true; - } - return false; - } - - function isIterationStatement(node) { - if (node == null) { return false; } - switch (node.type) { - case 'DoWhileStatement': - case 'ForInStatement': - case 'ForStatement': - case 'WhileStatement': - return true; - } - return false; - } - - function isStatement(node) { - if (node == null) { return false; } - switch (node.type) { - case 'BlockStatement': - case 'BreakStatement': - case 'ContinueStatement': - case 'DebuggerStatement': - case 'DoWhileStatement': - case 'EmptyStatement': - case 'ExpressionStatement': - case 'ForInStatement': - case 'ForStatement': - case 'IfStatement': - case 'LabeledStatement': - case 'ReturnStatement': - case 'SwitchStatement': - case 'ThrowStatement': - case 'TryStatement': - case 'VariableDeclaration': - case 'WhileStatement': - case 'WithStatement': - return true; - } - return false; - } - - function isSourceElement(node) { - return isStatement(node) || node != null && node.type === 'FunctionDeclaration'; - } - - function trailingStatement(node) { - switch (node.type) { - case 'IfStatement': - if (node.alternate != null) { - return node.alternate; - } - return node.consequent; - - case 'LabeledStatement': - case 'ForStatement': - case 'ForInStatement': - case 'WhileStatement': - case 'WithStatement': - return node.body; - } - return null; - } - - function isProblematicIfStatement(node) { - var current; - - if (node.type !== 'IfStatement') { - return false; - } - if (node.alternate == null) { - return false; - } - current = node.consequent; - do { - if (current.type === 'IfStatement') { - if (current.alternate == null) { - return true; - } - } - current = trailingStatement(current); - } while (current); - - return false; - } - - module.exports = { - isExpression: isExpression, - isStatement: isStatement, - isIterationStatement: isIterationStatement, - isSourceElement: isSourceElement, - isProblematicIfStatement: isProblematicIfStatement, - - trailingStatement: trailingStatement - }; -}()); -/* vim: set sw=4 ts=4 et tw=80 : */ - - -/***/ }), -/* 438 */ -/***/ (function(module, exports) { - -/* - Copyright (C) 2013-2014 Yusuke Suzuki <utatane.tea@gmail.com> - Copyright (C) 2014 Ivan Nikulin <ifaaan@gmail.com> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -(function () { - 'use strict'; - - var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch; - - // See `tools/generate-identifier-regex.js`. - ES5Regex = { - // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierStart: - NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/, - // ECMAScript 5.1/Unicode v7.0.0 NonAsciiIdentifierPart: - NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/ - }; - - ES6Regex = { - // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart: - NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/, - // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart: - NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ - }; - - function isDecimalDigit(ch) { - return 0x30 <= ch && ch <= 0x39; // 0..9 - } - - function isHexDigit(ch) { - return 0x30 <= ch && ch <= 0x39 || // 0..9 - 0x61 <= ch && ch <= 0x66 || // a..f - 0x41 <= ch && ch <= 0x46; // A..F - } +/***/ (function(module, exports, __webpack_require__) { - function isOctalDigit(ch) { - return ch >= 0x30 && ch <= 0x37; // 0..7 - } +"use strict"; - // 7.2 White Space - NON_ASCII_WHITESPACES = [ - 0x1680, 0x180E, - 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, - 0x202F, 0x205F, - 0x3000, - 0xFEFF - ]; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isIdentifierStart = isIdentifierStart; +exports.isIdentifierChar = isIdentifierChar; +exports.isIdentifierName = isIdentifierName; +let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; +let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; +const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); +const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; +const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; +const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; + +function isInAstralSet(code, set) { + let pos = 0x10000; + + for (let i = 0, length = set.length; i < length; i += 2) { + pos += set[i]; + if (pos > code) return false; + pos += set[i + 1]; + if (pos >= code) return true; + } - function isWhiteSpace(ch) { - return ch === 0x20 || ch === 0x09 || ch === 0x0B || ch === 0x0C || ch === 0xA0 || - ch >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0; - } + return false; +} - // 7.3 Line Terminators +function isIdentifierStart(code) { + if (code < 65) return code === 36; + if (code <= 90) return true; + if (code < 97) return code === 95; + if (code <= 122) return true; - function isLineTerminator(ch) { - return ch === 0x0A || ch === 0x0D || ch === 0x2028 || ch === 0x2029; - } + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + } - // 7.6 Identifier Names and Identifiers + return isInAstralSet(code, astralIdentifierStartCodes); +} - function fromCodePoint(cp) { - if (cp <= 0xFFFF) { return String.fromCharCode(cp); } - var cu1 = String.fromCharCode(Math.floor((cp - 0x10000) / 0x400) + 0xD800); - var cu2 = String.fromCharCode(((cp - 0x10000) % 0x400) + 0xDC00); - return cu1 + cu2; - } +function isIdentifierChar(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code <= 90) return true; + if (code < 97) return code === 95; + if (code <= 122) return true; - IDENTIFIER_START = new Array(0x80); - for(ch = 0; ch < 0x80; ++ch) { - IDENTIFIER_START[ch] = - ch >= 0x61 && ch <= 0x7A || // a..z - ch >= 0x41 && ch <= 0x5A || // A..Z - ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) - } + if (code <= 0xffff) { + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + } - IDENTIFIER_PART = new Array(0x80); - for(ch = 0; ch < 0x80; ++ch) { - IDENTIFIER_PART[ch] = - ch >= 0x61 && ch <= 0x7A || // a..z - ch >= 0x41 && ch <= 0x5A || // A..Z - ch >= 0x30 && ch <= 0x39 || // 0..9 - ch === 0x24 || ch === 0x5F; // $ (dollar) and _ (underscore) - } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); +} - function isIdentifierStartES5(ch) { - return ch < 0x80 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); - } +function isIdentifierName(name) { + let isFirst = true; - function isIdentifierPartES5(ch) { - return ch < 0x80 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); - } + for (let _i = 0, _Array$from = Array.from(name); _i < _Array$from.length; _i++) { + const char = _Array$from[_i]; + const cp = char.codePointAt(0); - function isIdentifierStartES6(ch) { - return ch < 0x80 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)); - } + if (isFirst) { + if (!isIdentifierStart(cp)) { + return false; + } - function isIdentifierPartES6(ch) { - return ch < 0x80 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)); + isFirst = false; + } else if (!isIdentifierChar(cp)) { + return false; } + } - module.exports = { - isDecimalDigit: isDecimalDigit, - isHexDigit: isHexDigit, - isOctalDigit: isOctalDigit, - isWhiteSpace: isWhiteSpace, - isLineTerminator: isLineTerminator, - isIdentifierStartES5: isIdentifierStartES5, - isIdentifierPartES5: isIdentifierPartES5, - isIdentifierStartES6: isIdentifierStartES6, - isIdentifierPartES6: isIdentifierPartES6 - }; -}()); -/* vim: set sw=4 ts=4 et tw=80 : */ - + return true; +} /***/ }), -/* 439 */ +/* 438 */ /***/ (function(module, exports, __webpack_require__) { -/* - Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -(function () { - 'use strict'; - - var code = __webpack_require__(438); - - function isStrictModeReservedWordES6(id) { - switch (id) { - case 'implements': - case 'interface': - case 'package': - case 'private': - case 'protected': - case 'public': - case 'static': - case 'let': - return true; - default: - return false; - } - } - - function isKeywordES5(id, strict) { - // yield should not be treated as keyword under non-strict mode. - if (!strict && id === 'yield') { - return false; - } - return isKeywordES6(id, strict); - } - - function isKeywordES6(id, strict) { - if (strict && isStrictModeReservedWordES6(id)) { - return true; - } - - switch (id.length) { - case 2: - return (id === 'if') || (id === 'in') || (id === 'do'); - case 3: - return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try'); - case 4: - return (id === 'this') || (id === 'else') || (id === 'case') || - (id === 'void') || (id === 'with') || (id === 'enum'); - case 5: - return (id === 'while') || (id === 'break') || (id === 'catch') || - (id === 'throw') || (id === 'const') || (id === 'yield') || - (id === 'class') || (id === 'super'); - case 6: - return (id === 'return') || (id === 'typeof') || (id === 'delete') || - (id === 'switch') || (id === 'export') || (id === 'import'); - case 7: - return (id === 'default') || (id === 'finally') || (id === 'extends'); - case 8: - return (id === 'function') || (id === 'continue') || (id === 'debugger'); - case 10: - return (id === 'instanceof'); - default: - return false; - } - } - - function isReservedWordES5(id, strict) { - return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict); - } - - function isReservedWordES6(id, strict) { - return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict); - } - - function isRestrictedWord(id) { - return id === 'eval' || id === 'arguments'; - } - - function isIdentifierNameES5(id) { - var i, iz, ch; - - if (id.length === 0) { return false; } - - ch = id.charCodeAt(0); - if (!code.isIdentifierStartES5(ch)) { - return false; - } - - for (i = 1, iz = id.length; i < iz; ++i) { - ch = id.charCodeAt(i); - if (!code.isIdentifierPartES5(ch)) { - return false; - } - } - return true; - } - - function decodeUtf16(lead, trail) { - return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; - } +"use strict"; - function isIdentifierNameES6(id) { - var i, iz, ch, lowCh, check; - if (id.length === 0) { return false; } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isReservedWord = isReservedWord; +exports.isStrictReservedWord = isStrictReservedWord; +exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord; +exports.isStrictBindReservedWord = isStrictBindReservedWord; +exports.isKeyword = isKeyword; +const reservedWords = { + keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"], + strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"], + strictBind: ["eval", "arguments"] +}; +const keywords = new Set(reservedWords.keyword); +const reservedWordsStrictSet = new Set(reservedWords.strict); +const reservedWordsStrictBindSet = new Set(reservedWords.strictBind); - check = code.isIdentifierStartES6; - for (i = 0, iz = id.length; i < iz; ++i) { - ch = id.charCodeAt(i); - if (0xD800 <= ch && ch <= 0xDBFF) { - ++i; - if (i >= iz) { return false; } - lowCh = id.charCodeAt(i); - if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) { - return false; - } - ch = decodeUtf16(ch, lowCh); - } - if (!check(ch)) { - return false; - } - check = code.isIdentifierPartES6; - } - return true; - } +function isReservedWord(word, inModule) { + return inModule && word === "await" || word === "enum"; +} - function isIdentifierES5(id, strict) { - return isIdentifierNameES5(id) && !isReservedWordES5(id, strict); - } +function isStrictReservedWord(word, inModule) { + return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word); +} - function isIdentifierES6(id, strict) { - return isIdentifierNameES6(id) && !isReservedWordES6(id, strict); - } +function isStrictBindOnlyReservedWord(word) { + return reservedWordsStrictBindSet.has(word); +} - module.exports = { - isKeywordES5: isKeywordES5, - isKeywordES6: isKeywordES6, - isReservedWordES5: isReservedWordES5, - isReservedWordES6: isReservedWordES6, - isRestrictedWord: isRestrictedWord, - isIdentifierNameES5: isIdentifierNameES5, - isIdentifierNameES6: isIdentifierNameES6, - isIdentifierES5: isIdentifierES5, - isIdentifierES6: isIdentifierES6 - }; -}()); -/* vim: set sw=4 ts=4 et tw=80 : */ +function isStrictBindReservedWord(word, inModule) { + return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word); +} +function isKeyword(word) { + return keywords.has(word); +} /***/ }), -/* 440 */ +/* 439 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(441); -const stdoutColor = __webpack_require__(442).stdout; +const ansiStyles = __webpack_require__(440); +const stdoutColor = __webpack_require__(441).stdout; -const template = __webpack_require__(443); +const template = __webpack_require__(442); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -39240,7 +38902,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 441 */ +/* 440 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39413,7 +39075,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 442 */ +/* 441 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39555,7 +39217,7 @@ module.exports = { /***/ }), -/* 443 */ +/* 442 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39690,7 +39352,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 444 */ +/* 443 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39729,7 +39391,7 @@ exports.KBN_P12_PASSWORD = 'storepass'; /***/ }), -/* 445 */ +/* 444 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39753,9 +39415,9 @@ exports.KBN_P12_PASSWORD = 'storepass'; * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -var run_1 = __webpack_require__(446); +var run_1 = __webpack_require__(445); exports.run = run_1.run; -var fail_1 = __webpack_require__(447); +var fail_1 = __webpack_require__(446); exports.createFailError = fail_1.createFailError; exports.createFlagError = fail_1.createFlagError; exports.combineErrors = fail_1.combineErrors; @@ -39763,7 +39425,7 @@ exports.isFailError = fail_1.isFailError; /***/ }), -/* 446 */ +/* 445 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39792,8 +39454,8 @@ const util_1 = __webpack_require__(29); // @ts-ignore @types are outdated and module is super simple const exit_hook_1 = tslib_1.__importDefault(__webpack_require__(348)); const tooling_log_1 = __webpack_require__(414); -const fail_1 = __webpack_require__(447); -const flags_1 = __webpack_require__(448); +const fail_1 = __webpack_require__(446); +const flags_1 = __webpack_require__(447); const proc_runner_1 = __webpack_require__(37); async function run(fn, options = {}) { var _a; @@ -39868,7 +39530,7 @@ exports.run = run; /***/ }), -/* 447 */ +/* 446 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39936,7 +39598,7 @@ exports.combineErrors = combineErrors; /***/ }), -/* 448 */ +/* 447 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39963,7 +39625,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(36); const path_1 = __webpack_require__(16); const dedent_1 = tslib_1.__importDefault(__webpack_require__(14)); -const getopts_1 = tslib_1.__importDefault(__webpack_require__(449)); +const getopts_1 = tslib_1.__importDefault(__webpack_require__(448)); function getFlags(argv, options) { const unexpectedNames = new Set(); const flagOpts = options.flags || {}; @@ -40066,7 +39728,7 @@ exports.getHelp = getHelp; /***/ }), -/* 449 */ +/* 448 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40278,7 +39940,7 @@ module.exports = getopts /***/ }), -/* 450 */ +/* 449 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40302,14 +39964,14 @@ module.exports = getopts * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -var kbn_client_1 = __webpack_require__(451); +var kbn_client_1 = __webpack_require__(450); exports.KbnClient = kbn_client_1.KbnClient; -var kbn_client_requester_1 = __webpack_require__(452); +var kbn_client_requester_1 = __webpack_require__(451); exports.uriencode = kbn_client_requester_1.uriencode; /***/ }), -/* 451 */ +/* 450 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40333,12 +39995,12 @@ exports.uriencode = kbn_client_requester_1.uriencode; * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -const kbn_client_requester_1 = __webpack_require__(452); -const kbn_client_status_1 = __webpack_require__(494); -const kbn_client_plugins_1 = __webpack_require__(495); -const kbn_client_version_1 = __webpack_require__(496); -const kbn_client_saved_objects_1 = __webpack_require__(497); -const kbn_client_ui_settings_1 = __webpack_require__(498); +const kbn_client_requester_1 = __webpack_require__(451); +const kbn_client_status_1 = __webpack_require__(493); +const kbn_client_plugins_1 = __webpack_require__(494); +const kbn_client_version_1 = __webpack_require__(495); +const kbn_client_saved_objects_1 = __webpack_require__(496); +const kbn_client_ui_settings_1 = __webpack_require__(497); class KbnClient { /** * Basic Kibana server client that implements common behaviors for talking @@ -40376,7 +40038,7 @@ exports.KbnClient = KbnClient; /***/ }), -/* 452 */ +/* 451 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40401,9 +40063,9 @@ exports.KbnClient = KbnClient; */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(36); -const url_1 = tslib_1.__importDefault(__webpack_require__(453)); -const axios_1 = tslib_1.__importDefault(__webpack_require__(454)); -const axios_2 = __webpack_require__(492); +const url_1 = tslib_1.__importDefault(__webpack_require__(452)); +const axios_1 = tslib_1.__importDefault(__webpack_require__(453)); +const axios_2 = __webpack_require__(491); const isConcliftOnGetError = (error) => { return (axios_2.isAxiosResponseError(error) && error.config.method === 'GET' && error.response.status === 409); }; @@ -40487,28 +40149,28 @@ exports.KbnClientRequester = KbnClientRequester; /***/ }), -/* 453 */ +/* 452 */ /***/ (function(module, exports) { module.exports = require("url"); /***/ }), -/* 454 */ +/* 453 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = __webpack_require__(455); +module.exports = __webpack_require__(454); /***/ }), -/* 455 */ +/* 454 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); -var bind = __webpack_require__(457); -var Axios = __webpack_require__(459); -var defaults = __webpack_require__(460); +var utils = __webpack_require__(455); +var bind = __webpack_require__(456); +var Axios = __webpack_require__(458); +var defaults = __webpack_require__(459); /** * Create an instance of Axios @@ -40541,15 +40203,15 @@ axios.create = function create(instanceConfig) { }; // Expose Cancel & CancelToken -axios.Cancel = __webpack_require__(489); -axios.CancelToken = __webpack_require__(490); -axios.isCancel = __webpack_require__(486); +axios.Cancel = __webpack_require__(488); +axios.CancelToken = __webpack_require__(489); +axios.isCancel = __webpack_require__(485); // Expose all/spread axios.all = function all(promises) { return Promise.all(promises); }; -axios.spread = __webpack_require__(491); +axios.spread = __webpack_require__(490); module.exports = axios; @@ -40558,14 +40220,14 @@ module.exports.default = axios; /***/ }), -/* 456 */ +/* 455 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var bind = __webpack_require__(457); -var isBuffer = __webpack_require__(458); +var bind = __webpack_require__(456); +var isBuffer = __webpack_require__(457); /*global toString:true*/ @@ -40868,7 +40530,7 @@ module.exports = { /***/ }), -/* 457 */ +/* 456 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40886,7 +40548,7 @@ module.exports = function bind(fn, thisArg) { /***/ }), -/* 458 */ +/* 457 */ /***/ (function(module, exports) { /*! @@ -40903,16 +40565,16 @@ module.exports = function isBuffer (obj) { /***/ }), -/* 459 */ +/* 458 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var defaults = __webpack_require__(460); -var utils = __webpack_require__(456); -var InterceptorManager = __webpack_require__(483); -var dispatchRequest = __webpack_require__(484); +var defaults = __webpack_require__(459); +var utils = __webpack_require__(455); +var InterceptorManager = __webpack_require__(482); +var dispatchRequest = __webpack_require__(483); /** * Create a new instance of Axios @@ -40989,14 +40651,14 @@ module.exports = Axios; /***/ }), -/* 460 */ +/* 459 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); -var normalizeHeaderName = __webpack_require__(461); +var utils = __webpack_require__(455); +var normalizeHeaderName = __webpack_require__(460); var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' @@ -41012,10 +40674,10 @@ function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== 'undefined') { // For browsers use XHR adapter - adapter = __webpack_require__(462); + adapter = __webpack_require__(461); } else if (typeof process !== 'undefined') { // For node use HTTP adapter - adapter = __webpack_require__(470); + adapter = __webpack_require__(469); } return adapter; } @@ -41092,13 +40754,13 @@ module.exports = defaults; /***/ }), -/* 461 */ +/* 460 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); module.exports = function normalizeHeaderName(headers, normalizedName) { utils.forEach(headers, function processHeader(value, name) { @@ -41111,18 +40773,18 @@ module.exports = function normalizeHeaderName(headers, normalizedName) { /***/ }), -/* 462 */ +/* 461 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); -var settle = __webpack_require__(463); -var buildURL = __webpack_require__(466); -var parseHeaders = __webpack_require__(467); -var isURLSameOrigin = __webpack_require__(468); -var createError = __webpack_require__(464); +var utils = __webpack_require__(455); +var settle = __webpack_require__(462); +var buildURL = __webpack_require__(465); +var parseHeaders = __webpack_require__(466); +var isURLSameOrigin = __webpack_require__(467); +var createError = __webpack_require__(463); module.exports = function xhrAdapter(config) { return new Promise(function dispatchXhrRequest(resolve, reject) { @@ -41202,7 +40864,7 @@ module.exports = function xhrAdapter(config) { // This is only done if running in a standard browser environment. // Specifically not if we're in a web worker, or react-native. if (utils.isStandardBrowserEnv()) { - var cookies = __webpack_require__(469); + var cookies = __webpack_require__(468); // Add xsrf header var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? @@ -41280,13 +40942,13 @@ module.exports = function xhrAdapter(config) { /***/ }), -/* 463 */ +/* 462 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var createError = __webpack_require__(464); +var createError = __webpack_require__(463); /** * Resolve or reject a Promise based on response status. @@ -41313,13 +40975,13 @@ module.exports = function settle(resolve, reject, response) { /***/ }), -/* 464 */ +/* 463 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var enhanceError = __webpack_require__(465); +var enhanceError = __webpack_require__(464); /** * Create an Error with the specified message, config, error code, request and response. @@ -41338,7 +41000,7 @@ module.exports = function createError(message, config, code, request, response) /***/ }), -/* 465 */ +/* 464 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41366,13 +41028,13 @@ module.exports = function enhanceError(error, config, code, request, response) { /***/ }), -/* 466 */ +/* 465 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); function encode(val) { return encodeURIComponent(val). @@ -41439,13 +41101,13 @@ module.exports = function buildURL(url, params, paramsSerializer) { /***/ }), -/* 467 */ +/* 466 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); // Headers whose duplicates are ignored by node // c.f. https://nodejs.org/api/http.html#http_message_headers @@ -41499,13 +41161,13 @@ module.exports = function parseHeaders(headers) { /***/ }), -/* 468 */ +/* 467 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); module.exports = ( utils.isStandardBrowserEnv() ? @@ -41574,13 +41236,13 @@ module.exports = ( /***/ }), -/* 469 */ +/* 468 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); module.exports = ( utils.isStandardBrowserEnv() ? @@ -41634,24 +41296,24 @@ module.exports = ( /***/ }), -/* 470 */ +/* 469 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); -var settle = __webpack_require__(463); -var buildURL = __webpack_require__(466); -var http = __webpack_require__(471); -var https = __webpack_require__(472); -var httpFollow = __webpack_require__(473).http; -var httpsFollow = __webpack_require__(473).https; -var url = __webpack_require__(453); -var zlib = __webpack_require__(481); -var pkg = __webpack_require__(482); -var createError = __webpack_require__(464); -var enhanceError = __webpack_require__(465); +var utils = __webpack_require__(455); +var settle = __webpack_require__(462); +var buildURL = __webpack_require__(465); +var http = __webpack_require__(470); +var https = __webpack_require__(471); +var httpFollow = __webpack_require__(472).http; +var httpsFollow = __webpack_require__(472).https; +var url = __webpack_require__(452); +var zlib = __webpack_require__(480); +var pkg = __webpack_require__(481); +var createError = __webpack_require__(463); +var enhanceError = __webpack_require__(464); /*eslint consistent-return:0*/ module.exports = function httpAdapter(config) { @@ -41879,27 +41541,27 @@ module.exports = function httpAdapter(config) { /***/ }), -/* 471 */ +/* 470 */ /***/ (function(module, exports) { module.exports = require("http"); /***/ }), -/* 472 */ +/* 471 */ /***/ (function(module, exports) { module.exports = require("https"); /***/ }), -/* 473 */ +/* 472 */ /***/ (function(module, exports, __webpack_require__) { -var url = __webpack_require__(453); -var http = __webpack_require__(471); -var https = __webpack_require__(472); +var url = __webpack_require__(452); +var http = __webpack_require__(470); +var https = __webpack_require__(471); var assert = __webpack_require__(30); var Writable = __webpack_require__(27).Writable; -var debug = __webpack_require__(474)("follow-redirects"); +var debug = __webpack_require__(473)("follow-redirects"); // RFC7231§4.2.1: Of the request methods defined by this specification, // the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. @@ -42219,7 +41881,7 @@ module.exports.wrap = wrap; /***/ }), -/* 474 */ +/* 473 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -42228,14 +41890,14 @@ module.exports.wrap = wrap; */ if (typeof process === 'undefined' || process.type === 'renderer') { - module.exports = __webpack_require__(475); + module.exports = __webpack_require__(474); } else { - module.exports = __webpack_require__(478); + module.exports = __webpack_require__(477); } /***/ }), -/* 475 */ +/* 474 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -42244,7 +41906,7 @@ if (typeof process === 'undefined' || process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(476); +exports = module.exports = __webpack_require__(475); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -42436,7 +42098,7 @@ function localstorage() { /***/ }), -/* 476 */ +/* 475 */ /***/ (function(module, exports, __webpack_require__) { @@ -42452,7 +42114,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(477); +exports.humanize = __webpack_require__(476); /** * Active `debug` instances. @@ -42667,7 +42329,7 @@ function coerce(val) { /***/ }), -/* 477 */ +/* 476 */ /***/ (function(module, exports) { /** @@ -42825,14 +42487,14 @@ function plural(ms, n, name) { /***/ }), -/* 478 */ +/* 477 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(479); +var tty = __webpack_require__(478); var util = __webpack_require__(29); /** @@ -42841,7 +42503,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(476); +exports = module.exports = __webpack_require__(475); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -42856,7 +42518,7 @@ exports.useColors = useColors; exports.colors = [ 6, 2, 3, 4, 5, 1 ]; try { - var supportsColor = __webpack_require__(480); + var supportsColor = __webpack_require__(479); if (supportsColor && supportsColor.level >= 2) { exports.colors = [ 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, @@ -43017,13 +42679,13 @@ exports.enable(load()); /***/ }), -/* 479 */ +/* 478 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 480 */ +/* 479 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43168,25 +42830,25 @@ module.exports = { /***/ }), -/* 481 */ +/* 480 */ /***/ (function(module, exports) { module.exports = require("zlib"); /***/ }), -/* 482 */ +/* 481 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"axios\",\"version\":\"0.18.1\",\"description\":\"Promise based HTTP client for the browser and node.js\",\"main\":\"index.js\",\"scripts\":{\"test\":\"grunt test && bundlesize\",\"start\":\"node ./sandbox/server.js\",\"build\":\"NODE_ENV=production grunt build\",\"preversion\":\"npm test\",\"version\":\"npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json\",\"postversion\":\"git push && git push --tags\",\"examples\":\"node ./examples/server.js\",\"coveralls\":\"cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\"},\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/axios/axios.git\"},\"keywords\":[\"xhr\",\"http\",\"ajax\",\"promise\",\"node\"],\"author\":\"Matt Zabriskie\",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/axios/axios/issues\"},\"homepage\":\"https://github.com/axios/axios\",\"devDependencies\":{\"bundlesize\":\"^0.5.7\",\"coveralls\":\"^2.11.9\",\"es6-promise\":\"^4.0.5\",\"grunt\":\"^1.0.1\",\"grunt-banner\":\"^0.6.0\",\"grunt-cli\":\"^1.2.0\",\"grunt-contrib-clean\":\"^1.0.0\",\"grunt-contrib-nodeunit\":\"^1.0.0\",\"grunt-contrib-watch\":\"^1.0.0\",\"grunt-eslint\":\"^19.0.0\",\"grunt-karma\":\"^2.0.0\",\"grunt-ts\":\"^6.0.0-beta.3\",\"grunt-webpack\":\"^1.0.18\",\"istanbul-instrumenter-loader\":\"^1.0.0\",\"jasmine-core\":\"^2.4.1\",\"karma\":\"^1.3.0\",\"karma-chrome-launcher\":\"^2.0.0\",\"karma-coverage\":\"^1.0.0\",\"karma-firefox-launcher\":\"^1.0.0\",\"karma-jasmine\":\"^1.0.2\",\"karma-jasmine-ajax\":\"^0.1.13\",\"karma-opera-launcher\":\"^1.0.0\",\"karma-safari-launcher\":\"^1.0.0\",\"karma-sauce-launcher\":\"^1.1.0\",\"karma-sinon\":\"^1.0.5\",\"karma-sourcemap-loader\":\"^0.3.7\",\"karma-webpack\":\"^1.7.0\",\"load-grunt-tasks\":\"^3.5.2\",\"minimist\":\"^1.2.0\",\"sinon\":\"^1.17.4\",\"webpack\":\"^1.13.1\",\"webpack-dev-server\":\"^1.14.1\",\"url-search-params\":\"^0.6.1\",\"typescript\":\"^2.0.3\"},\"browser\":{\"./lib/adapters/http.js\":\"./lib/adapters/xhr.js\"},\"typings\":\"./index.d.ts\",\"dependencies\":{\"follow-redirects\":\"1.5.10\",\"is-buffer\":\"^2.0.2\"},\"bundlesize\":[{\"path\":\"./dist/axios.min.js\",\"threshold\":\"5kB\"}]}"); /***/ }), -/* 483 */ +/* 482 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); function InterceptorManager() { this.handlers = []; @@ -43239,18 +42901,18 @@ module.exports = InterceptorManager; /***/ }), -/* 484 */ +/* 483 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); -var transformData = __webpack_require__(485); -var isCancel = __webpack_require__(486); -var defaults = __webpack_require__(460); -var isAbsoluteURL = __webpack_require__(487); -var combineURLs = __webpack_require__(488); +var utils = __webpack_require__(455); +var transformData = __webpack_require__(484); +var isCancel = __webpack_require__(485); +var defaults = __webpack_require__(459); +var isAbsoluteURL = __webpack_require__(486); +var combineURLs = __webpack_require__(487); /** * Throws a `Cancel` if cancellation has been requested. @@ -43332,13 +42994,13 @@ module.exports = function dispatchRequest(config) { /***/ }), -/* 485 */ +/* 484 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(456); +var utils = __webpack_require__(455); /** * Transform the data for a request or a response @@ -43359,7 +43021,7 @@ module.exports = function transformData(data, headers, fns) { /***/ }), -/* 486 */ +/* 485 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43371,7 +43033,7 @@ module.exports = function isCancel(value) { /***/ }), -/* 487 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43392,7 +43054,7 @@ module.exports = function isAbsoluteURL(url) { /***/ }), -/* 488 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43413,7 +43075,7 @@ module.exports = function combineURLs(baseURL, relativeURL) { /***/ }), -/* 489 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43439,13 +43101,13 @@ module.exports = Cancel; /***/ }), -/* 490 */ +/* 489 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Cancel = __webpack_require__(489); +var Cancel = __webpack_require__(488); /** * A `CancelToken` is an object that can be used to request cancellation of an operation. @@ -43503,7 +43165,7 @@ module.exports = CancelToken; /***/ }), -/* 491 */ +/* 490 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43537,7 +43199,7 @@ module.exports = function spread(callback) { /***/ }), -/* 492 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43562,11 +43224,11 @@ module.exports = function spread(callback) { */ Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = __webpack_require__(36); -tslib_1.__exportStar(__webpack_require__(493), exports); +tslib_1.__exportStar(__webpack_require__(492), exports); /***/ }), -/* 493 */ +/* 492 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43599,7 +43261,7 @@ exports.isAxiosResponseError = (error) => { /***/ }), -/* 494 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43648,7 +43310,7 @@ exports.KbnClientStatus = KbnClientStatus; /***/ }), -/* 495 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43698,7 +43360,7 @@ exports.KbnClientPlugins = KbnClientPlugins; /***/ }), -/* 496 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43739,7 +43401,7 @@ exports.KbnClientVersion = KbnClientVersion; /***/ }), -/* 497 */ +/* 496 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43763,7 +43425,7 @@ exports.KbnClientVersion = KbnClientVersion; * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -const kbn_client_requester_1 = __webpack_require__(452); +const kbn_client_requester_1 = __webpack_require__(451); class KbnClientSavedObjects { constructor(log, requester) { this.log = log; @@ -43848,7 +43510,7 @@ exports.KbnClientSavedObjects = KbnClientSavedObjects; /***/ }), -/* 498 */ +/* 497 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43872,7 +43534,7 @@ exports.KbnClientSavedObjects = KbnClientSavedObjects; * under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); -const kbn_client_requester_1 = __webpack_require__(452); +const kbn_client_requester_1 = __webpack_require__(451); class KbnClientUiSettings { constructor(log, requester, defaults) { this.log = log; @@ -43948,7 +43610,7 @@ exports.KbnClientUiSettings = KbnClientUiSettings; /***/ }), -/* 499 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -44014,7 +43676,7 @@ async function parallelize(items, fn, concurrency = 4) { } /***/ }), -/* 500 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -44023,15 +43685,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; }); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(501); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(500); /* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514); -/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(577); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(513); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(514); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(576); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -44230,7 +43892,7 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { } /***/ }), -/* 501 */ +/* 500 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -44276,21 +43938,21 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { module.exports = glob var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(508) +var inherits = __webpack_require__(507) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var globSync = __webpack_require__(511) -var common = __webpack_require__(512) +var isAbsolute = __webpack_require__(509) +var globSync = __webpack_require__(510) +var common = __webpack_require__(511) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(513) +var inflight = __webpack_require__(512) var util = __webpack_require__(29) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored @@ -45026,7 +44688,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 502 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { module.exports = realpath @@ -45042,7 +44704,7 @@ var origRealpathSync = fs.realpathSync var version = process.version var ok = /^v[0-5]\./.test(version) -var old = __webpack_require__(503) +var old = __webpack_require__(502) function newError (er) { return er && er.syscall === 'realpath' && ( @@ -45098,7 +44760,7 @@ function unmonkeypatch () { /***/ }), -/* 503 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { // Copyright Joyent, Inc. and other Node contributors. @@ -45407,7 +45069,7 @@ exports.realpath = function realpath(p, cache, cb) { /***/ }), -/* 504 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { module.exports = minimatch @@ -45419,7 +45081,7 @@ try { } catch (er) {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = __webpack_require__(505) +var expand = __webpack_require__(504) var plTypes = { '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, @@ -46336,11 +45998,11 @@ function regExpEscape (s) { /***/ }), -/* 505 */ +/* 504 */ /***/ (function(module, exports, __webpack_require__) { -var concatMap = __webpack_require__(506); -var balanced = __webpack_require__(507); +var concatMap = __webpack_require__(505); +var balanced = __webpack_require__(506); module.exports = expandTop; @@ -46543,7 +46205,7 @@ function expand(str, isTop) { /***/ }), -/* 506 */ +/* 505 */ /***/ (function(module, exports) { module.exports = function (xs, fn) { @@ -46562,7 +46224,7 @@ var isArray = Array.isArray || function (xs) { /***/ }), -/* 507 */ +/* 506 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46628,7 +46290,7 @@ function range(a, b, str) { /***/ }), -/* 508 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -46638,12 +46300,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(509); + module.exports = __webpack_require__(508); } /***/ }), -/* 509 */ +/* 508 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -46676,7 +46338,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 510 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46703,22 +46365,22 @@ module.exports.win32 = win32; /***/ }), -/* 511 */ +/* 510 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(501).Glob +var Glob = __webpack_require__(500).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var common = __webpack_require__(512) +var isAbsolute = __webpack_require__(509) +var common = __webpack_require__(511) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -47195,7 +46857,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 512 */ +/* 511 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -47213,8 +46875,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(16) -var minimatch = __webpack_require__(504) -var isAbsolute = __webpack_require__(510) +var minimatch = __webpack_require__(503) +var isAbsolute = __webpack_require__(509) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -47441,7 +47103,7 @@ function childrenIgnored (self, path) { /***/ }), -/* 513 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { var wrappy = __webpack_require__(385) @@ -47501,7 +47163,7 @@ function slice (args) { /***/ }), -/* 514 */ +/* 513 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -47534,7 +47196,7 @@ class CliError extends Error { } /***/ }), -/* 515 */ +/* 514 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -47548,13 +47210,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(514); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(513); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(562); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(515); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(561); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -47782,7 +47444,7 @@ function normalizePath(path) { } /***/ }), -/* 516 */ +/* 515 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -47790,9 +47452,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readPackageJson", function() { return readPackageJson; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writePackageJson", function() { return writePackageJson; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; }); -/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(517); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(516); /* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(543); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(542); /* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -47826,7 +47488,7 @@ function writePackageJson(path, json) { const isLinkDependency = depVersion => depVersion.startsWith('link:'); /***/ }), -/* 517 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47834,7 +47496,7 @@ const isLinkDependency = depVersion => depVersion.startsWith('link:'); const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); -const parseJson = __webpack_require__(518); +const parseJson = __webpack_require__(517); const readFileAsync = promisify(fs.readFile); @@ -47849,7 +47511,7 @@ module.exports = async options => { const json = parseJson(await readFileAsync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(519)(json); + __webpack_require__(518)(json); } return json; @@ -47866,7 +47528,7 @@ module.exports.sync = options => { const json = parseJson(fs.readFileSync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(519)(json); + __webpack_require__(518)(json); } return json; @@ -47874,7 +47536,7 @@ module.exports.sync = options => { /***/ }), -/* 518 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47931,15 +47593,15 @@ module.exports = (string, reviver, filename) => { /***/ }), -/* 519 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { module.exports = normalize -var fixer = __webpack_require__(520) +var fixer = __webpack_require__(519) normalize.fixer = fixer -var makeWarning = __webpack_require__(541) +var makeWarning = __webpack_require__(540) var fieldsToFix = ['name','version','description','repository','modules','scripts' ,'files','bin','man','bugs','keywords','readme','homepage','license'] @@ -47976,17 +47638,17 @@ function ucFirst (string) { /***/ }), -/* 520 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { -var semver = __webpack_require__(521) -var validateLicense = __webpack_require__(522); -var hostedGitInfo = __webpack_require__(527) -var isBuiltinModule = __webpack_require__(530).isCore +var semver = __webpack_require__(520) +var validateLicense = __webpack_require__(521); +var hostedGitInfo = __webpack_require__(526) +var isBuiltinModule = __webpack_require__(529).isCore var depTypes = ["dependencies","devDependencies","optionalDependencies"] -var extractDescription = __webpack_require__(539) -var url = __webpack_require__(453) -var typos = __webpack_require__(540) +var extractDescription = __webpack_require__(538) +var url = __webpack_require__(452) +var typos = __webpack_require__(539) var fixer = module.exports = { // default warning function @@ -48400,7 +48062,7 @@ function bugsTypos(bugs, warn) { /***/ }), -/* 521 */ +/* 520 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -49889,11 +49551,11 @@ function coerce (version) { /***/ }), -/* 522 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(523); -var correct = __webpack_require__(525); +var parse = __webpack_require__(522); +var correct = __webpack_require__(524); var genericWarning = ( 'license should be ' + @@ -49979,10 +49641,10 @@ module.exports = function(argument) { /***/ }), -/* 523 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { -var parser = __webpack_require__(524).parser +var parser = __webpack_require__(523).parser module.exports = function (argument) { return parser.parse(argument) @@ -49990,7 +49652,7 @@ module.exports = function (argument) { /***/ }), -/* 524 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ @@ -51354,10 +51016,10 @@ if ( true && __webpack_require__.c[__webpack_require__.s] === module) { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 525 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { -var licenseIDs = __webpack_require__(526); +var licenseIDs = __webpack_require__(525); function valid(string) { return licenseIDs.indexOf(string) > -1; @@ -51597,20 +51259,20 @@ module.exports = function(identifier) { /***/ }), -/* 526 */ +/* 525 */ /***/ (function(module) { module.exports = JSON.parse("[\"Glide\",\"Abstyles\",\"AFL-1.1\",\"AFL-1.2\",\"AFL-2.0\",\"AFL-2.1\",\"AFL-3.0\",\"AMPAS\",\"APL-1.0\",\"Adobe-Glyph\",\"APAFML\",\"Adobe-2006\",\"AGPL-1.0\",\"Afmparse\",\"Aladdin\",\"ADSL\",\"AMDPLPA\",\"ANTLR-PD\",\"Apache-1.0\",\"Apache-1.1\",\"Apache-2.0\",\"AML\",\"APSL-1.0\",\"APSL-1.1\",\"APSL-1.2\",\"APSL-2.0\",\"Artistic-1.0\",\"Artistic-1.0-Perl\",\"Artistic-1.0-cl8\",\"Artistic-2.0\",\"AAL\",\"Bahyph\",\"Barr\",\"Beerware\",\"BitTorrent-1.0\",\"BitTorrent-1.1\",\"BSL-1.0\",\"Borceux\",\"BSD-2-Clause\",\"BSD-2-Clause-FreeBSD\",\"BSD-2-Clause-NetBSD\",\"BSD-3-Clause\",\"BSD-3-Clause-Clear\",\"BSD-4-Clause\",\"BSD-Protection\",\"BSD-Source-Code\",\"BSD-3-Clause-Attribution\",\"0BSD\",\"BSD-4-Clause-UC\",\"bzip2-1.0.5\",\"bzip2-1.0.6\",\"Caldera\",\"CECILL-1.0\",\"CECILL-1.1\",\"CECILL-2.0\",\"CECILL-2.1\",\"CECILL-B\",\"CECILL-C\",\"ClArtistic\",\"MIT-CMU\",\"CNRI-Jython\",\"CNRI-Python\",\"CNRI-Python-GPL-Compatible\",\"CPOL-1.02\",\"CDDL-1.0\",\"CDDL-1.1\",\"CPAL-1.0\",\"CPL-1.0\",\"CATOSL-1.1\",\"Condor-1.1\",\"CC-BY-1.0\",\"CC-BY-2.0\",\"CC-BY-2.5\",\"CC-BY-3.0\",\"CC-BY-4.0\",\"CC-BY-ND-1.0\",\"CC-BY-ND-2.0\",\"CC-BY-ND-2.5\",\"CC-BY-ND-3.0\",\"CC-BY-ND-4.0\",\"CC-BY-NC-1.0\",\"CC-BY-NC-2.0\",\"CC-BY-NC-2.5\",\"CC-BY-NC-3.0\",\"CC-BY-NC-4.0\",\"CC-BY-NC-ND-1.0\",\"CC-BY-NC-ND-2.0\",\"CC-BY-NC-ND-2.5\",\"CC-BY-NC-ND-3.0\",\"CC-BY-NC-ND-4.0\",\"CC-BY-NC-SA-1.0\",\"CC-BY-NC-SA-2.0\",\"CC-BY-NC-SA-2.5\",\"CC-BY-NC-SA-3.0\",\"CC-BY-NC-SA-4.0\",\"CC-BY-SA-1.0\",\"CC-BY-SA-2.0\",\"CC-BY-SA-2.5\",\"CC-BY-SA-3.0\",\"CC-BY-SA-4.0\",\"CC0-1.0\",\"Crossword\",\"CrystalStacker\",\"CUA-OPL-1.0\",\"Cube\",\"curl\",\"D-FSL-1.0\",\"diffmark\",\"WTFPL\",\"DOC\",\"Dotseqn\",\"DSDP\",\"dvipdfm\",\"EPL-1.0\",\"ECL-1.0\",\"ECL-2.0\",\"eGenix\",\"EFL-1.0\",\"EFL-2.0\",\"MIT-advertising\",\"MIT-enna\",\"Entessa\",\"ErlPL-1.1\",\"EUDatagrid\",\"EUPL-1.0\",\"EUPL-1.1\",\"Eurosym\",\"Fair\",\"MIT-feh\",\"Frameworx-1.0\",\"FreeImage\",\"FTL\",\"FSFAP\",\"FSFUL\",\"FSFULLR\",\"Giftware\",\"GL2PS\",\"Glulxe\",\"AGPL-3.0\",\"GFDL-1.1\",\"GFDL-1.2\",\"GFDL-1.3\",\"GPL-1.0\",\"GPL-2.0\",\"GPL-3.0\",\"LGPL-2.1\",\"LGPL-3.0\",\"LGPL-2.0\",\"gnuplot\",\"gSOAP-1.3b\",\"HaskellReport\",\"HPND\",\"IBM-pibs\",\"IPL-1.0\",\"ICU\",\"ImageMagick\",\"iMatix\",\"Imlib2\",\"IJG\",\"Info-ZIP\",\"Intel-ACPI\",\"Intel\",\"Interbase-1.0\",\"IPA\",\"ISC\",\"JasPer-2.0\",\"JSON\",\"LPPL-1.0\",\"LPPL-1.1\",\"LPPL-1.2\",\"LPPL-1.3a\",\"LPPL-1.3c\",\"Latex2e\",\"BSD-3-Clause-LBNL\",\"Leptonica\",\"LGPLLR\",\"Libpng\",\"libtiff\",\"LAL-1.2\",\"LAL-1.3\",\"LiLiQ-P-1.1\",\"LiLiQ-Rplus-1.1\",\"LiLiQ-R-1.1\",\"LPL-1.02\",\"LPL-1.0\",\"MakeIndex\",\"MTLL\",\"MS-PL\",\"MS-RL\",\"MirOS\",\"MITNFA\",\"MIT\",\"Motosoto\",\"MPL-1.0\",\"MPL-1.1\",\"MPL-2.0\",\"MPL-2.0-no-copyleft-exception\",\"mpich2\",\"Multics\",\"Mup\",\"NASA-1.3\",\"Naumen\",\"NBPL-1.0\",\"NetCDF\",\"NGPL\",\"NOSL\",\"NPL-1.0\",\"NPL-1.1\",\"Newsletr\",\"NLPL\",\"Nokia\",\"NPOSL-3.0\",\"NLOD-1.0\",\"Noweb\",\"NRL\",\"NTP\",\"Nunit\",\"OCLC-2.0\",\"ODbL-1.0\",\"PDDL-1.0\",\"OCCT-PL\",\"OGTSL\",\"OLDAP-2.2.2\",\"OLDAP-1.1\",\"OLDAP-1.2\",\"OLDAP-1.3\",\"OLDAP-1.4\",\"OLDAP-2.0\",\"OLDAP-2.0.1\",\"OLDAP-2.1\",\"OLDAP-2.2\",\"OLDAP-2.2.1\",\"OLDAP-2.3\",\"OLDAP-2.4\",\"OLDAP-2.5\",\"OLDAP-2.6\",\"OLDAP-2.7\",\"OLDAP-2.8\",\"OML\",\"OPL-1.0\",\"OSL-1.0\",\"OSL-1.1\",\"OSL-2.0\",\"OSL-2.1\",\"OSL-3.0\",\"OpenSSL\",\"OSET-PL-2.1\",\"PHP-3.0\",\"PHP-3.01\",\"Plexus\",\"PostgreSQL\",\"psfrag\",\"psutils\",\"Python-2.0\",\"QPL-1.0\",\"Qhull\",\"Rdisc\",\"RPSL-1.0\",\"RPL-1.1\",\"RPL-1.5\",\"RHeCos-1.1\",\"RSCPL\",\"RSA-MD\",\"Ruby\",\"SAX-PD\",\"Saxpath\",\"SCEA\",\"SWL\",\"SMPPL\",\"Sendmail\",\"SGI-B-1.0\",\"SGI-B-1.1\",\"SGI-B-2.0\",\"OFL-1.0\",\"OFL-1.1\",\"SimPL-2.0\",\"Sleepycat\",\"SNIA\",\"Spencer-86\",\"Spencer-94\",\"Spencer-99\",\"SMLNJ\",\"SugarCRM-1.1.3\",\"SISSL\",\"SISSL-1.2\",\"SPL-1.0\",\"Watcom-1.0\",\"TCL\",\"Unlicense\",\"TMate\",\"TORQUE-1.1\",\"TOSL\",\"Unicode-TOU\",\"UPL-1.0\",\"NCSA\",\"Vim\",\"VOSTROM\",\"VSL-1.0\",\"W3C-19980720\",\"W3C\",\"Wsuipa\",\"Xnet\",\"X11\",\"Xerox\",\"XFree86-1.1\",\"xinetd\",\"xpp\",\"XSkat\",\"YPL-1.0\",\"YPL-1.1\",\"Zed\",\"Zend-2.0\",\"Zimbra-1.3\",\"Zimbra-1.4\",\"Zlib\",\"zlib-acknowledgement\",\"ZPL-1.1\",\"ZPL-2.0\",\"ZPL-2.1\",\"BSD-3-Clause-No-Nuclear-License\",\"BSD-3-Clause-No-Nuclear-Warranty\",\"BSD-3-Clause-No-Nuclear-License-2014\",\"eCos-2.0\",\"GPL-2.0-with-autoconf-exception\",\"GPL-2.0-with-bison-exception\",\"GPL-2.0-with-classpath-exception\",\"GPL-2.0-with-font-exception\",\"GPL-2.0-with-GCC-exception\",\"GPL-3.0-with-autoconf-exception\",\"GPL-3.0-with-GCC-exception\",\"StandardML-NJ\",\"WXwindows\"]"); /***/ }), -/* 527 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var url = __webpack_require__(453) -var gitHosts = __webpack_require__(528) -var GitHost = module.exports = __webpack_require__(529) +var url = __webpack_require__(452) +var gitHosts = __webpack_require__(527) +var GitHost = module.exports = __webpack_require__(528) var protocolToRepresentationMap = { 'git+ssh': 'sshurl', @@ -51731,7 +51393,7 @@ function parseGitUrl (giturl) { /***/ }), -/* 528 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -51806,12 +51468,12 @@ Object.keys(gitHosts).forEach(function (name) { /***/ }), -/* 529 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var gitHosts = __webpack_require__(528) +var gitHosts = __webpack_require__(527) var extend = Object.assign || __webpack_require__(29)._extend var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) { @@ -51927,21 +51589,21 @@ GitHost.prototype.toString = function (opts) { /***/ }), -/* 530 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { -var core = __webpack_require__(531); -var async = __webpack_require__(533); +var core = __webpack_require__(530); +var async = __webpack_require__(532); async.core = core; async.isCore = function isCore(x) { return core[x]; }; -async.sync = __webpack_require__(538); +async.sync = __webpack_require__(537); exports = async; module.exports = async; /***/ }), -/* 531 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { var current = (process.versions && process.versions.node && process.versions.node.split('.')) || []; @@ -51988,7 +51650,7 @@ function versionIncluded(specifierValue) { return matchesRange(specifierValue); } -var data = __webpack_require__(532); +var data = __webpack_require__(531); var core = {}; for (var mod in data) { // eslint-disable-line no-restricted-syntax @@ -52000,21 +51662,21 @@ module.exports = core; /***/ }), -/* 532 */ +/* 531 */ /***/ (function(module) { module.exports = JSON.parse("{\"assert\":true,\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debugger\":\"< 8\",\"dgram\":true,\"dns\":true,\"domain\":true,\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":\">= 10 && < 10.1\",\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"string_decoder\":true,\"sys\":true,\"timers\":true,\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8\":\">= 1\",\"vm\":true,\"worker_threads\":\">= 11.7\",\"zlib\":true}"); /***/ }), -/* 533 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { -var core = __webpack_require__(531); +var core = __webpack_require__(530); var fs = __webpack_require__(23); var path = __webpack_require__(16); -var caller = __webpack_require__(534); -var nodeModulesPaths = __webpack_require__(535); -var normalizeOptions = __webpack_require__(537); +var caller = __webpack_require__(533); +var nodeModulesPaths = __webpack_require__(534); +var normalizeOptions = __webpack_require__(536); var defaultIsFile = function isFile(file, cb) { fs.stat(file, function (err, stat) { @@ -52241,7 +51903,7 @@ module.exports = function resolve(x, options, callback) { /***/ }), -/* 534 */ +/* 533 */ /***/ (function(module, exports) { module.exports = function () { @@ -52255,11 +51917,11 @@ module.exports = function () { /***/ }), -/* 535 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { var path = __webpack_require__(16); -var parse = path.parse || __webpack_require__(536); +var parse = path.parse || __webpack_require__(535); var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) { var prefix = '/'; @@ -52303,7 +51965,7 @@ module.exports = function nodeModulesPaths(start, opts, request) { /***/ }), -/* 536 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -52403,7 +52065,7 @@ module.exports.win32 = win32.parse; /***/ }), -/* 537 */ +/* 536 */ /***/ (function(module, exports) { module.exports = function (x, opts) { @@ -52419,15 +52081,15 @@ module.exports = function (x, opts) { /***/ }), -/* 538 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { -var core = __webpack_require__(531); +var core = __webpack_require__(530); var fs = __webpack_require__(23); var path = __webpack_require__(16); -var caller = __webpack_require__(534); -var nodeModulesPaths = __webpack_require__(535); -var normalizeOptions = __webpack_require__(537); +var caller = __webpack_require__(533); +var nodeModulesPaths = __webpack_require__(534); +var normalizeOptions = __webpack_require__(536); var defaultIsFile = function isFile(file) { try { @@ -52579,7 +52241,7 @@ module.exports = function (x, options) { /***/ }), -/* 539 */ +/* 538 */ /***/ (function(module, exports) { module.exports = extractDescription @@ -52599,17 +52261,17 @@ function extractDescription (d) { /***/ }), -/* 540 */ +/* 539 */ /***/ (function(module) { module.exports = JSON.parse("{\"topLevel\":{\"dependancies\":\"dependencies\",\"dependecies\":\"dependencies\",\"depdenencies\":\"dependencies\",\"devEependencies\":\"devDependencies\",\"depends\":\"dependencies\",\"dev-dependencies\":\"devDependencies\",\"devDependences\":\"devDependencies\",\"devDepenencies\":\"devDependencies\",\"devdependencies\":\"devDependencies\",\"repostitory\":\"repository\",\"repo\":\"repository\",\"prefereGlobal\":\"preferGlobal\",\"hompage\":\"homepage\",\"hampage\":\"homepage\",\"autohr\":\"author\",\"autor\":\"author\",\"contributers\":\"contributors\",\"publicationConfig\":\"publishConfig\",\"script\":\"scripts\"},\"bugs\":{\"web\":\"url\",\"name\":\"url\"},\"script\":{\"server\":\"start\",\"tests\":\"test\"}}"); /***/ }), -/* 541 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { var util = __webpack_require__(29) -var messages = __webpack_require__(542) +var messages = __webpack_require__(541) module.exports = function() { var args = Array.prototype.slice.call(arguments, 0) @@ -52634,20 +52296,20 @@ function makeTypoWarning (providedName, probableName, field) { /***/ }), -/* 542 */ +/* 541 */ /***/ (function(module) { module.exports = JSON.parse("{\"repositories\":\"'repositories' (plural) Not supported. Please pick one as the 'repository' field\",\"missingRepository\":\"No repository field.\",\"brokenGitUrl\":\"Probably broken git url: %s\",\"nonObjectScripts\":\"scripts must be an object\",\"nonStringScript\":\"script values must be string commands\",\"nonArrayFiles\":\"Invalid 'files' member\",\"invalidFilename\":\"Invalid filename in 'files' list: %s\",\"nonArrayBundleDependencies\":\"Invalid 'bundleDependencies' list. Must be array of package names\",\"nonStringBundleDependency\":\"Invalid bundleDependencies member: %s\",\"nonDependencyBundleDependency\":\"Non-dependency in bundleDependencies: %s\",\"nonObjectDependencies\":\"%s field must be an object\",\"nonStringDependency\":\"Invalid dependency: %s %s\",\"deprecatedArrayDependencies\":\"specifying %s as array is deprecated\",\"deprecatedModules\":\"modules field is deprecated\",\"nonArrayKeywords\":\"keywords should be an array of strings\",\"nonStringKeyword\":\"keywords should be an array of strings\",\"conflictingName\":\"%s is also the name of a node core module.\",\"nonStringDescription\":\"'description' field should be a string\",\"missingDescription\":\"No description\",\"missingReadme\":\"No README data\",\"missingLicense\":\"No license field.\",\"nonEmailUrlBugsString\":\"Bug string field must be url, email, or {email,url}\",\"nonUrlBugsUrlField\":\"bugs.url field must be a string url. Deleted.\",\"nonEmailBugsEmailField\":\"bugs.email field must be a string email. Deleted.\",\"emptyNormalizedBugs\":\"Normalized value of bugs field is an empty object. Deleted.\",\"nonUrlHomepage\":\"homepage field must be a string url. Deleted.\",\"invalidLicense\":\"license should be a valid SPDX license expression\",\"typo\":\"%s should probably be %s.\"}"); /***/ }), -/* 543 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const writeJsonFile = __webpack_require__(544); -const sortKeys = __webpack_require__(556); +const writeJsonFile = __webpack_require__(543); +const sortKeys = __webpack_require__(555); const dependencyKeys = new Set([ 'dependencies', @@ -52712,18 +52374,18 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 544 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const fs = __webpack_require__(545); -const writeFileAtomic = __webpack_require__(549); -const sortKeys = __webpack_require__(556); -const makeDir = __webpack_require__(558); -const pify = __webpack_require__(560); -const detectIndent = __webpack_require__(561); +const fs = __webpack_require__(544); +const writeFileAtomic = __webpack_require__(548); +const sortKeys = __webpack_require__(555); +const makeDir = __webpack_require__(557); +const pify = __webpack_require__(559); +const detectIndent = __webpack_require__(560); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -52795,13 +52457,13 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 545 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { var fs = __webpack_require__(23) -var polyfills = __webpack_require__(546) -var legacy = __webpack_require__(547) -var clone = __webpack_require__(548) +var polyfills = __webpack_require__(545) +var legacy = __webpack_require__(546) +var clone = __webpack_require__(547) var queue = [] @@ -53080,7 +52742,7 @@ function retry () { /***/ }), -/* 546 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { var constants = __webpack_require__(25) @@ -53415,7 +53077,7 @@ function patch (fs) { /***/ }), -/* 547 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27).Stream @@ -53539,7 +53201,7 @@ function legacy (fs) { /***/ }), -/* 548 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53565,7 +53227,7 @@ function clone (obj) { /***/ }), -/* 549 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53575,8 +53237,8 @@ module.exports.sync = writeFileSync module.exports._getTmpname = getTmpname // for testing module.exports._cleanupOnExit = cleanupOnExit -var fs = __webpack_require__(550) -var MurmurHash3 = __webpack_require__(554) +var fs = __webpack_require__(549) +var MurmurHash3 = __webpack_require__(553) var onExit = __webpack_require__(377) var path = __webpack_require__(16) var activeFiles = {} @@ -53585,7 +53247,7 @@ var activeFiles = {} /* istanbul ignore next */ var threadId = (function getId () { try { - var workerThreads = __webpack_require__(555) + var workerThreads = __webpack_require__(554) /// if we are in main thread, this is set to `0` return workerThreads.threadId @@ -53810,12 +53472,12 @@ function writeFileSync (filename, data, options) { /***/ }), -/* 550 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { var fs = __webpack_require__(23) -var polyfills = __webpack_require__(551) -var legacy = __webpack_require__(553) +var polyfills = __webpack_require__(550) +var legacy = __webpack_require__(552) var queue = [] var util = __webpack_require__(29) @@ -53839,7 +53501,7 @@ if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { }) } -module.exports = patch(__webpack_require__(552)) +module.exports = patch(__webpack_require__(551)) if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) { module.exports = patch(fs) } @@ -54078,10 +53740,10 @@ function retry () { /***/ }), -/* 551 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(552) +var fs = __webpack_require__(551) var constants = __webpack_require__(25) var origCwd = process.cwd @@ -54414,7 +54076,7 @@ function chownErOk (er) { /***/ }), -/* 552 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54442,7 +54104,7 @@ function clone (obj) { /***/ }), -/* 553 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27).Stream @@ -54566,7 +54228,7 @@ function legacy (fs) { /***/ }), -/* 554 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -54708,18 +54370,18 @@ function legacy (fs) { /***/ }), -/* 555 */ +/* 554 */ /***/ (function(module, exports) { module.exports = require(undefined); /***/ }), -/* 556 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isPlainObj = __webpack_require__(557); +const isPlainObj = __webpack_require__(556); module.exports = (obj, opts) => { if (!isPlainObj(obj)) { @@ -54776,7 +54438,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 557 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54790,15 +54452,15 @@ module.exports = function (x) { /***/ }), -/* 558 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const pify = __webpack_require__(559); -const semver = __webpack_require__(521); +const pify = __webpack_require__(558); +const semver = __webpack_require__(520); const defaults = { mode: 0o777 & (~process.umask()), @@ -54936,7 +54598,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 559 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55011,7 +54673,7 @@ module.exports = (input, options) => { /***/ }), -/* 560 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55086,7 +54748,7 @@ module.exports = (input, options) => { /***/ }), -/* 561 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55215,7 +54877,7 @@ module.exports = str => { /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55224,7 +54886,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; }); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(563); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(562); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -55294,7 +54956,7 @@ async function yarnWorkspacesInfo(directory) { } /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55305,13 +54967,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(564); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(563); /* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(569); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(568); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -55373,12 +55035,12 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(565); +const chalk = __webpack_require__(564); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -55400,16 +55062,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(566); -const stdoutColor = __webpack_require__(567).stdout; +const ansiStyles = __webpack_require__(565); +const stdoutColor = __webpack_require__(566).stdout; -const template = __webpack_require__(568); +const template = __webpack_require__(567); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -55635,7 +55297,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55808,7 +55470,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55950,7 +55612,7 @@ module.exports = { /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56085,7 +55747,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -56093,12 +55755,12 @@ module.exports = (chalk, tmp) => { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(570); -module.exports.cli = __webpack_require__(574); +module.exports = __webpack_require__(569); +module.exports.cli = __webpack_require__(573); /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56113,9 +55775,9 @@ var stream = __webpack_require__(27); var util = __webpack_require__(29); var fs = __webpack_require__(23); -var through = __webpack_require__(571); -var duplexer = __webpack_require__(572); -var StringDecoder = __webpack_require__(573).StringDecoder; +var through = __webpack_require__(570); +var duplexer = __webpack_require__(571); +var StringDecoder = __webpack_require__(572).StringDecoder; module.exports = Logger; @@ -56304,7 +55966,7 @@ function lineMerger(host) { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -56418,7 +56080,7 @@ function through (write, end, opts) { /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -56511,13 +56173,13 @@ function duplex(writer, reader) { /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56528,11 +56190,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(575); +var minimist = __webpack_require__(574); var path = __webpack_require__(16); -var Logger = __webpack_require__(570); -var pkg = __webpack_require__(576); +var Logger = __webpack_require__(569); +var pkg = __webpack_require__(575); module.exports = cli; @@ -56586,7 +56248,7 @@ function usage($0, p) { /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -56828,29 +56490,29 @@ function isNumber (x) { /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham <ryan@strongloop.com>\",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; }); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(501); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(500); /* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(577); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(516); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(500); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(515); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(499); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -56942,7 +56604,7 @@ function packagesFromGlobPattern({ } /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57012,7 +56674,7 @@ function getProjectPaths({ } /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57020,13 +56682,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(580); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(579); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(581); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(580); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -57252,19 +56914,19 @@ async function getAllChecksums(kbn, log) { } /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(582); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(581); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); /* @@ -57308,7 +56970,7 @@ async function readYarnLock(kbn) { } /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -58867,7 +58529,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(580); +module.exports = __webpack_require__(579); /***/ }), /* 10 */, @@ -61191,7 +60853,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(583); +module.exports = __webpack_require__(582); /***/ }), /* 64 */, @@ -62129,7 +61791,7 @@ module.exports.win32 = win32; /* 79 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(479); +module.exports = __webpack_require__(478); /***/ }), /* 80 */, @@ -67586,13 +67248,13 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -67689,7 +67351,7 @@ class BootstrapCacheFile { } /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -67697,9 +67359,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(674); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(673); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -67780,11 +67442,10 @@ const CleanCommand = { const originalCwd = process.cwd(); try { - for (const _ref of toDelete) { - const { - pattern, - cwd - } = _ref; + for (const { + pattern, + cwd + } of toDelete) { process.chdir(cwd); const promise = del__WEBPACK_IMPORTED_MODULE_1___default()(pattern); ora__WEBPACK_IMPORTED_MODULE_2___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_3__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_3__["join"])(cwd, String(pattern)))); @@ -67799,21 +67460,21 @@ const CleanCommand = { }; /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); -const globby = __webpack_require__(587); -const isGlob = __webpack_require__(604); -const slash = __webpack_require__(665); +const globby = __webpack_require__(586); +const isGlob = __webpack_require__(603); +const slash = __webpack_require__(664); const gracefulFs = __webpack_require__(22); -const isPathCwd = __webpack_require__(667); -const isPathInside = __webpack_require__(668); -const rimraf = __webpack_require__(669); -const pMap = __webpack_require__(670); +const isPathCwd = __webpack_require__(666); +const isPathInside = __webpack_require__(667); +const rimraf = __webpack_require__(668); +const pMap = __webpack_require__(669); const rimrafP = promisify(rimraf); @@ -67927,19 +67588,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(588); -const merge2 = __webpack_require__(589); -const glob = __webpack_require__(590); -const fastGlob = __webpack_require__(595); -const dirGlob = __webpack_require__(661); -const gitignore = __webpack_require__(663); -const {FilterStream, UniqueStream} = __webpack_require__(666); +const arrayUnion = __webpack_require__(587); +const merge2 = __webpack_require__(588); +const glob = __webpack_require__(589); +const fastGlob = __webpack_require__(594); +const dirGlob = __webpack_require__(660); +const gitignore = __webpack_require__(662); +const {FilterStream, UniqueStream} = __webpack_require__(665); const DEFAULT_FILTER = () => false; @@ -68112,7 +67773,7 @@ module.exports.gitignore = gitignore; /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68124,7 +67785,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68238,7 +67899,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -68284,21 +67945,21 @@ function pauseStreams (streams, options) { module.exports = glob var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(591) +var inherits = __webpack_require__(590) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var globSync = __webpack_require__(593) -var common = __webpack_require__(594) +var isAbsolute = __webpack_require__(509) +var globSync = __webpack_require__(592) +var common = __webpack_require__(593) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(513) +var inflight = __webpack_require__(512) var util = __webpack_require__(29) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored @@ -69034,7 +68695,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -69044,12 +68705,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(592); + module.exports = __webpack_require__(591); } /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -69082,22 +68743,22 @@ if (typeof Object.create === 'function') { /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(590).Glob +var Glob = __webpack_require__(589).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var common = __webpack_require__(594) +var isAbsolute = __webpack_require__(509) +var common = __webpack_require__(593) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -69574,7 +69235,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -69592,8 +69253,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(16) -var minimatch = __webpack_require__(504) -var isAbsolute = __webpack_require__(510) +var minimatch = __webpack_require__(503) +var isAbsolute = __webpack_require__(509) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -69820,17 +69481,17 @@ function childrenIgnored (self, path) { /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(596); -const async_1 = __webpack_require__(624); -const stream_1 = __webpack_require__(657); -const sync_1 = __webpack_require__(658); -const settings_1 = __webpack_require__(660); -const utils = __webpack_require__(597); +const taskManager = __webpack_require__(595); +const async_1 = __webpack_require__(623); +const stream_1 = __webpack_require__(656); +const sync_1 = __webpack_require__(657); +const settings_1 = __webpack_require__(659); +const utils = __webpack_require__(596); function FastGlob(source, options) { try { assertPatternsInput(source); @@ -69888,13 +69549,13 @@ module.exports = FastGlob; /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -69962,28 +69623,28 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const array = __webpack_require__(598); +const array = __webpack_require__(597); exports.array = array; -const errno = __webpack_require__(599); +const errno = __webpack_require__(598); exports.errno = errno; -const fs = __webpack_require__(600); +const fs = __webpack_require__(599); exports.fs = fs; -const path = __webpack_require__(601); +const path = __webpack_require__(600); exports.path = path; -const pattern = __webpack_require__(602); +const pattern = __webpack_require__(601); exports.pattern = pattern; -const stream = __webpack_require__(623); +const stream = __webpack_require__(622); exports.stream = stream; /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69996,7 +69657,7 @@ exports.flatten = flatten; /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70009,7 +69670,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70034,7 +69695,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70055,16 +69716,16 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const globParent = __webpack_require__(603); -const isGlob = __webpack_require__(604); -const micromatch = __webpack_require__(606); +const globParent = __webpack_require__(602); +const isGlob = __webpack_require__(603); +const micromatch = __webpack_require__(605); const GLOBSTAR = '**'; function isStaticPattern(pattern) { return !isDynamicPattern(pattern); @@ -70153,13 +69814,13 @@ exports.matchAny = matchAny; /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(604); +var isGlob = __webpack_require__(603); var pathPosixDirname = __webpack_require__(16).posix.dirname; var isWin32 = __webpack_require__(11).platform() === 'win32'; @@ -70194,7 +69855,7 @@ module.exports = function globParent(str) { /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -70204,7 +69865,7 @@ module.exports = function globParent(str) { * Released under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); var chars = { '{': '}', '(': ')', '[': ']'}; var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; @@ -70248,7 +69909,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports) { /*! @@ -70274,16 +69935,16 @@ module.exports = function isExtglob(str) { /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const util = __webpack_require__(29); -const braces = __webpack_require__(607); -const picomatch = __webpack_require__(617); -const utils = __webpack_require__(620); +const braces = __webpack_require__(606); +const picomatch = __webpack_require__(616); +const utils = __webpack_require__(619); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -70748,16 +70409,16 @@ module.exports = micromatch; /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(608); -const compile = __webpack_require__(610); -const expand = __webpack_require__(614); -const parse = __webpack_require__(615); +const stringify = __webpack_require__(607); +const compile = __webpack_require__(609); +const expand = __webpack_require__(613); +const parse = __webpack_require__(614); /** * Expand the given pattern or create a regex-compatible string. @@ -70925,13 +70586,13 @@ module.exports = braces; /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(609); +const utils = __webpack_require__(608); module.exports = (ast, options = {}) => { let stringify = (node, parent = {}) => { @@ -70964,7 +70625,7 @@ module.exports = (ast, options = {}) => { /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71083,14 +70744,14 @@ exports.flatten = (...args) => { /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(611); -const utils = __webpack_require__(609); +const fill = __webpack_require__(610); +const utils = __webpack_require__(608); const compile = (ast, options = {}) => { let walk = (node, parent = {}) => { @@ -71147,7 +70808,7 @@ module.exports = compile; /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71161,7 +70822,7 @@ module.exports = compile; const util = __webpack_require__(29); -const toRegexRange = __webpack_require__(612); +const toRegexRange = __webpack_require__(611); const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); @@ -71403,7 +71064,7 @@ module.exports = fill; /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71416,7 +71077,7 @@ module.exports = fill; -const isNumber = __webpack_require__(613); +const isNumber = __webpack_require__(612); const toRegexRange = (min, max, options) => { if (isNumber(min) === false) { @@ -71698,7 +71359,7 @@ module.exports = toRegexRange; /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71723,15 +71384,15 @@ module.exports = function(num) { /***/ }), -/* 614 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(611); -const stringify = __webpack_require__(608); -const utils = __webpack_require__(609); +const fill = __webpack_require__(610); +const stringify = __webpack_require__(607); +const utils = __webpack_require__(608); const append = (queue = '', stash = '', enclose = false) => { let result = []; @@ -71843,13 +71504,13 @@ module.exports = expand; /***/ }), -/* 615 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(608); +const stringify = __webpack_require__(607); /** * Constants @@ -71871,7 +71532,7 @@ const { CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(616); +} = __webpack_require__(615); /** * parse @@ -72183,7 +71844,7 @@ module.exports = parse; /***/ }), -/* 616 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72247,26 +71908,26 @@ module.exports = { /***/ }), -/* 617 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(618); +module.exports = __webpack_require__(617); /***/ }), -/* 618 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const scan = __webpack_require__(619); -const parse = __webpack_require__(622); -const utils = __webpack_require__(620); +const scan = __webpack_require__(618); +const parse = __webpack_require__(621); +const utils = __webpack_require__(619); /** * Creates a matcher function from one or more glob patterns. The @@ -72569,7 +72230,7 @@ picomatch.toRegex = (source, options) => { * @return {Object} */ -picomatch.constants = __webpack_require__(621); +picomatch.constants = __webpack_require__(620); /** * Expose "picomatch" @@ -72579,13 +72240,13 @@ module.exports = picomatch; /***/ }), -/* 619 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(620); +const utils = __webpack_require__(619); const { CHAR_ASTERISK, /* * */ @@ -72603,7 +72264,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(621); +} = __webpack_require__(620); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -72805,7 +72466,7 @@ module.exports = (input, options) => { /***/ }), -/* 620 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72817,7 +72478,7 @@ const { REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL, REGEX_REMOVE_BACKSLASH -} = __webpack_require__(621); +} = __webpack_require__(620); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -72855,7 +72516,7 @@ exports.escapeLast = (input, char, lastIdx) => { /***/ }), -/* 621 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73041,14 +72702,14 @@ module.exports = { /***/ }), -/* 622 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(620); -const constants = __webpack_require__(621); +const utils = __webpack_require__(619); +const constants = __webpack_require__(620); /** * Constants @@ -74059,13 +73720,13 @@ module.exports = parse; /***/ }), -/* 623 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(589); +const merge2 = __webpack_require__(588); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -74077,14 +73738,14 @@ exports.merge = merge; /***/ }), -/* 624 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(625); -const provider_1 = __webpack_require__(652); +const stream_1 = __webpack_require__(624); +const provider_1 = __webpack_require__(651); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -74112,16 +73773,16 @@ exports.default = ProviderAsync; /***/ }), -/* 625 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const fsStat = __webpack_require__(626); -const fsWalk = __webpack_require__(631); -const reader_1 = __webpack_require__(651); +const fsStat = __webpack_require__(625); +const fsWalk = __webpack_require__(630); +const reader_1 = __webpack_require__(650); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -74174,15 +73835,15 @@ exports.default = ReaderStream; /***/ }), -/* 626 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(627); -const sync = __webpack_require__(628); -const settings_1 = __webpack_require__(629); +const async = __webpack_require__(626); +const sync = __webpack_require__(627); +const settings_1 = __webpack_require__(628); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74205,7 +73866,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 627 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74243,7 +73904,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 628 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74272,13 +73933,13 @@ exports.read = read; /***/ }), -/* 629 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(630); +const fs = __webpack_require__(629); class Settings { constructor(_options = {}) { this._options = _options; @@ -74295,7 +73956,7 @@ exports.default = Settings; /***/ }), -/* 630 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74318,16 +73979,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 631 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(632); -const stream_1 = __webpack_require__(647); -const sync_1 = __webpack_require__(648); -const settings_1 = __webpack_require__(650); +const async_1 = __webpack_require__(631); +const stream_1 = __webpack_require__(646); +const sync_1 = __webpack_require__(647); +const settings_1 = __webpack_require__(649); exports.Settings = settings_1.default; function walk(dir, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74357,13 +74018,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 632 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(633); +const async_1 = __webpack_require__(632); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -74394,17 +74055,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 633 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __webpack_require__(379); -const fsScandir = __webpack_require__(634); -const fastq = __webpack_require__(643); -const common = __webpack_require__(645); -const reader_1 = __webpack_require__(646); +const fsScandir = __webpack_require__(633); +const fastq = __webpack_require__(642); +const common = __webpack_require__(644); +const reader_1 = __webpack_require__(645); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -74494,15 +74155,15 @@ exports.default = AsyncReader; /***/ }), -/* 634 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(635); -const sync = __webpack_require__(640); -const settings_1 = __webpack_require__(641); +const async = __webpack_require__(634); +const sync = __webpack_require__(639); +const settings_1 = __webpack_require__(640); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74525,16 +74186,16 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const rpl = __webpack_require__(636); -const constants_1 = __webpack_require__(637); -const utils = __webpack_require__(638); +const fsStat = __webpack_require__(625); +const rpl = __webpack_require__(635); +const constants_1 = __webpack_require__(636); +const utils = __webpack_require__(637); function read(dir, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings, callback); @@ -74623,7 +74284,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports) { module.exports = runParallel @@ -74677,7 +74338,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 637 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74693,18 +74354,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSIO /***/ }), -/* 638 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(639); +const fs = __webpack_require__(638); exports.fs = fs; /***/ }), -/* 639 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74729,15 +74390,15 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 640 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const constants_1 = __webpack_require__(637); -const utils = __webpack_require__(638); +const fsStat = __webpack_require__(625); +const constants_1 = __webpack_require__(636); +const utils = __webpack_require__(637); function read(dir, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings); @@ -74788,15 +74449,15 @@ exports.readdir = readdir; /***/ }), -/* 641 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(626); -const fs = __webpack_require__(642); +const fsStat = __webpack_require__(625); +const fs = __webpack_require__(641); class Settings { constructor(_options = {}) { this._options = _options; @@ -74819,7 +74480,7 @@ exports.default = Settings; /***/ }), -/* 642 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74844,13 +74505,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 643 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(644) +var reusify = __webpack_require__(643) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -75024,7 +74685,7 @@ module.exports = fastqueue /***/ }), -/* 644 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75064,7 +74725,7 @@ module.exports = reusify /***/ }), -/* 645 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75095,13 +74756,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 646 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(645); +const common = __webpack_require__(644); class Reader { constructor(_root, _settings) { this._root = _root; @@ -75113,14 +74774,14 @@ exports.default = Reader; /***/ }), -/* 647 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const async_1 = __webpack_require__(633); +const async_1 = __webpack_require__(632); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -75150,13 +74811,13 @@ exports.default = StreamProvider; /***/ }), -/* 648 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(649); +const sync_1 = __webpack_require__(648); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -75171,15 +74832,15 @@ exports.default = SyncProvider; /***/ }), -/* 649 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(634); -const common = __webpack_require__(645); -const reader_1 = __webpack_require__(646); +const fsScandir = __webpack_require__(633); +const common = __webpack_require__(644); +const reader_1 = __webpack_require__(645); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -75237,14 +74898,14 @@ exports.default = SyncReader; /***/ }), -/* 650 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsScandir = __webpack_require__(634); +const fsScandir = __webpack_require__(633); class Settings { constructor(_options = {}) { this._options = _options; @@ -75270,15 +74931,15 @@ exports.default = Settings; /***/ }), -/* 651 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(626); -const utils = __webpack_require__(597); +const fsStat = __webpack_require__(625); +const utils = __webpack_require__(596); class Reader { constructor(_settings) { this._settings = _settings; @@ -75310,17 +74971,17 @@ exports.default = Reader; /***/ }), -/* 652 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const deep_1 = __webpack_require__(653); -const entry_1 = __webpack_require__(654); -const error_1 = __webpack_require__(655); -const entry_2 = __webpack_require__(656); +const deep_1 = __webpack_require__(652); +const entry_1 = __webpack_require__(653); +const error_1 = __webpack_require__(654); +const entry_2 = __webpack_require__(655); class Provider { constructor(_settings) { this._settings = _settings; @@ -75365,13 +75026,13 @@ exports.default = Provider; /***/ }), -/* 653 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -75431,13 +75092,13 @@ exports.default = DeepFilter; /***/ }), -/* 654 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -75492,13 +75153,13 @@ exports.default = EntryFilter; /***/ }), -/* 655 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -75514,13 +75175,13 @@ exports.default = ErrorFilter; /***/ }), -/* 656 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -75547,15 +75208,15 @@ exports.default = EntryTransformer; /***/ }), -/* 657 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const stream_2 = __webpack_require__(625); -const provider_1 = __webpack_require__(652); +const stream_2 = __webpack_require__(624); +const provider_1 = __webpack_require__(651); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -75583,14 +75244,14 @@ exports.default = ProviderStream; /***/ }), -/* 658 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(659); -const provider_1 = __webpack_require__(652); +const sync_1 = __webpack_require__(658); +const provider_1 = __webpack_require__(651); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -75613,15 +75274,15 @@ exports.default = ProviderSync; /***/ }), -/* 659 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const fsWalk = __webpack_require__(631); -const reader_1 = __webpack_require__(651); +const fsStat = __webpack_require__(625); +const fsWalk = __webpack_require__(630); +const reader_1 = __webpack_require__(650); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -75663,7 +75324,7 @@ exports.default = ReaderSync; /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75723,13 +75384,13 @@ exports.default = Settings; /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(662); +const pathType = __webpack_require__(661); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -75805,7 +75466,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75855,7 +75516,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75863,9 +75524,9 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(595); -const gitIgnore = __webpack_require__(664); -const slash = __webpack_require__(665); +const fastGlob = __webpack_require__(594); +const gitIgnore = __webpack_require__(663); +const slash = __webpack_require__(664); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -75979,7 +75640,7 @@ module.exports.sync = options => { /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -76570,7 +76231,7 @@ if ( /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76588,7 +76249,7 @@ module.exports = path => { /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76641,7 +76302,7 @@ module.exports = { /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76663,7 +76324,7 @@ module.exports = path_ => { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76691,7 +76352,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { const assert = __webpack_require__(30) @@ -76699,7 +76360,7 @@ const path = __webpack_require__(16) const fs = __webpack_require__(23) let glob = undefined try { - glob = __webpack_require__(590) + glob = __webpack_require__(589) } catch (_err) { // treat glob as optional. } @@ -77065,12 +76726,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(671); +const AggregateError = __webpack_require__(670); module.exports = async ( iterable, @@ -77153,13 +76814,13 @@ module.exports = async ( /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(672); -const cleanStack = __webpack_require__(673); +const indentString = __webpack_require__(671); +const cleanStack = __webpack_require__(672); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -77207,7 +76868,7 @@ module.exports = AggregateError; /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77249,7 +76910,7 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77296,15 +76957,15 @@ module.exports = (stack, options) => { /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(675); -const cliCursor = __webpack_require__(679); -const cliSpinners = __webpack_require__(683); -const logSymbols = __webpack_require__(564); +const chalk = __webpack_require__(674); +const cliCursor = __webpack_require__(678); +const cliSpinners = __webpack_require__(682); +const logSymbols = __webpack_require__(563); class Ora { constructor(options) { @@ -77451,16 +77112,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(676); -const stdoutColor = __webpack_require__(677).stdout; +const ansiStyles = __webpack_require__(675); +const stdoutColor = __webpack_require__(676).stdout; -const template = __webpack_require__(678); +const template = __webpack_require__(677); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -77686,7 +77347,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77859,7 +77520,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78001,7 +77662,7 @@ module.exports = { /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78136,12 +77797,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(680); +const restoreCursor = __webpack_require__(679); let hidden = false; @@ -78182,12 +77843,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(681); +const onetime = __webpack_require__(680); const signalExit = __webpack_require__(377); module.exports = onetime(() => { @@ -78198,12 +77859,12 @@ module.exports = onetime(() => { /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(682); +const mimicFn = __webpack_require__(681); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -78244,7 +77905,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78260,22 +77921,22 @@ module.exports = (to, from) => { /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(684); +module.exports = __webpack_require__(683); /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78284,8 +77945,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(498); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -78335,7 +77996,7 @@ const RunCommand = { }; /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78344,9 +78005,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(687); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(498); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(686); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -78430,7 +78091,7 @@ const WatchCommand = { }; /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78504,7 +78165,7 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78512,18 +78173,18 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(689); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(688); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(690); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(689); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(513); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(500); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(697); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(698); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(499); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(696); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(697); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -78608,7 +78269,7 @@ function toArray(value) { } /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78642,13 +78303,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(691); -const stripAnsi = __webpack_require__(695); +const stringWidth = __webpack_require__(690); +const stripAnsi = __webpack_require__(694); const ESCAPES = new Set([ '\u001B', @@ -78842,13 +78503,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(692); -const isFullwidthCodePoint = __webpack_require__(694); +const stripAnsi = __webpack_require__(691); +const isFullwidthCodePoint = __webpack_require__(693); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -78885,18 +78546,18 @@ module.exports = str => { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(693); +const ansiRegex = __webpack_require__(692); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78913,7 +78574,7 @@ module.exports = () => { /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78966,18 +78627,18 @@ module.exports = x => { /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(696); +const ansiRegex = __webpack_require__(695); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78994,7 +78655,7 @@ module.exports = () => { /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79147,7 +78808,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79155,15 +78816,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(699); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(698); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(703); +/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(702); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(577); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -79301,15 +78962,15 @@ class Kibana { } /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const minimatch = __webpack_require__(504); -const arrayUnion = __webpack_require__(700); -const arrayDiffer = __webpack_require__(701); -const arrify = __webpack_require__(702); +const minimatch = __webpack_require__(503); +const arrayUnion = __webpack_require__(699); +const arrayDiffer = __webpack_require__(700); +const arrify = __webpack_require__(701); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -79333,7 +78994,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79345,7 +79006,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79360,7 +79021,7 @@ module.exports = arrayDiffer; /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79390,7 +79051,7 @@ module.exports = arrify; /***/ }), -/* 703 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79418,15 +79079,15 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 704 */ +/* 703 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(928); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(922); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -79451,23 +79112,23 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 705 */ +/* 704 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(577); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(500); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(515); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(499); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -79599,7 +79260,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 706 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79607,13 +79268,13 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(379); const path = __webpack_require__(16); const os = __webpack_require__(11); -const pAll = __webpack_require__(707); -const arrify = __webpack_require__(709); -const globby = __webpack_require__(710); -const isGlob = __webpack_require__(604); -const cpFile = __webpack_require__(913); -const junk = __webpack_require__(925); -const CpyError = __webpack_require__(926); +const pAll = __webpack_require__(706); +const arrify = __webpack_require__(708); +const globby = __webpack_require__(709); +const isGlob = __webpack_require__(603); +const cpFile = __webpack_require__(907); +const junk = __webpack_require__(919); +const CpyError = __webpack_require__(920); const defaultOptions = { ignoreJunk: true @@ -79732,12 +79393,12 @@ module.exports = (source, destination, { /***/ }), -/* 707 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(708); +const pMap = __webpack_require__(707); module.exports = (iterable, options) => pMap(iterable, element => element(), options); // TODO: Remove this for the next major release @@ -79745,7 +79406,7 @@ module.exports.default = module.exports; /***/ }), -/* 708 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79824,7 +79485,7 @@ module.exports.default = pMap; /***/ }), -/* 709 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79854,17 +79515,17 @@ module.exports = arrify; /***/ }), -/* 710 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(711); -const glob = __webpack_require__(713); -const fastGlob = __webpack_require__(718); -const dirGlob = __webpack_require__(906); -const gitignore = __webpack_require__(909); +const arrayUnion = __webpack_require__(710); +const glob = __webpack_require__(712); +const fastGlob = __webpack_require__(717); +const dirGlob = __webpack_require__(900); +const gitignore = __webpack_require__(903); const DEFAULT_FILTER = () => false; @@ -80009,12 +79670,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 711 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(712); +var arrayUniq = __webpack_require__(711); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -80022,7 +79683,7 @@ module.exports = function () { /***/ }), -/* 712 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80091,7 +79752,7 @@ if ('Set' in global) { /***/ }), -/* 713 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -80137,21 +79798,21 @@ if ('Set' in global) { module.exports = glob var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(714) +var inherits = __webpack_require__(713) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var globSync = __webpack_require__(716) -var common = __webpack_require__(717) +var isAbsolute = __webpack_require__(509) +var globSync = __webpack_require__(715) +var common = __webpack_require__(716) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(513) +var inflight = __webpack_require__(512) var util = __webpack_require__(29) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored @@ -80887,7 +80548,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 714 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -80897,12 +80558,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(715); + module.exports = __webpack_require__(714); } /***/ }), -/* 715 */ +/* 714 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -80935,22 +80596,22 @@ if (typeof Object.create === 'function') { /***/ }), -/* 716 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync var fs = __webpack_require__(23) -var rp = __webpack_require__(502) -var minimatch = __webpack_require__(504) +var rp = __webpack_require__(501) +var minimatch = __webpack_require__(503) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(713).Glob +var Glob = __webpack_require__(712).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) -var isAbsolute = __webpack_require__(510) -var common = __webpack_require__(717) +var isAbsolute = __webpack_require__(509) +var common = __webpack_require__(716) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -81427,7 +81088,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 717 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -81445,8 +81106,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(16) -var minimatch = __webpack_require__(504) -var isAbsolute = __webpack_require__(510) +var minimatch = __webpack_require__(503) +var isAbsolute = __webpack_require__(509) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -81673,10 +81334,10 @@ function childrenIgnored (self, path) { /***/ }), -/* 718 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(719); +const pkg = __webpack_require__(718); module.exports = pkg.async; module.exports.default = pkg.async; @@ -81689,19 +81350,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 719 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(720); -var taskManager = __webpack_require__(721); -var reader_async_1 = __webpack_require__(877); -var reader_stream_1 = __webpack_require__(901); -var reader_sync_1 = __webpack_require__(902); -var arrayUtils = __webpack_require__(904); -var streamUtils = __webpack_require__(905); +var optionsManager = __webpack_require__(719); +var taskManager = __webpack_require__(720); +var reader_async_1 = __webpack_require__(871); +var reader_stream_1 = __webpack_require__(895); +var reader_sync_1 = __webpack_require__(896); +var arrayUtils = __webpack_require__(898); +var streamUtils = __webpack_require__(899); /** * Synchronous API. */ @@ -81767,7 +81428,7 @@ function isString(source) { /***/ }), -/* 720 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81805,13 +81466,13 @@ exports.prepare = prepare; /***/ }), -/* 721 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(722); +var patternUtils = __webpack_require__(721); /** * Generate tasks based on parent directory of each pattern. */ @@ -81902,16 +81563,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 722 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(723); -var isGlob = __webpack_require__(726); -var micromatch = __webpack_require__(727); +var globParent = __webpack_require__(722); +var isGlob = __webpack_require__(725); +var micromatch = __webpack_require__(726); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -82057,15 +81718,15 @@ exports.matchAny = matchAny; /***/ }), -/* 723 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(724); -var pathDirname = __webpack_require__(725); +var isglob = __webpack_require__(723); +var pathDirname = __webpack_require__(724); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -82088,7 +81749,7 @@ module.exports = function globParent(str) { /***/ }), -/* 724 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -82098,7 +81759,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -82119,7 +81780,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 725 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82269,7 +81930,7 @@ module.exports.win32 = win32; /***/ }), -/* 726 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -82279,7 +81940,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -82321,7 +81982,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 727 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82332,18 +81993,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(728); -var toRegex = __webpack_require__(830); -var extend = __webpack_require__(838); +var braces = __webpack_require__(727); +var toRegex = __webpack_require__(829); +var extend = __webpack_require__(837); /** * Local dependencies */ -var compilers = __webpack_require__(841); -var parsers = __webpack_require__(873); -var cache = __webpack_require__(874); -var utils = __webpack_require__(875); +var compilers = __webpack_require__(840); +var parsers = __webpack_require__(867); +var cache = __webpack_require__(868); +var utils = __webpack_require__(869); var MAX_LENGTH = 1024 * 64; /** @@ -83205,7 +82866,7 @@ module.exports = micromatch; /***/ }), -/* 728 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83215,18 +82876,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(729); -var unique = __webpack_require__(741); -var extend = __webpack_require__(738); +var toRegex = __webpack_require__(728); +var unique = __webpack_require__(740); +var extend = __webpack_require__(737); /** * Local dependencies */ -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var Braces = __webpack_require__(767); -var utils = __webpack_require__(743); +var compilers = __webpack_require__(741); +var parsers = __webpack_require__(756); +var Braces = __webpack_require__(766); +var utils = __webpack_require__(742); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -83530,15 +83191,15 @@ module.exports = braces; /***/ }), -/* 729 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(730); -var extend = __webpack_require__(738); -var not = __webpack_require__(740); +var define = __webpack_require__(729); +var extend = __webpack_require__(737); +var not = __webpack_require__(739); var MAX_LENGTH = 1024 * 64; /** @@ -83685,7 +83346,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 730 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83698,7 +83359,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(731); +var isDescriptor = __webpack_require__(730); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -83723,7 +83384,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 731 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83736,9 +83397,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(732); -var isAccessor = __webpack_require__(733); -var isData = __webpack_require__(736); +var typeOf = __webpack_require__(731); +var isAccessor = __webpack_require__(732); +var isData = __webpack_require__(735); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -83752,7 +83413,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 732 */ +/* 731 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -83905,7 +83566,7 @@ function isBuffer(val) { /***/ }), -/* 733 */ +/* 732 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83918,7 +83579,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(734); +var typeOf = __webpack_require__(733); // accessor descriptor properties var accessor = { @@ -83981,10 +83642,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 734 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -84103,7 +83764,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 735 */ +/* 734 */ /***/ (function(module, exports) { /*! @@ -84130,7 +83791,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 736 */ +/* 735 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84143,7 +83804,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(737); +var typeOf = __webpack_require__(736); // data descriptor properties var data = { @@ -84192,10 +83853,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 737 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -84314,13 +83975,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 738 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(739); +var isObject = __webpack_require__(738); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -84354,7 +84015,7 @@ function hasOwn(obj, key) { /***/ }), -/* 739 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84374,13 +84035,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 740 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(738); +var extend = __webpack_require__(737); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -84447,7 +84108,7 @@ module.exports = toRegex; /***/ }), -/* 741 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84497,13 +84158,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 742 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(743); +var utils = __webpack_require__(742); module.exports = function(braces, options) { braces.compiler @@ -84786,25 +84447,25 @@ function hasQueue(node) { /***/ }), -/* 743 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(744); +var splitString = __webpack_require__(743); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(738); -utils.flatten = __webpack_require__(750); -utils.isObject = __webpack_require__(748); -utils.fillRange = __webpack_require__(751); -utils.repeat = __webpack_require__(756); -utils.unique = __webpack_require__(741); +utils.extend = __webpack_require__(737); +utils.flatten = __webpack_require__(749); +utils.isObject = __webpack_require__(747); +utils.fillRange = __webpack_require__(750); +utils.repeat = __webpack_require__(755); +utils.unique = __webpack_require__(740); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -85136,7 +84797,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 744 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85149,7 +84810,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(745); +var extend = __webpack_require__(744); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -85314,14 +84975,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 745 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(746); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(745); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -85381,7 +85042,7 @@ function isEnum(obj, key) { /***/ }), -/* 746 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85394,7 +85055,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -85402,7 +85063,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 747 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85415,7 +85076,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); function isObjectObject(o) { return isObject(o) === true @@ -85446,7 +85107,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 748 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85465,7 +85126,7 @@ module.exports = function isObject(val) { /***/ }), -/* 749 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85512,7 +85173,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 750 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85541,7 +85202,7 @@ function flat(arr, res) { /***/ }), -/* 751 */ +/* 750 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85555,10 +85216,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(752); -var extend = __webpack_require__(738); -var repeat = __webpack_require__(754); -var toRegex = __webpack_require__(755); +var isNumber = __webpack_require__(751); +var extend = __webpack_require__(737); +var repeat = __webpack_require__(753); +var toRegex = __webpack_require__(754); /** * Return a range of numbers or letters. @@ -85756,7 +85417,7 @@ module.exports = fillRange; /***/ }), -/* 752 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85769,7 +85430,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); module.exports = function isNumber(num) { var type = typeOf(num); @@ -85785,10 +85446,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 753 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -85907,7 +85568,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 754 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85984,7 +85645,7 @@ function repeat(str, num) { /***/ }), -/* 755 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85997,8 +85658,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(754); -var isNumber = __webpack_require__(752); +var repeat = __webpack_require__(753); +var isNumber = __webpack_require__(751); var cache = {}; function toRegexRange(min, max, options) { @@ -86285,7 +85946,7 @@ module.exports = toRegexRange; /***/ }), -/* 756 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86310,14 +85971,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 757 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(758); -var utils = __webpack_require__(743); +var Node = __webpack_require__(757); +var utils = __webpack_require__(742); /** * Braces parsers @@ -86677,15 +86338,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 758 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(748); -var define = __webpack_require__(759); -var utils = __webpack_require__(766); +var isObject = __webpack_require__(747); +var define = __webpack_require__(758); +var utils = __webpack_require__(765); var ownNames; /** @@ -87176,7 +86837,7 @@ exports = module.exports = Node; /***/ }), -/* 759 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87189,7 +86850,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -87214,7 +86875,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 760 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87227,9 +86888,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(761); -var isAccessor = __webpack_require__(762); -var isData = __webpack_require__(764); +var typeOf = __webpack_require__(760); +var isAccessor = __webpack_require__(761); +var isData = __webpack_require__(763); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -87243,7 +86904,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 761 */ +/* 760 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87378,7 +87039,7 @@ function isBuffer(val) { /***/ }), -/* 762 */ +/* 761 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87391,7 +87052,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(763); +var typeOf = __webpack_require__(762); // accessor descriptor properties var accessor = { @@ -87454,7 +87115,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 763 */ +/* 762 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87589,7 +87250,7 @@ function isBuffer(val) { /***/ }), -/* 764 */ +/* 763 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87602,7 +87263,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(765); +var typeOf = __webpack_require__(764); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -87645,7 +87306,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 765 */ +/* 764 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87780,13 +87441,13 @@ function isBuffer(val) { /***/ }), -/* 766 */ +/* 765 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); var utils = module.exports; /** @@ -88806,17 +88467,17 @@ function assert(val, message) { /***/ }), -/* 767 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var utils = __webpack_require__(743); +var extend = __webpack_require__(737); +var Snapdragon = __webpack_require__(767); +var compilers = __webpack_require__(741); +var parsers = __webpack_require__(756); +var utils = __webpack_require__(742); /** * Customize Snapdragon parser and renderer @@ -88917,17 +88578,17 @@ module.exports = Braces; /***/ }), -/* 768 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(769); -var define = __webpack_require__(730); -var Compiler = __webpack_require__(798); -var Parser = __webpack_require__(827); -var utils = __webpack_require__(807); +var Base = __webpack_require__(768); +var define = __webpack_require__(729); +var Compiler = __webpack_require__(797); +var Parser = __webpack_require__(826); +var utils = __webpack_require__(806); var regexCache = {}; var cache = {}; @@ -89098,20 +88759,20 @@ module.exports.Parser = Parser; /***/ }), -/* 769 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(770); -var CacheBase = __webpack_require__(771); -var Emitter = __webpack_require__(772); -var isObject = __webpack_require__(748); -var merge = __webpack_require__(789); -var pascal = __webpack_require__(792); -var cu = __webpack_require__(793); +var define = __webpack_require__(769); +var CacheBase = __webpack_require__(770); +var Emitter = __webpack_require__(771); +var isObject = __webpack_require__(747); +var merge = __webpack_require__(788); +var pascal = __webpack_require__(791); +var cu = __webpack_require__(792); /** * Optionally define a custom `cache` namespace to use. @@ -89540,7 +89201,7 @@ module.exports.namespace = namespace; /***/ }), -/* 770 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89553,7 +89214,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -89578,21 +89239,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 771 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(748); -var Emitter = __webpack_require__(772); -var visit = __webpack_require__(773); -var toPath = __webpack_require__(776); -var union = __webpack_require__(777); -var del = __webpack_require__(781); -var get = __webpack_require__(779); -var has = __webpack_require__(786); -var set = __webpack_require__(780); +var isObject = __webpack_require__(747); +var Emitter = __webpack_require__(771); +var visit = __webpack_require__(772); +var toPath = __webpack_require__(775); +var union = __webpack_require__(776); +var del = __webpack_require__(780); +var get = __webpack_require__(778); +var has = __webpack_require__(785); +var set = __webpack_require__(779); /** * Create a `Cache` constructor that when instantiated will @@ -89846,7 +89507,7 @@ module.exports.namespace = namespace; /***/ }), -/* 772 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { @@ -90015,7 +89676,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 773 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90028,8 +89689,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(774); -var mapVisit = __webpack_require__(775); +var visit = __webpack_require__(773); +var mapVisit = __webpack_require__(774); module.exports = function(collection, method, val) { var result; @@ -90052,7 +89713,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 774 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90065,7 +89726,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -90092,14 +89753,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 775 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(774); +var visit = __webpack_require__(773); /** * Map `visit` over an array of objects. @@ -90136,7 +89797,7 @@ function isObject(val) { /***/ }), -/* 776 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90149,7 +89810,7 @@ function isObject(val) { -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -90176,16 +89837,16 @@ function filter(arr) { /***/ }), -/* 777 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(739); -var union = __webpack_require__(778); -var get = __webpack_require__(779); -var set = __webpack_require__(780); +var isObject = __webpack_require__(738); +var union = __webpack_require__(777); +var get = __webpack_require__(778); +var set = __webpack_require__(779); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -90213,7 +89874,7 @@ function arrayify(val) { /***/ }), -/* 778 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90249,7 +89910,7 @@ module.exports = function union(init) { /***/ }), -/* 779 */ +/* 778 */ /***/ (function(module, exports) { /*! @@ -90305,7 +89966,7 @@ function toString(val) { /***/ }), -/* 780 */ +/* 779 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90318,10 +89979,10 @@ function toString(val) { -var split = __webpack_require__(744); -var extend = __webpack_require__(738); -var isPlainObject = __webpack_require__(747); -var isObject = __webpack_require__(739); +var split = __webpack_require__(743); +var extend = __webpack_require__(737); +var isPlainObject = __webpack_require__(746); +var isObject = __webpack_require__(738); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -90367,7 +90028,7 @@ function isValidKey(key) { /***/ }), -/* 781 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90380,8 +90041,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(748); -var has = __webpack_require__(782); +var isObject = __webpack_require__(747); +var has = __webpack_require__(781); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -90406,7 +90067,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 782 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90419,9 +90080,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(783); -var hasValues = __webpack_require__(785); -var get = __webpack_require__(779); +var isObject = __webpack_require__(782); +var hasValues = __webpack_require__(784); +var get = __webpack_require__(778); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -90432,7 +90093,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 783 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90445,7 +90106,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(784); +var isArray = __webpack_require__(783); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -90453,7 +90114,7 @@ module.exports = function isObject(val) { /***/ }), -/* 784 */ +/* 783 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -90464,7 +90125,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 785 */ +/* 784 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90507,7 +90168,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 786 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90520,9 +90181,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(748); -var hasValues = __webpack_require__(787); -var get = __webpack_require__(779); +var isObject = __webpack_require__(747); +var hasValues = __webpack_require__(786); +var get = __webpack_require__(778); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -90530,7 +90191,7 @@ module.exports = function(val, prop) { /***/ }), -/* 787 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90543,8 +90204,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(788); -var isNumber = __webpack_require__(752); +var typeOf = __webpack_require__(787); +var isNumber = __webpack_require__(751); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -90597,10 +90258,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 788 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -90722,14 +90383,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 789 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(790); -var forIn = __webpack_require__(791); +var isExtendable = __webpack_require__(789); +var forIn = __webpack_require__(790); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -90793,7 +90454,7 @@ module.exports = mixinDeep; /***/ }), -/* 790 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90806,7 +90467,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -90814,7 +90475,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 791 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90837,7 +90498,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 792 */ +/* 791 */ /***/ (function(module, exports) { /*! @@ -90864,14 +90525,14 @@ module.exports = pascalcase; /***/ }), -/* 793 */ +/* 792 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(794); +var utils = __webpack_require__(793); /** * Expose class utils @@ -91236,7 +90897,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 794 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91250,10 +90911,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(778); -utils.define = __webpack_require__(730); -utils.isObj = __webpack_require__(748); -utils.staticExtend = __webpack_require__(795); +utils.union = __webpack_require__(777); +utils.define = __webpack_require__(729); +utils.isObj = __webpack_require__(747); +utils.staticExtend = __webpack_require__(794); /** @@ -91264,7 +90925,7 @@ module.exports = utils; /***/ }), -/* 795 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91277,8 +90938,8 @@ module.exports = utils; -var copy = __webpack_require__(796); -var define = __webpack_require__(730); +var copy = __webpack_require__(795); +var define = __webpack_require__(729); var util = __webpack_require__(29); /** @@ -91361,15 +91022,15 @@ module.exports = extend; /***/ }), -/* 796 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(753); -var copyDescriptor = __webpack_require__(797); -var define = __webpack_require__(730); +var typeOf = __webpack_require__(752); +var copyDescriptor = __webpack_require__(796); +var define = __webpack_require__(729); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -91542,7 +91203,7 @@ module.exports.has = has; /***/ }), -/* 797 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91630,16 +91291,16 @@ function isObject(val) { /***/ }), -/* 798 */ +/* 797 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(799); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:compiler'); -var utils = __webpack_require__(807); +var use = __webpack_require__(798); +var define = __webpack_require__(729); +var debug = __webpack_require__(800)('snapdragon:compiler'); +var utils = __webpack_require__(806); /** * Create a new `Compiler` with the given `options`. @@ -91793,7 +91454,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(826); + var sourcemaps = __webpack_require__(825); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -91814,7 +91475,7 @@ module.exports = Compiler; /***/ }), -/* 799 */ +/* 798 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91827,7 +91488,7 @@ module.exports = Compiler; -var utils = __webpack_require__(800); +var utils = __webpack_require__(799); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -91942,7 +91603,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 800 */ +/* 799 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91956,8 +91617,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(730); -utils.isObject = __webpack_require__(748); +utils.define = __webpack_require__(729); +utils.isObject = __webpack_require__(747); utils.isString = function(val) { @@ -91972,7 +91633,7 @@ module.exports = utils; /***/ }), -/* 801 */ +/* 800 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -91981,14 +91642,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(802); + module.exports = __webpack_require__(801); } else { - module.exports = __webpack_require__(805); + module.exports = __webpack_require__(804); } /***/ }), -/* 802 */ +/* 801 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -91997,7 +91658,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(803); +exports = module.exports = __webpack_require__(802); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -92179,7 +91840,7 @@ function localstorage() { /***/ }), -/* 803 */ +/* 802 */ /***/ (function(module, exports, __webpack_require__) { @@ -92195,7 +91856,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(804); +exports.humanize = __webpack_require__(803); /** * The currently active debug mode names, and names to skip. @@ -92387,7 +92048,7 @@ function coerce(val) { /***/ }), -/* 804 */ +/* 803 */ /***/ (function(module, exports) { /** @@ -92545,14 +92206,14 @@ function plural(ms, n, name) { /***/ }), -/* 805 */ +/* 804 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(479); +var tty = __webpack_require__(478); var util = __webpack_require__(29); /** @@ -92561,7 +92222,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(803); +exports = module.exports = __webpack_require__(802); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -92740,7 +92401,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(806); + var net = __webpack_require__(805); stream = new net.Socket({ fd: fd, readable: false, @@ -92799,13 +92460,13 @@ exports.enable(load()); /***/ }), -/* 806 */ +/* 805 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 807 */ +/* 806 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92815,9 +92476,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(738); -exports.SourceMap = __webpack_require__(808); -exports.sourceMapResolve = __webpack_require__(819); +exports.extend = __webpack_require__(737); +exports.SourceMap = __webpack_require__(807); +exports.sourceMapResolve = __webpack_require__(818); /** * Convert backslash in the given string to forward slashes @@ -92860,7 +92521,7 @@ exports.last = function(arr, n) { /***/ }), -/* 808 */ +/* 807 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -92868,13 +92529,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(815).SourceMapConsumer; -exports.SourceNode = __webpack_require__(818).SourceNode; +exports.SourceMapGenerator = __webpack_require__(808).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(814).SourceMapConsumer; +exports.SourceNode = __webpack_require__(817).SourceNode; /***/ }), -/* 809 */ +/* 808 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -92884,10 +92545,10 @@ exports.SourceNode = __webpack_require__(818).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(810); -var util = __webpack_require__(812); -var ArraySet = __webpack_require__(813).ArraySet; -var MappingList = __webpack_require__(814).MappingList; +var base64VLQ = __webpack_require__(809); +var util = __webpack_require__(811); +var ArraySet = __webpack_require__(812).ArraySet; +var MappingList = __webpack_require__(813).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -93296,7 +92957,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 810 */ +/* 809 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93336,7 +92997,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(811); +var base64 = __webpack_require__(810); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -93442,7 +93103,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 811 */ +/* 810 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93515,7 +93176,7 @@ exports.decode = function (charCode) { /***/ }), -/* 812 */ +/* 811 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93938,7 +93599,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 813 */ +/* 812 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93948,7 +93609,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); +var util = __webpack_require__(811); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -94065,7 +93726,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 814 */ +/* 813 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94075,7 +93736,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); +var util = __webpack_require__(811); /** * Determine whether mappingB is after mappingA with respect to generated @@ -94150,7 +93811,7 @@ exports.MappingList = MappingList; /***/ }), -/* 815 */ +/* 814 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94160,11 +93821,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); -var binarySearch = __webpack_require__(816); -var ArraySet = __webpack_require__(813).ArraySet; -var base64VLQ = __webpack_require__(810); -var quickSort = __webpack_require__(817).quickSort; +var util = __webpack_require__(811); +var binarySearch = __webpack_require__(815); +var ArraySet = __webpack_require__(812).ArraySet; +var base64VLQ = __webpack_require__(809); +var quickSort = __webpack_require__(816).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -95238,7 +94899,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 816 */ +/* 815 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95355,7 +95016,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 817 */ +/* 816 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95475,7 +95136,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 818 */ +/* 817 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95485,8 +95146,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -var util = __webpack_require__(812); +var SourceMapGenerator = __webpack_require__(808).SourceMapGenerator; +var util = __webpack_require__(811); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -95894,17 +95555,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 819 */ +/* 818 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(820) -var resolveUrl = __webpack_require__(821) -var decodeUriComponent = __webpack_require__(822) -var urix = __webpack_require__(824) -var atob = __webpack_require__(825) +var sourceMappingURL = __webpack_require__(819) +var resolveUrl = __webpack_require__(820) +var decodeUriComponent = __webpack_require__(821) +var urix = __webpack_require__(823) +var atob = __webpack_require__(824) @@ -96202,7 +95863,7 @@ module.exports = { /***/ }), -/* 820 */ +/* 819 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -96265,13 +95926,13 @@ void (function(root, factory) { /***/ }), -/* 821 */ +/* 820 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var url = __webpack_require__(453) +var url = __webpack_require__(452) function resolveUrl(/* ...urls */) { return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { @@ -96283,13 +95944,13 @@ module.exports = resolveUrl /***/ }), -/* 822 */ +/* 821 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(823) +var decodeUriComponent = __webpack_require__(822) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -96300,7 +95961,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 823 */ +/* 822 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96401,7 +96062,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 824 */ +/* 823 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -96424,7 +96085,7 @@ module.exports = urix /***/ }), -/* 825 */ +/* 824 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96438,7 +96099,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 826 */ +/* 825 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96446,8 +96107,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(730); -var utils = __webpack_require__(807); +var define = __webpack_require__(729); +var utils = __webpack_require__(806); /** * Expose `mixin()`. @@ -96590,19 +96251,19 @@ exports.comment = function(node) { /***/ }), -/* 827 */ +/* 826 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(799); +var use = __webpack_require__(798); var util = __webpack_require__(29); -var Cache = __webpack_require__(828); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:parser'); -var Position = __webpack_require__(829); -var utils = __webpack_require__(807); +var Cache = __webpack_require__(827); +var define = __webpack_require__(729); +var debug = __webpack_require__(800)('snapdragon:parser'); +var Position = __webpack_require__(828); +var utils = __webpack_require__(806); /** * Create a new `Parser` with the given `input` and `options`. @@ -97130,7 +96791,7 @@ module.exports = Parser; /***/ }), -/* 828 */ +/* 827 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97237,13 +96898,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 829 */ +/* 828 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(730); +var define = __webpack_require__(729); /** * Store position for a node @@ -97258,16 +96919,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 830 */ +/* 829 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(831); -var define = __webpack_require__(837); -var extend = __webpack_require__(838); -var not = __webpack_require__(840); +var safe = __webpack_require__(830); +var define = __webpack_require__(836); +var extend = __webpack_require__(837); +var not = __webpack_require__(839); var MAX_LENGTH = 1024 * 64; /** @@ -97420,10 +97081,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 831 */ +/* 830 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(832); +var parse = __webpack_require__(831); var types = parse.types; module.exports = function (re, opts) { @@ -97469,13 +97130,13 @@ function isRegExp (x) { /***/ }), -/* 832 */ +/* 831 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(833); -var types = __webpack_require__(834); -var sets = __webpack_require__(835); -var positions = __webpack_require__(836); +var util = __webpack_require__(832); +var types = __webpack_require__(833); +var sets = __webpack_require__(834); +var positions = __webpack_require__(835); module.exports = function(regexpStr) { @@ -97757,11 +97418,11 @@ module.exports.types = types; /***/ }), -/* 833 */ +/* 832 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); -var sets = __webpack_require__(835); +var types = __webpack_require__(833); +var sets = __webpack_require__(834); // All of these are private and only used by randexp. @@ -97874,7 +97535,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 834 */ +/* 833 */ /***/ (function(module, exports) { module.exports = { @@ -97890,10 +97551,10 @@ module.exports = { /***/ }), -/* 835 */ +/* 834 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); +var types = __webpack_require__(833); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -97978,10 +97639,10 @@ exports.anyChar = function() { /***/ }), -/* 836 */ +/* 835 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); +var types = __webpack_require__(833); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -98001,7 +97662,7 @@ exports.end = function() { /***/ }), -/* 837 */ +/* 836 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98014,8 +97675,8 @@ exports.end = function() { -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); +var isobject = __webpack_require__(747); +var isDescriptor = __webpack_require__(759); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -98046,14 +97707,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 838 */ +/* 837 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(839); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(838); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -98113,7 +97774,7 @@ function isEnum(obj, key) { /***/ }), -/* 839 */ +/* 838 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98126,7 +97787,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -98134,14 +97795,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 840 */ +/* 839 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(838); -var safe = __webpack_require__(831); +var extend = __webpack_require__(837); +var safe = __webpack_require__(830); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -98213,14 +97874,14 @@ module.exports = toRegex; /***/ }), -/* 841 */ +/* 840 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(842); -var extglob = __webpack_require__(857); +var nanomatch = __webpack_require__(841); +var extglob = __webpack_require__(856); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -98297,7 +97958,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 842 */ +/* 841 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98308,17 +97969,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(729); -var extend = __webpack_require__(843); +var toRegex = __webpack_require__(728); +var extend = __webpack_require__(842); /** * Local dependencies */ -var compilers = __webpack_require__(845); -var parsers = __webpack_require__(846); -var cache = __webpack_require__(849); -var utils = __webpack_require__(851); +var compilers = __webpack_require__(844); +var parsers = __webpack_require__(845); +var cache = __webpack_require__(848); +var utils = __webpack_require__(850); var MAX_LENGTH = 1024 * 64; /** @@ -99142,14 +98803,14 @@ module.exports = nanomatch; /***/ }), -/* 843 */ +/* 842 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(844); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(843); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -99209,7 +98870,7 @@ function isEnum(obj, key) { /***/ }), -/* 844 */ +/* 843 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99222,7 +98883,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -99230,7 +98891,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 845 */ +/* 844 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99576,15 +99237,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 846 */ +/* 845 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(729); -var isOdd = __webpack_require__(847); +var regexNot = __webpack_require__(739); +var toRegex = __webpack_require__(728); +var isOdd = __webpack_require__(846); /** * Characters to use in negation regex (we want to "not" match @@ -99970,7 +99631,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 847 */ +/* 846 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99983,7 +99644,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(848); +var isNumber = __webpack_require__(847); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -99997,7 +99658,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 848 */ +/* 847 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100025,14 +99686,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 849 */ +/* 848 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(850))(); +module.exports = new (__webpack_require__(849))(); /***/ }), -/* 850 */ +/* 849 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100045,7 +99706,7 @@ module.exports = new (__webpack_require__(850))(); -var MapCache = __webpack_require__(828); +var MapCache = __webpack_require__(827); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -100167,7 +99828,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 851 */ +/* 850 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100180,14 +99841,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(852)(); -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(853); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(843); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(856); -utils.unique = __webpack_require__(741); +var isWindows = __webpack_require__(851)(); +var Snapdragon = __webpack_require__(767); +utils.define = __webpack_require__(852); +utils.diff = __webpack_require__(853); +utils.extend = __webpack_require__(842); +utils.pick = __webpack_require__(854); +utils.typeOf = __webpack_require__(855); +utils.unique = __webpack_require__(740); /** * Returns true if the given value is effectively an empty string @@ -100553,7 +100214,7 @@ utils.unixify = function(options) { /***/ }), -/* 852 */ +/* 851 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -100581,7 +100242,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 853 */ +/* 852 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100594,8 +100255,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); +var isobject = __webpack_require__(747); +var isDescriptor = __webpack_require__(759); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -100626,7 +100287,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 854 */ +/* 853 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100680,7 +100341,7 @@ function diffArray(one, two) { /***/ }), -/* 855 */ +/* 854 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100693,7 +100354,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -100722,7 +100383,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 856 */ +/* 855 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -100857,7 +100518,7 @@ function isBuffer(val) { /***/ }), -/* 857 */ +/* 856 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100867,18 +100528,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(738); -var unique = __webpack_require__(741); -var toRegex = __webpack_require__(729); +var extend = __webpack_require__(737); +var unique = __webpack_require__(740); +var toRegex = __webpack_require__(728); /** * Local dependencies */ -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(869); -var Extglob = __webpack_require__(872); -var utils = __webpack_require__(871); +var compilers = __webpack_require__(857); +var parsers = __webpack_require__(863); +var Extglob = __webpack_require__(866); +var utils = __webpack_require__(865); var MAX_LENGTH = 1024 * 64; /** @@ -101195,13 +100856,13 @@ module.exports = extglob; /***/ }), -/* 858 */ +/* 857 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(859); +var brackets = __webpack_require__(858); /** * Extglob compilers @@ -101371,7 +101032,7 @@ module.exports = function(extglob) { /***/ }), -/* 859 */ +/* 858 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101381,17 +101042,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(860); -var parsers = __webpack_require__(862); +var compilers = __webpack_require__(859); +var parsers = __webpack_require__(861); /** * Module dependencies */ -var debug = __webpack_require__(864)('expand-brackets'); -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var toRegex = __webpack_require__(729); +var debug = __webpack_require__(800)('expand-brackets'); +var extend = __webpack_require__(737); +var Snapdragon = __webpack_require__(767); +var toRegex = __webpack_require__(728); /** * Parses the given POSIX character class `pattern` and returns a @@ -101589,13 +101250,13 @@ module.exports = brackets; /***/ }), -/* 860 */ +/* 859 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(861); +var posix = __webpack_require__(860); module.exports = function(brackets) { brackets.compiler @@ -101683,7 +101344,7 @@ module.exports = function(brackets) { /***/ }), -/* 861 */ +/* 860 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101712,14 +101373,14 @@ module.exports = { /***/ }), -/* 862 */ +/* 861 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(863); -var define = __webpack_require__(730); +var utils = __webpack_require__(862); +var define = __webpack_require__(729); /** * Text regex @@ -101938,14 +101599,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 863 */ +/* 862 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(729); -var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(728); +var regexNot = __webpack_require__(739); var cached; /** @@ -101979,842 +101640,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 864 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Detect Electron renderer process, which is node, but we should - * treat as a browser. - */ - -if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(865); -} else { - module.exports = __webpack_require__(868); -} - - -/***/ }), -/* 865 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(866); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - - -/***/ }), -/* 866 */ -/***/ (function(module, exports, __webpack_require__) { - - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = __webpack_require__(867); - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Previous log timestamp. - */ - -var prevTime; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - return debug; -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - - -/***/ }), -/* 867 */ -/***/ (function(module, exports) { - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; - -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ - -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; - } -} - -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; - } - return Math.ceil(ms / n) + ' ' + name + 's'; -} - - -/***/ }), -/* 868 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Module dependencies. - */ - -var tty = __webpack_require__(479); -var util = __webpack_require__(29); - -/** - * This is the Node.js implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = __webpack_require__(866); -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; - -/** - * Colors. - */ - -exports.colors = [6, 2, 3, 4, 5, 1]; - -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ - -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); - - // coerce string value into JS value - var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); - - obj[prop] = val; - return obj; -}, {}); - -/** - * The file descriptor to write the `debug()` calls to. - * Set the `DEBUG_FD` env variable to override with another value. i.e.: - * - * $ DEBUG_FD=3 node script.js 3>debug.log - */ - -var fd = parseInt(process.env.DEBUG_FD, 10) || 2; - -if (1 !== fd && 2 !== fd) { - util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() -} - -var stream = 1 === fd ? process.stdout : - 2 === fd ? process.stderr : - createWritableStdioStream(fd); - -/** - * Is stdout a TTY? Colored output is enabled when `true`. - */ - -function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(fd); -} - -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; - -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ - -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; - -/** - * Adds ANSI color escape codes if enabled. - * - * @api public - */ - -function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; - - if (useColors) { - var c = this.color; - var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; - - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); - } else { - args[0] = new Date().toUTCString() - + ' ' + name + ' ' + args[0]; - } -} - -/** - * Invokes `util.format()` with the specified arguments and writes to `stream`. - */ - -function log() { - return stream.write(util.format.apply(util, arguments) + '\n'); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - if (null == namespaces) { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; - } -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - return process.env.DEBUG; -} - -/** - * Copied from `node/src/node.js`. - * - * XXX: It's lame that node doesn't expose this API out-of-the-box. It also - * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. - */ - -function createWritableStdioStream (fd) { - var stream; - var tty_wrap = process.binding('tty_wrap'); - - // Note stream._type is used for test-module-load-list.js - - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - stream = new tty.WriteStream(fd); - stream._type = 'tty'; - - // Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - case 'FILE': - var fs = __webpack_require__(23); - stream = new fs.SyncWriteStream(fd, { autoClose: false }); - stream._type = 'fs'; - break; - - case 'PIPE': - case 'TCP': - var net = __webpack_require__(806); - stream = new net.Socket({ - fd: fd, - readable: false, - writable: true - }); - - // FIXME Should probably have an option in net.Socket to create a - // stream from an existing fd which is writable only. But for now - // we'll just add this hack and set the `readable` member to false. - // Test: ./node test/fixtures/echo.js < /etc/passwd - stream.readable = false; - stream.read = null; - stream._type = 'pipe'; - - // FIXME Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stream file type!'); - } - - // For supporting legacy API we put the FD here. - stream.fd = fd; - - stream._isStdio = true; - - return stream; -} - -/** - * Init logic for `debug` instances. - * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. - */ - -function init (debug) { - debug.inspectOpts = {}; - - var keys = Object.keys(exports.inspectOpts); - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; - } -} - -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ - -exports.enable(load()); - - -/***/ }), -/* 869 */ +/* 863 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(859); -var define = __webpack_require__(870); -var utils = __webpack_require__(871); +var brackets = __webpack_require__(858); +var define = __webpack_require__(864); +var utils = __webpack_require__(865); /** * Characters to use in text regex (we want to "not" match @@ -102969,7 +101803,7 @@ module.exports = parsers; /***/ }), -/* 870 */ +/* 864 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102982,7 +101816,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -103007,14 +101841,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 871 */ +/* 865 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(740); -var Cache = __webpack_require__(850); +var regex = __webpack_require__(739); +var Cache = __webpack_require__(849); /** * Utils @@ -103083,7 +101917,7 @@ utils.createRegex = function(str) { /***/ }), -/* 872 */ +/* 866 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103093,16 +101927,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(768); -var define = __webpack_require__(870); -var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(767); +var define = __webpack_require__(864); +var extend = __webpack_require__(737); /** * Local dependencies */ -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(869); +var compilers = __webpack_require__(857); +var parsers = __webpack_require__(863); /** * Customize Snapdragon parser and renderer @@ -103168,16 +102002,16 @@ module.exports = Extglob; /***/ }), -/* 873 */ +/* 867 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(857); -var nanomatch = __webpack_require__(842); -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(830); +var extglob = __webpack_require__(856); +var nanomatch = __webpack_require__(841); +var regexNot = __webpack_require__(739); +var toRegex = __webpack_require__(829); var not; /** @@ -103258,14 +102092,14 @@ function textRegex(pattern) { /***/ }), -/* 874 */ +/* 868 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(850))(); +module.exports = new (__webpack_require__(849))(); /***/ }), -/* 875 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103278,13 +102112,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(837); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(838); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(876); -utils.unique = __webpack_require__(741); +var Snapdragon = __webpack_require__(767); +utils.define = __webpack_require__(836); +utils.diff = __webpack_require__(853); +utils.extend = __webpack_require__(837); +utils.pick = __webpack_require__(854); +utils.typeOf = __webpack_require__(870); +utils.unique = __webpack_require__(740); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -103581,7 +102415,7 @@ utils.unixify = function(options) { /***/ }), -/* 876 */ +/* 870 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -103716,7 +102550,7 @@ function isBuffer(val) { /***/ }), -/* 877 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103735,9 +102569,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_stream_1 = __webpack_require__(895); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_stream_1 = __webpack_require__(889); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -103798,15 +102632,15 @@ exports.default = ReaderAsync; /***/ }), -/* 878 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(879); -const readdirAsync = __webpack_require__(887); -const readdirStream = __webpack_require__(890); +const readdirSync = __webpack_require__(873); +const readdirAsync = __webpack_require__(881); +const readdirStream = __webpack_require__(884); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -103890,7 +102724,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 879 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103898,11 +102732,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(880); +const DirectoryReader = __webpack_require__(874); let syncFacade = { - fs: __webpack_require__(885), - forEach: __webpack_require__(886), + fs: __webpack_require__(879), + forEach: __webpack_require__(880), sync: true }; @@ -103931,7 +102765,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 880 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103940,9 +102774,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(881); -const stat = __webpack_require__(883); -const call = __webpack_require__(884); +const normalizeOptions = __webpack_require__(875); +const stat = __webpack_require__(877); +const call = __webpack_require__(878); /** * Asynchronously reads the contents of a directory and streams the results @@ -104318,14 +103152,14 @@ module.exports = DirectoryReader; /***/ }), -/* 881 */ +/* 875 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(882); +const globToRegExp = __webpack_require__(876); module.exports = normalizeOptions; @@ -104502,7 +103336,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 882 */ +/* 876 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -104639,13 +103473,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 883 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(884); +const call = __webpack_require__(878); module.exports = stat; @@ -104720,7 +103554,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 884 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104781,14 +103615,14 @@ function callOnce (fn) { /***/ }), -/* 885 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(884); +const call = __webpack_require__(878); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -104852,7 +103686,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 886 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104881,7 +103715,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 887 */ +/* 881 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104889,12 +103723,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(888); -const DirectoryReader = __webpack_require__(880); +const maybe = __webpack_require__(882); +const DirectoryReader = __webpack_require__(874); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(889), + forEach: __webpack_require__(883), async: true }; @@ -104936,7 +103770,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 888 */ +/* 882 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104963,7 +103797,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 889 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104999,7 +103833,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 890 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105007,11 +103841,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(880); +const DirectoryReader = __webpack_require__(874); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(889), + forEach: __webpack_require__(883), async: true }; @@ -105031,16 +103865,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 891 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(892); -var entry_1 = __webpack_require__(894); -var pathUtil = __webpack_require__(893); +var deep_1 = __webpack_require__(886); +var entry_1 = __webpack_require__(888); +var pathUtil = __webpack_require__(887); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -105106,14 +103940,14 @@ exports.default = Reader; /***/ }), -/* 892 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(893); -var patternUtils = __webpack_require__(722); +var pathUtils = __webpack_require__(887); +var patternUtils = __webpack_require__(721); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -105196,7 +104030,7 @@ exports.default = DeepFilter; /***/ }), -/* 893 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105227,14 +104061,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 894 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(893); -var patternUtils = __webpack_require__(722); +var pathUtils = __webpack_require__(887); +var patternUtils = __webpack_require__(721); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -105319,7 +104153,7 @@ exports.default = EntryFilter; /***/ }), -/* 895 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105339,8 +104173,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(896); -var fs_1 = __webpack_require__(900); +var fsStat = __webpack_require__(890); +var fs_1 = __webpack_require__(894); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -105390,14 +104224,14 @@ exports.default = FileSystemStream; /***/ }), -/* 896 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(897); -const statProvider = __webpack_require__(899); +const optionsManager = __webpack_require__(891); +const statProvider = __webpack_require__(893); /** * Asynchronous API. */ @@ -105428,13 +104262,13 @@ exports.statSync = statSync; /***/ }), -/* 897 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(898); +const fsAdapter = __webpack_require__(892); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -105447,7 +104281,7 @@ exports.prepare = prepare; /***/ }), -/* 898 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105470,7 +104304,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 899 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105522,7 +104356,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 900 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105553,7 +104387,7 @@ exports.default = FileSystem; /***/ }), -/* 901 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105573,9 +104407,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_stream_1 = __webpack_require__(895); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_stream_1 = __webpack_require__(889); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -105643,7 +104477,7 @@ exports.default = ReaderStream; /***/ }), -/* 902 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105662,9 +104496,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(878); -var reader_1 = __webpack_require__(891); -var fs_sync_1 = __webpack_require__(903); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_sync_1 = __webpack_require__(897); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -105724,7 +104558,7 @@ exports.default = ReaderSync; /***/ }), -/* 903 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105743,8 +104577,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(896); -var fs_1 = __webpack_require__(900); +var fsStat = __webpack_require__(890); +var fs_1 = __webpack_require__(894); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -105790,7 +104624,7 @@ exports.default = FileSystemSync; /***/ }), -/* 904 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105806,13 +104640,13 @@ exports.flatten = flatten; /***/ }), -/* 905 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(589); +var merge2 = __webpack_require__(588); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -105827,13 +104661,13 @@ exports.merge = merge; /***/ }), -/* 906 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(907); +const pathType = __webpack_require__(901); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -105899,13 +104733,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 907 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(908); +const pify = __webpack_require__(902); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -105948,7 +104782,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 908 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106039,17 +104873,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 909 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(718); -const gitIgnore = __webpack_require__(910); -const pify = __webpack_require__(911); -const slash = __webpack_require__(912); +const fastGlob = __webpack_require__(717); +const gitIgnore = __webpack_require__(904); +const pify = __webpack_require__(905); +const slash = __webpack_require__(906); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -106147,7 +104981,7 @@ module.exports.sync = options => { /***/ }), -/* 910 */ +/* 904 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -106616,7 +105450,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 911 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106691,7 +105525,7 @@ module.exports = (input, options) => { /***/ }), -/* 912 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106709,17 +105543,17 @@ module.exports = input => { /***/ }), -/* 913 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(914); -const CpFileError = __webpack_require__(917); -const fs = __webpack_require__(921); -const ProgressEmitter = __webpack_require__(924); +const pEvent = __webpack_require__(908); +const CpFileError = __webpack_require__(911); +const fs = __webpack_require__(915); +const ProgressEmitter = __webpack_require__(918); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -106833,12 +105667,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 914 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(915); +const pTimeout = __webpack_require__(909); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -107129,12 +105963,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 915 */ +/* 909 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(916); +const pFinally = __webpack_require__(910); class TimeoutError extends Error { constructor(message) { @@ -107180,7 +106014,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 916 */ +/* 910 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107202,12 +106036,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 917 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(918); +const NestedError = __webpack_require__(912); class CpFileError extends NestedError { constructor(message, nested) { @@ -107221,10 +106055,10 @@ module.exports = CpFileError; /***/ }), -/* 918 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(919); +var inherits = __webpack_require__(913); var NestedError = function (message, nested) { this.nested = nested; @@ -107275,7 +106109,7 @@ module.exports = NestedError; /***/ }), -/* 919 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -107283,12 +106117,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(920); + module.exports = __webpack_require__(914); } /***/ }), -/* 920 */ +/* 914 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -107317,16 +106151,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 921 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(922); -const pEvent = __webpack_require__(914); -const CpFileError = __webpack_require__(917); +const makeDir = __webpack_require__(916); +const pEvent = __webpack_require__(908); +const CpFileError = __webpack_require__(911); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -107423,7 +106257,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 922 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107431,7 +106265,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(923); +const semver = __webpack_require__(917); const defaults = { mode: 0o777 & (~process.umask()), @@ -107580,7 +106414,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 923 */ +/* 917 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -109182,7 +108016,7 @@ function coerce (version, options) { /***/ }), -/* 924 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -109223,7 +108057,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 925 */ +/* 919 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -109269,12 +108103,12 @@ exports.default = module.exports; /***/ }), -/* 926 */ +/* 920 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(927); +const NestedError = __webpack_require__(921); class CpyError extends NestedError { constructor(message, nested) { @@ -109288,7 +108122,7 @@ module.exports = CpyError; /***/ }), -/* 927 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -109344,14 +108178,14 @@ module.exports = NestedError; /***/ }), -/* 928 */ +/* 922 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return prepareExternalProjectDependencies; }); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(516); -/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(515); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(515); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(514); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index a236db9eee18a..be56fad8aa0ce 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,11 +10,11 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { - "@babel/core": "^7.5.5", - "@babel/plugin-proposal-class-properties": "^7.5.5", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/preset-env": "^7.5.5", - "@babel/preset-typescript": "^7.7.4", + "@babel/core": "^7.9.0", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@babel/preset-typescript": "^7.9.0", "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", diff --git a/packages/kbn-spec-to-console/README.md b/packages/kbn-spec-to-console/README.md index 6729f03b3d4db..526ceef43e3cd 100644 --- a/packages/kbn-spec-to-console/README.md +++ b/packages/kbn-spec-to-console/README.md @@ -23,10 +23,10 @@ At the root of the Kibana repository, run the following commands: ```sh # OSS -yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/rest-api-spec/src/main/resources/rest-api-spec/api/*" -d "src/legacy/core_plugins/console/server/api_server/spec/generated" +yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/rest-api-spec/src/main/resources/rest-api-spec/api/*" -d "src/plugins/console/server/lib/spec_definitions/json" # X-pack -yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/x-pack/plugin/src/test/resources/rest-api-spec/api/*" -d "x-pack/legacy/plugins/console_extensions/spec/generated" +yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/x-pack/plugin/src/test/resources/rest-api-spec/api/*" -d "x-pack/plugins/console_extensions/server/lib/spec_definitions/json" ``` ### Information used in Console that is not available in the REST spec diff --git a/packages/kbn-spec-to-console/bin/spec_to_console.js b/packages/kbn-spec-to-console/bin/spec_to_console.js index 20e870963e4b4..20b42c67f3b89 100644 --- a/packages/kbn-spec-to-console/bin/spec_to_console.js +++ b/packages/kbn-spec-to-console/bin/spec_to_console.js @@ -21,6 +21,7 @@ const fs = require('fs'); const path = require('path'); const program = require('commander'); const glob = require('glob'); +const chalk = require('chalk'); const packageJSON = require('../package.json'); const convert = require('../lib/convert'); @@ -37,10 +38,26 @@ if (!program.glob) { } const files = glob.sync(program.glob); -console.log(files.length, files); +const totalFilesCount = files.length; +let convertedFilesCount = 0; + +console.log(chalk.bold(`Detected files (count: ${totalFilesCount}):`)); +console.log(); +console.log(files); +console.log(); + files.forEach(file => { const spec = JSON.parse(fs.readFileSync(file)); - const output = JSON.stringify(convert(spec), null, 2); + const convertedSpec = convert(spec); + if (!Object.keys(convertedSpec).length) { + console.log( + // prettier-ignore + `${chalk.yellow('Detected')} ${chalk.grey(file)} but no endpoints were converted; ${chalk.yellow('skipping')}...` + ); + return; + } + const output = JSON.stringify(convertedSpec, null, 2); + ++convertedFilesCount; if (program.directory) { const outputName = path.basename(file); const outputPath = path.resolve(program.directory, outputName); @@ -54,3 +71,9 @@ files.forEach(file => { console.log(output); } }); + +console.log(); +// prettier-ignore +console.log(`${chalk.grey('Converted')} ${chalk.bold(`${convertedFilesCount}/${totalFilesCount}`)} ${chalk.grey('files')}`); +console.log(`Check your ${chalk.bold('git status')}.`); +console.log(); diff --git a/packages/kbn-spec-to-console/lib/convert.js b/packages/kbn-spec-to-console/lib/convert.js index 5dbdd6e1c94e4..88e3693d702e5 100644 --- a/packages/kbn-spec-to-console/lib/convert.js +++ b/packages/kbn-spec-to-console/lib/convert.js @@ -36,6 +36,11 @@ module.exports = spec => { */ Object.keys(spec).forEach(api => { const source = spec[api]; + + if (source.url.paths.every(path => Boolean(path.deprecated))) { + return; + } + if (!source.url) { return result; } diff --git a/packages/kbn-spec-to-console/lib/convert/params.js b/packages/kbn-spec-to-console/lib/convert/params.js index 86ac1667282f0..0d1747ae4f685 100644 --- a/packages/kbn-spec-to-console/lib/convert/params.js +++ b/packages/kbn-spec-to-console/lib/convert/params.js @@ -47,6 +47,7 @@ module.exports = params => { case 'date': case 'string': case 'number': + case 'number|string': result[param] = defaultValue || ''; break; case 'list': diff --git a/packages/kbn-storybook/storybook_config/middleware.js b/packages/kbn-storybook/storybook_config/middleware.js index f517477b405bd..046758948b2cf 100644 --- a/packages/kbn-storybook/storybook_config/middleware.js +++ b/packages/kbn-storybook/storybook_config/middleware.js @@ -22,5 +22,5 @@ const path = require('path'); // Extend the Storybook Middleware to include a route to access Legacy UI assets module.exports = function(router) { - router.get('/ui', serve(path.resolve(__dirname, '../../../../src/legacy/ui/public/assets'))); + router.get('/ui', serve(path.resolve(__dirname, '../../../src/core/server/core_app/assets'))); }; diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index a01c4ebab8ad0..0ab0048619358 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -10,7 +10,7 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "^7.5.5", + "@babel/cli": "^7.8.4", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/parse-link-header": "^1.0.0", diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index cfbd1ee0fe64c..57cdc8ffd494f 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -58,3 +58,5 @@ export { export { runFailedTestsReporterCli } from './failed_tests_reporter'; export { makeJunitReportPath } from './junit_report_path'; + +export { CI_PARALLEL_PROCESS_PREFIX } from './ci_parallel_process_prefix'; diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 0402a83d3d274..bcebdf591d6f0 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -30,7 +30,7 @@ "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { - "@babel/core": "^7.5.5", + "@babel/core": "^7.9.0", "@elastic/eui": "0.0.55", "@kbn/babel-preset": "1.0.0", "autoprefixer": "^9.7.4", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 1e9ceb42433f0..c76e909d2adbc 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -9,7 +9,7 @@ "kbn:watch": "node scripts/build --watch" }, "devDependencies": { - "@elastic/charts": "^18.1.0", + "@elastic/charts": "^18.1.1", "abortcontroller-polyfill": "^1.4.0", "@elastic/eui": "21.0.1", "@kbn/babel-preset": "1.0.0", diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 8862b96e74401..44b6c39556afd 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -264,7 +264,7 @@ export class ClusterManager { fromRoot('src/legacy/server/sass/__tmp__'), fromRoot('x-pack/legacy/plugins/reporting/.chromium'), fromRoot('x-pack/legacy/plugins/siem/cypress'), - fromRoot('x-pack/legacy/plugins/apm/e2e/cypress'), + fromRoot('x-pack/legacy/plugins/apm/e2e'), fromRoot('x-pack/legacy/plugins/apm/scripts'), fromRoot('x-pack/legacy/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes, 'plugins/java_languageserver', diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 0d5d300ec3b79..5d7b467052029 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -43,6 +43,7 @@ - [Core services](#core-services-1) - [Plugin services](#plugin-services) - [UI Exports](#ui-exports) + - [Plugin Spec](#plugin-spec) - [How to](#how-to) - [Configure plugin](#configure-plugin) - [Handle plugin configuration deprecations](#handle-plugin-configuration-deprecations) @@ -88,7 +89,7 @@ src/plugins plugin.ts [5] ``` -**[1] `kibana.json`** is a [static manifest](../../docs/development/core/server/kibana-plugin-server.pluginmanifest.md) file that is used to identify the plugin and to determine what kind of code the platform should execute from the plugin: +**[1] `kibana.json`** is a [static manifest](../../docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) file that is used to identify the plugin and to determine what kind of code the platform should execute from the plugin: ```json { @@ -98,7 +99,7 @@ src/plugins "ui": true } ``` -More details about[manifest file format](/docs/development/core/server/kibana-plugin-server.pluginmanifest.md) +More details about[manifest file format](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) Note that `package.json` files are irrelevant to and ignored by the new platform. @@ -210,9 +211,9 @@ These are the contracts exposed by the core services for each lifecycle event: | lifecycle event | contract | | --------------- | --------------------------------------------------------------------------------------------------------------- | -| *contructor* | [PluginInitializerContext](../../docs/development/core/server/kibana-plugin-server.plugininitializercontext.md) | -| *setup* | [CoreSetup](../../docs/development/core/server/kibana-plugin-server.coresetup.md) | -| *start* | [CoreStart](../../docs/development/core/server/kibana-plugin-server.corestart.md) | +| *contructor* | [PluginInitializerContext](../../docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.md) | +| *setup* | [CoreSetup](../../docs/development/core/server/kibana-plugin-core-server.coresetup.md) | +| *start* | [CoreStart](../../docs/development/core/server/kibana-plugin-core-server.corestart.md) | | *stop* | | ### Integrating with other plugins @@ -1131,33 +1132,33 @@ import { npStart: { core } } from 'ui/new_platform'; | Legacy Platform | New Platform | Notes | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `chrome.addBasePath` | [`core.http.basePath.prepend`](/docs/development/core/public/kibana-plugin-public.httpservicebase.basepath.md) | | -| `chrome.navLinks.update` | [`core.appbase.updater`](/docs/development/core/public/kibana-plugin-public.appbase.updater_.md) | Use the `updater$` property when registering your application via `core.application.register` | -| `chrome.breadcrumbs.set` | [`core.chrome.setBreadcrumbs`](/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md) | | -| `chrome.getUiSettingsClient` | [`core.uiSettings`](/docs/development/core/public/kibana-plugin-public.uisettingsclient.md) | | -| `chrome.helpExtension.set` | [`core.chrome.setHelpExtension`](/docs/development/core/public/kibana-plugin-public.chromestart.sethelpextension.md) | | -| `chrome.setVisible` | [`core.chrome.setIsVisible`](/docs/development/core/public/kibana-plugin-public.chromestart.setisvisible.md) | | +| `chrome.addBasePath` | [`core.http.basePath.prepend`](/docs/development/core/public/kibana-plugin-core-public.httpsetup.basepath.md) | | +| `chrome.navLinks.update` | [`core.appbase.updater`](/docs/development/core/public/kibana-plugin-core-public.appbase.updater_.md) | Use the `updater$` property when registering your application via `core.application.register` | +| `chrome.breadcrumbs.set` | [`core.chrome.setBreadcrumbs`](/docs/development/core/public/kibana-plugin-core-public.chromestart.setbreadcrumbs.md) | | +| `chrome.getUiSettingsClient` | [`core.uiSettings`](/docs/development/core/public/kibana-plugin-core-public.uisettingsclient.md) | | +| `chrome.helpExtension.set` | [`core.chrome.setHelpExtension`](/docs/development/core/public/kibana-plugin-core-public.chromestart.sethelpextension.md) | | +| `chrome.setVisible` | [`core.chrome.setIsVisible`](/docs/development/core/public/kibana-plugin-core-public.chromestart.setisvisible.md) | | | `chrome.setRootTemplate` / `chrome.setRootController` | -- | Use application mounting via `core.application.register` (not available to legacy plugins at this time). | -| `import { recentlyAccessed } from 'ui/persisted_log'` | [`core.chrome.recentlyAccessed`](/docs/development/core/public/kibana-plugin-public.chromerecentlyaccessed.md) | | -| `ui/capabilities` | [`core.application.capabilities`](/docs/development/core/public/kibana-plugin-public.capabilities.md) | | -| `ui/documentation_links` | [`core.docLinks`](/docs/development/core/public/kibana-plugin-public.doclinksstart.md) | | -| `ui/kfetch` | [`core.http`](/docs/development/core/public/kibana-plugin-public.httpservicebase.md) | API is nearly identical | -| `ui/notify` | [`core.notifications`](/docs/development/core/public/kibana-plugin-public.notificationsstart.md) and [`core.overlays`](/docs/development/core/public/kibana-plugin-public.overlaystart.md) | Toast messages are in `notifications`, banners are in `overlays`. May be combined later. | +| `import { recentlyAccessed } from 'ui/persisted_log'` | [`core.chrome.recentlyAccessed`](/docs/development/core/public/kibana-plugin-core-public.chromerecentlyaccessed.md) | | +| `ui/capabilities` | [`core.application.capabilities`](/docs/development/core/public/kibana-plugin-core-public.capabilities.md) | | +| `ui/documentation_links` | [`core.docLinks`](/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md) | | +| `ui/kfetch` | [`core.http`](/docs/development/core/public/kibana-plugin-core-public.httpservicebase.md) | API is nearly identical | +| `ui/notify` | [`core.notifications`](/docs/development/core/public/kibana-plugin-core-public.notificationsstart.md) and [`core.overlays`](/docs/development/core/public/kibana-plugin-core-public.overlaystart.md) | Toast messages are in `notifications`, banners are in `overlays`. May be combined later. | | `ui/routes` | -- | There is no global routing mechanism. Each app [configures its own routing](/rfcs/text/0004_application_service_mounting.md#complete-example). | -| `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md) | Client API is the same | -| `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-public.chromedoctitle.md) | | -| `uiExports/injectedVars` / `chrome.getInjected` | [Configure plugin](#configure-plugin) and [`PluginConfigDescriptor.exposeToBrowser`](/docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.exposetobrowser.md) | Can only be used to expose configuration properties | +| `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-core-public.savedobjectsstart.md) | Client API is the same | +| `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-core-public.chromedoctitle.md) | | +| `uiExports/injectedVars` / `chrome.getInjected` | [Configure plugin](#configure-plugin) and [`PluginConfigDescriptor.exposeToBrowser`](/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.exposetobrowser.md) | Can only be used to expose configuration properties | -_See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-public.corestart.md)_ +_See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-core-public.corestart.md)_ ##### Plugins for shared application services -In client code, we have a series of plugins which house shared application services that are being built in the shape of the new platform, but for the time being, are only available in legacy. So if your plugin depends on any of the APIs below, you'll need build your plugin as a legacy plugin that shims the new platform. Once these API's have been moved to the new platform you can migrate your plugin and declare a dependency on the plugin that owns the API's you require. +In client code, we have a series of plugins which house shared application services which are not technically part of `core`, but are often used in Kibana plugins. -The contracts for these plugins are exposed for you to consume in your own plugin; we have created dedicated exports for the `setup` and `start` contracts in a file called `legacy`. By passing these contracts to your plugin's `setup` and `start` methods, you can mimic the functionality that will eventually be provided in the new platform. +This table maps some of the most commonly used legacy items to their new platform locations. ```ts -import { setup, start } from '../core_plugins/visualizations/public/legacy'; +import { npStart: { plugins } } from 'ui/new_platform'; ``` | Legacy Platform | New Platform | Notes | @@ -1192,26 +1193,26 @@ In server code, `core` can be accessed from either `server.newPlatform` or `kbnS | Legacy Platform | New Platform | Notes | | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | -| `server.config()` | [`initializerContext.config.create()`](/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md) | Must also define schema. See _[how to configure plugin](#configure-plugin)_ | -| `server.route` | [`core.http.createRouter`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md) | [Examples](./MIGRATION_EXAMPLES.md#route-registration) | -| `server.renderApp()` / `server.renderAppWithDefaultConfig()` | [`context.rendering.render()`](/docs/development/core/server/kibana-plugin-server.iscopedrenderingclient.render.md) | [Examples](./MIGRATION_EXAMPLES.md#render-html-content) | -| `request.getBasePath()` | [`core.http.basePath.get`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md) | | -| `server.plugins.elasticsearch.getCluster('data')` | [`context.core.elasticsearch.dataClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | | -| `server.plugins.elasticsearch.getCluster('admin')` | [`context.core.elasticsearch.adminClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | | -| `server.plugins.elasticsearch.createCluster(...)` | [`core.elasticsearch.legacy.createClient`](/docs/development/core/server/kibana-plugin-server.elasticsearchservicestart.legacy.md) | | -| `server.savedObjects.setScopedSavedObjectsClientFactory` | [`core.savedObjects.setClientFactoryProvider`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.setclientfactoryprovider.md) | | -| `server.savedObjects.addScopedSavedObjectsClientWrapperFactory` | [`core.savedObjects.addClientWrapper`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.addclientwrapper.md) | | -| `server.savedObjects.getSavedObjectsRepository` | [`core.savedObjects.createInternalRepository`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createinternalrepository.md) [`core.savedObjects.createScopedRepository`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.createscopedrepository.md) | | -| `server.savedObjects.getScopedSavedObjectsClient` | [`core.savedObjects.getScopedClient`](/docs/development/core/server/kibana-plugin-server.savedobjectsservicestart.getscopedclient.md) | | -| `request.getSavedObjectsClient` | [`context.core.savedObjects.client`](/docs/development/core/server/kibana-plugin-server.requesthandlercontext.core.md) | | -| `request.getUiSettingsService` | [`context.core.uiSettings.client`](/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md) | | -| `kibana.Plugin.deprecations` | [Handle plugin configuration deprecations](#handle-plugin-config-deprecations) and [`PluginConfigDescriptor.deprecations`](docs/development/core/server/kibana-plugin-server.pluginconfigdescriptor.md) | Deprecations from New Platform are not applied to legacy configuration | -| `kibana.Plugin.savedObjectSchemas` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | -| `kibana.Plugin.mappings` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | -| `kibana.Plugin.migrations` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | -| `kibana.Plugin.savedObjectsManagement` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | - -_See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-plugin-server.coresetup.md)_ +| `server.config()` | [`initializerContext.config.create()`](/docs/development/core/server/kibana-plugin-core-server.plugininitializercontext.config.md) | Must also define schema. See _[how to configure plugin](#configure-plugin)_ | +| `server.route` | [`core.http.createRouter`](/docs/development/core/server/kibana-plugin-core-server.httpservicesetup.createrouter.md) | [Examples](./MIGRATION_EXAMPLES.md#route-registration) | +| `server.renderApp()` / `server.renderAppWithDefaultConfig()` | [`context.rendering.render()`](/docs/development/core/server/kibana-plugin-core-server.iscopedrenderingclient.render.md) | [Examples](./MIGRATION_EXAMPLES.md#render-html-content) | +| `request.getBasePath()` | [`core.http.basePath.get`](/docs/development/core/server/kibana-plugin-core-server.httpservicesetup.basepath.md) | | +| `server.plugins.elasticsearch.getCluster('data')` | [`context.core.elasticsearch.dataClient`](/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md) | | +| `server.plugins.elasticsearch.getCluster('admin')` | [`context.core.elasticsearch.adminClient`](/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md) | | +| `server.plugins.elasticsearch.createCluster(...)` | [`core.elasticsearch.legacy.createClient`](/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md) | | +| `server.savedObjects.setScopedSavedObjectsClientFactory` | [`core.savedObjects.setClientFactoryProvider`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | | +| `server.savedObjects.addScopedSavedObjectsClientWrapperFactory` | [`core.savedObjects.addClientWrapper`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md) | | +| `server.savedObjects.getSavedObjectsRepository` | [`core.savedObjects.createInternalRepository`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md) [`core.savedObjects.createScopedRepository`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md) | | +| `server.savedObjects.getScopedSavedObjectsClient` | [`core.savedObjects.getScopedClient`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.getscopedclient.md) | | +| `request.getSavedObjectsClient` | [`context.core.savedObjects.client`](/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md) | | +| `request.getUiSettingsService` | [`context.core.uiSettings.client`](/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md) | | +| `kibana.Plugin.deprecations` | [Handle plugin configuration deprecations](#handle-plugin-config-deprecations) and [`PluginConfigDescriptor.deprecations`](docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md) | Deprecations from New Platform are not applied to legacy configuration | +| `kibana.Plugin.savedObjectSchemas` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | +| `kibana.Plugin.mappings` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | +| `kibana.Plugin.migrations` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | +| `kibana.Plugin.savedObjectsManagement` | [`core.savedObjects.registerType`](docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | [Examples](./MIGRATION_EXAMPLES.md#saved-objects-types) | + +_See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-plugin-core-server.coresetup.md)_ ##### Plugin services | Legacy Platform | New Platform | Notes | @@ -1228,9 +1229,9 @@ This table shows where these uiExports have moved to in the New Platform. In mos | Legacy Platform | New Platform | Notes | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `aliases` | | | -| `app` | [`core.application.register`](/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md) | | +| `app` | [`core.application.register`](/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md) | | | `canvas` | | Should be an API on the canvas plugin. | -| `chromeNavControls` | [`core.chrome.navControls.register{Left,Right}`](/docs/development/core/public/kibana-plugin-public.chromenavcontrols.md) | | +| `chromeNavControls` | [`core.chrome.navControls.register{Left,Right}`](/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md) | | | `contextMenuActions` | | Should be an API on the devTools plugin. | | `devTools` | | | | `docViews` | [`plugins.discover.docViews.addDocView`](./src/plugins/discover/public/doc_views) | Should be an API on the discover plugin. | @@ -1256,48 +1257,27 @@ This table shows where these uiExports have moved to in the New Platform. In mos | `shareContextMenuExtensions` | | | | `styleSheetPaths` | | | | `taskDefinitions` | | Should be an API on the taskManager plugin. | -| `uiCapabilities` | [`core.application.register`](/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md) | | -| `uiSettingDefaults` | [`core.uiSettings.register`](/docs/development/core/server/kibana-plugin-server.uisettingsservicesetup.md) | | +| `uiCapabilities` | [`core.application.register`](/docs/development/core/public/kibana-plugin-core-public.applicationsetup.register.md) | | +| `uiSettingDefaults` | [`core.uiSettings.register`](/docs/development/core/server/kibana-plugin-core-server.uisettingsservicesetup.md) | | | `validations` | | Part of SavedObjects, see [#33587](https://github.com/elastic/kibana/issues/33587) | | `visEditorTypes` | | | | `visTypeEnhancers` | | | | `visTypes` | `plugins.visualizations.types` | | | `visualize` | | | -Examples: - -- **uiSettingDefaults** - -Before: - -```js -uiExports: { - uiSettingDefaults: { - 'my-plugin:my-setting': { - name: 'just-work', - value: true, - description: 'make it work', - category: ['my-category'], - }, - } -} -``` - -After: - -```ts -// src/plugins/my-plugin/server/plugin.ts -setup(core: CoreSetup){ - core.uiSettings.register({ - 'my-plugin:my-setting': { - name: 'just-work', - value: true, - description: 'make it work', - category: ['my-category'], - }, - }) -} -``` +#### Plugin Spec +| Legacy Platform | New Platform | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `id` | [`manifest.id`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) | +| `require` | [`manifest.requiredPlugins`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) | +| `version` | [`manifest.version`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) | +| `kibanaVersion` | [`manifest.kibanaVersion`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) | +| `configPrefix` | [`manifest.configPath`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) | +| `config` | [export config](#configure-plugin) | +| `deprecations` | [export config](#handle-plugin-configuration-deprecations) | +| `uiExports` | `N/A`. Use platform & plugin public contracts | +| `publicDir` | `N/A`. Platform serves static assets from `/public/assets` folder under `/plugins/{id}/assets/{path*}` URL. | +| `preInit`, `init`, `postInit` | `N/A`. Use NP [lifecycle events](#services) | ## How to @@ -1444,7 +1424,7 @@ In the legacy platform, Kibana requires to bind elasticsearch related API with a ``` The new platform introduced [a handler interface](/rfcs/text/0003_handler_interface.md) on the server-side to perform that association internally. Core services, that require impersonation with an incoming request, are -exposed via `context` argument of [the request handler interface.](/docs/development/core/server/kibana-plugin-server.requesthandler.md) +exposed via `context` argument of [the request handler interface.](/docs/development/core/server/kibana-plugin-core-server.requesthandler.md) The above example looks in the new platform as ```js async function handler(context, req, res) { @@ -1452,13 +1432,13 @@ The above example looks in the new platform as } ``` -The [request handler context](/docs/development/core/server/kibana-plugin-server.requesthandlercontext.md) exposed the next scoped **core** services: +The [request handler context](/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md) exposed the next scoped **core** services: | Legacy Platform | New Platform | | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------| -| `request.getSavedObjectsClient` | [`context.savedObjects.client`](/docs/development/core/server/kibana-plugin-server.savedobjectsclient.md) | -| `server.plugins.elasticsearch.getCluster('admin')` | [`context.elasticsearch.adminClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | -| `server.plugins.elasticsearch.getCluster('data')` | [`context.elasticsearch.dataClient`](/docs/development/core/server/kibana-plugin-server.iscopedclusterclient.md) | -| `request.getUiSettingsService` | [`context.uiSettings.client`](/docs/development/core/server/kibana-plugin-server.iuisettingsclient.md) | +| `request.getSavedObjectsClient` | [`context.savedObjects.client`](/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.md) | +| `server.plugins.elasticsearch.getCluster('admin')` | [`context.elasticsearch.adminClient`](/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md) | +| `server.plugins.elasticsearch.getCluster('data')` | [`context.elasticsearch.dataClient`](/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md) | +| `request.getUiSettingsService` | [`context.uiSettings.client`](/docs/development/core/server/kibana-plugin-core-server.iuisettingsclient.md) | #### Declare a custom scoped service Plugins can extend the handler context with custom API that will be available to the plugin itself and all dependent plugins. diff --git a/src/core/MIGRATION_EXAMPLES.md b/src/core/MIGRATION_EXAMPLES.md index 29edef476d7c3..37d0b9297ed3c 100644 --- a/src/core/MIGRATION_EXAMPLES.md +++ b/src/core/MIGRATION_EXAMPLES.md @@ -20,6 +20,7 @@ APIs to their New Platform equivalents. - [Chromeless Applications](#chromeless-applications) - [Render HTML Content](#render-html-content) - [Saved Objects types](#saved-objects-types) + - [UiSettings](#uisettings) ## Configuration @@ -975,4 +976,37 @@ const migration: SavedObjectMigrationFn = (doc, { log }) => {...} The `registerType` API will throw if called after the service has started, and therefor cannot be used from legacy plugin code. Legacy plugins should use the legacy savedObjects service and the legacy way to register -saved object types until migrated. \ No newline at end of file +saved object types until migrated. + +## UiSettings +UiSettings defaults registration performed during `setup` phase via `core.uiSettings.register` API. + +```js +// Before: +uiExports: { + uiSettingDefaults: { + 'my-plugin:my-setting': { + name: 'just-work', + value: true, + description: 'make it work', + category: ['my-category'], + }, + } +} +``` + +```ts +// After: +// src/plugins/my-plugin/server/plugin.ts +setup(core: CoreSetup){ + core.uiSettings.register({ + 'my-plugin:my-setting': { + name: 'just-work', + value: true, + description: 'make it work', + category: ['my-category'], + schema: schema.boolean(), + }, + }) +} +``` \ No newline at end of file diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 4dec084fd8a83..66b34c3db7bad 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -92,6 +92,9 @@ export class Header extends Component<HeaderProps, State> { constructor(props: HeaderProps) { super(props); + let isLocked = false; + props.isLocked$.subscribe(initialIsLocked => (isLocked = initialIsLocked)); + this.state = { appTitle: 'Kibana', isVisible: true, @@ -101,7 +104,7 @@ export class Header extends Component<HeaderProps, State> { navControlsLeft: [], navControlsRight: [], currentAppId: '', - isLocked: false, + isLocked, }; } diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index c40ad74893ead..b12cd1fe09a91 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -24,6 +24,7 @@ import { MaybePromise } from '@kbn/utility-types'; export interface HttpSetup { /** * APIs for manipulating the basePath on URL segments. + * See {@link IBasePath} */ basePath: IBasePath; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index f72e115fd24ff..254cac3495599 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -177,13 +177,18 @@ export { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; /** * Core services exposed to the `Plugin` setup lifecycle * + * @typeParam TPluginsStart - the type of the consuming plugin's start dependencies. Should be the same + * as the consuming {@link Plugin}'s `TPluginsStart` type. Used by `getStartServices`. + * @typeParam TStart - the type of the consuming plugin's start contract. Should be the same as the + * consuming {@link Plugin}'s `TStart` type. Used by `getStartServices`. + * * @public * * @internalRemarks We document the properties with \@link tags to improve * navigation in the generated docs until there's a fix for * https://github.com/Microsoft/web-build-tools/issues/1237 */ -export interface CoreSetup<TPluginsStart extends object = object> { +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> { /** {@link ApplicationSetup} */ application: ApplicationSetup; /** @@ -209,7 +214,7 @@ export interface CoreSetup<TPluginsStart extends object = object> { getInjectedVar: (name: string, defaultValue?: any) => unknown; }; /** {@link StartServicesAccessor} */ - getStartServices: StartServicesAccessor<TPluginsStart>; + getStartServices: StartServicesAccessor<TPluginsStart, TStart>; } /** @@ -219,9 +224,10 @@ export interface CoreSetup<TPluginsStart extends object = object> { * * @public */ -export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise< - [CoreStart, TPluginsStart] ->; +export type StartServicesAccessor< + TPluginsStart extends object = object, + TStart = unknown +> = () => Promise<[CoreStart, TPluginsStart, TStart]>; /** * Core services exposed to the `Plugin` start lifecycle @@ -274,7 +280,7 @@ export interface CoreStart { * @public * @deprecated */ -export interface LegacyCoreSetup extends CoreSetup<any> { +export interface LegacyCoreSetup extends CoreSetup<any, any> { /** @deprecated */ injectedMetadata: InjectedMetadataSetup; } diff --git a/src/core/public/legacy/legacy_service.ts b/src/core/public/legacy/legacy_service.ts index 1b7e25f585566..39ca7bdf54b7c 100644 --- a/src/core/public/legacy/legacy_service.ts +++ b/src/core/public/legacy/legacy_service.ts @@ -57,7 +57,7 @@ export class LegacyPlatformService { public readonly legacyId = Symbol(); private bootstrapModule?: BootstrapModule; private targetDomElement?: HTMLElement; - private readonly startDependencies$ = new Subject<[LegacyCoreStart, object]>(); + private readonly startDependencies$ = new Subject<[LegacyCoreStart, object, {}]>(); private readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); constructor(private readonly params: LegacyPlatformParams) {} @@ -129,7 +129,7 @@ export class LegacyPlatformService { }, }; - this.startDependencies$.next([legacyCore, plugins]); + this.startDependencies$.next([legacyCore, plugins, {}]); // Inject parts of the new platform into parts of the legacy platform // so that legacy APIs/modules can mimic their new platform counterparts diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index c860e9de8334e..0c4930592b233 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -49,13 +49,22 @@ export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; export { scopedHistoryMock } from './application/scoped_history.mock'; -function createCoreSetupMock({ basePath = '' } = {}) { +function createCoreSetupMock({ + basePath = '', + pluginStartDeps = {}, + pluginStartContract, +}: { + basePath?: string; + pluginStartDeps?: object; + pluginStartContract?: any; +} = {}) { const mock = { application: applicationServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), - getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object]>, []>(() => - Promise.resolve([createCoreStartMock({ basePath }), {}]) + getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>( + () => + Promise.resolve([createCoreStartMock({ basePath }), pluginStartDeps, pluginStartContract]) ), http: httpServiceMock.createSetupContract({ basePath }), notifications: notificationServiceMock.createSetupContract(), diff --git a/src/core/public/overlays/flyout/flyout_service.tsx b/src/core/public/overlays/flyout/flyout_service.tsx index 444430175d4f2..b609b2ce1d741 100644 --- a/src/core/public/overlays/flyout/flyout_service.tsx +++ b/src/core/public/overlays/flyout/flyout_service.tsx @@ -91,7 +91,6 @@ export interface OverlayFlyoutStart { export interface OverlayFlyoutOpenOptions { className?: string; closeButtonAriaLabel?: string; - ownFocus?: boolean; 'data-test-subj'?: string; } diff --git a/src/core/public/plugins/plugin.test.ts b/src/core/public/plugins/plugin.test.ts index 111ee93dd699b..39330711f7980 100644 --- a/src/core/public/plugins/plugin.test.ts +++ b/src/core/public/plugins/plugin.test.ts @@ -109,6 +109,10 @@ describe('PluginWrapper', () => { test("`start` resolves `startDependencies` Promise after plugin's start", async () => { expect.assertions(2); + const pluginStartContract = { + someApi: () => 'foo', + }; + let startDependenciesResolved = false; mockPluginLoader.mockResolvedValueOnce(() => ({ setup: jest.fn(), @@ -116,6 +120,7 @@ describe('PluginWrapper', () => { // Add small delay to ensure startDependencies is not resolved until after the plugin instance's start resolves. await new Promise(resolve => setTimeout(resolve, 10)); expect(startDependenciesResolved).toBe(false); + return pluginStartContract; }, })); await plugin.load(addBasePath); @@ -127,7 +132,7 @@ describe('PluginWrapper', () => { // called. const startDependenciesCheck = plugin.startDependencies.then(res => { startDependenciesResolved = true; - expect(res).toEqual([context, deps]); + expect(res).toEqual([context, deps, pluginStartContract]); }); await plugin.start(context, deps); await startDependenciesCheck; diff --git a/src/core/public/plugins/plugin.ts b/src/core/public/plugins/plugin.ts index e880627e352c8..e51c45040c452 100644 --- a/src/core/public/plugins/plugin.ts +++ b/src/core/public/plugins/plugin.ts @@ -35,7 +35,7 @@ export interface Plugin< TPluginsSetup extends object = object, TPluginsStart extends object = object > { - setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; + setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>; stop?(): void; } @@ -72,7 +72,7 @@ export class PluginWrapper< private initializer?: PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>; private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>; - private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>(); + private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>(); public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); constructor( @@ -105,7 +105,7 @@ export class PluginWrapper< * @param plugins The dictionary where the key is the dependency name and the value * is the contract returned by the dependency's `setup` function. */ - public async setup(setupContext: CoreSetup<TPluginsStart>, plugins: TPluginsSetup) { + public async setup(setupContext: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup) { this.instance = await this.createPluginInstance(); return await this.instance.setup(setupContext, plugins); @@ -125,7 +125,7 @@ export class PluginWrapper< const startContract = await this.instance.start(startContext, plugins); - this.startDependencies$.next([startContext, plugins]); + this.startDependencies$.next([startContext, plugins, startContract]); return startContract; } diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index 8e1574d05baf8..e698af689036d 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -53,7 +53,7 @@ export interface PluginsServiceStart { */ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> { /** Plugin wrappers in topological order. */ - private readonly plugins = new Map<PluginName, PluginWrapper<unknown, Record<string, unknown>>>(); + private readonly plugins = new Map<PluginName, PluginWrapper<unknown, unknown>>(); private readonly pluginDependencies = new Map<PluginName, PluginName[]>(); private readonly satupPlugins: PluginName[] = []; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index eec12f2348176..9f7f649f1e2a5 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -371,7 +371,7 @@ export interface CoreContext { } // @public -export interface CoreSetup<TPluginsStart extends object = object> { +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> { // (undocumented) application: ApplicationSetup; // @deprecated (undocumented) @@ -379,7 +379,7 @@ export interface CoreSetup<TPluginsStart extends object = object> { // (undocumented) fatalErrors: FatalErrorsSetup; // (undocumented) - getStartServices: StartServicesAccessor<TPluginsStart>; + getStartServices: StartServicesAccessor<TPluginsStart, TStart>; // (undocumented) http: HttpSetup; // @deprecated @@ -807,7 +807,7 @@ export interface IUiSettingsClient { } // @public @deprecated -export interface LegacyCoreSetup extends CoreSetup<any> { +export interface LegacyCoreSetup extends CoreSetup<any, any> { // Warning: (ae-forgotten-export) The symbol "InjectedMetadataSetup" needs to be exported by the entry point index.d.ts // // @deprecated (undocumented) @@ -907,7 +907,7 @@ export interface PackageInfo { // @public export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> { // (undocumented) - setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; + setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>; // (undocumented) start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>; // (undocumented) @@ -1237,7 +1237,7 @@ export class SimpleSavedObject<T = unknown> { } // @public -export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>; +export type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>; // @public export type StringValidation = StringValidationRegex | StringValidationRegexString; diff --git a/src/legacy/ui/public/assets/favicons/android-chrome-192x192.png b/src/core/server/core_app/assets/favicons/android-chrome-192x192.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/android-chrome-192x192.png rename to src/core/server/core_app/assets/favicons/android-chrome-192x192.png diff --git a/src/legacy/ui/public/assets/favicons/android-chrome-256x256.png b/src/core/server/core_app/assets/favicons/android-chrome-256x256.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/android-chrome-256x256.png rename to src/core/server/core_app/assets/favicons/android-chrome-256x256.png diff --git a/src/legacy/ui/public/assets/favicons/android-chrome-512x512.png b/src/core/server/core_app/assets/favicons/android-chrome-512x512.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/android-chrome-512x512.png rename to src/core/server/core_app/assets/favicons/android-chrome-512x512.png diff --git a/src/legacy/ui/public/assets/favicons/apple-touch-icon.png b/src/core/server/core_app/assets/favicons/apple-touch-icon.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/apple-touch-icon.png rename to src/core/server/core_app/assets/favicons/apple-touch-icon.png diff --git a/src/legacy/ui/public/assets/favicons/browserconfig.xml b/src/core/server/core_app/assets/favicons/browserconfig.xml similarity index 100% rename from src/legacy/ui/public/assets/favicons/browserconfig.xml rename to src/core/server/core_app/assets/favicons/browserconfig.xml diff --git a/src/legacy/ui/public/assets/favicons/favicon-16x16.png b/src/core/server/core_app/assets/favicons/favicon-16x16.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/favicon-16x16.png rename to src/core/server/core_app/assets/favicons/favicon-16x16.png diff --git a/src/legacy/ui/public/assets/favicons/favicon-32x32.png b/src/core/server/core_app/assets/favicons/favicon-32x32.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/favicon-32x32.png rename to src/core/server/core_app/assets/favicons/favicon-32x32.png diff --git a/src/legacy/ui/public/assets/favicons/favicon.ico b/src/core/server/core_app/assets/favicons/favicon.ico similarity index 100% rename from src/legacy/ui/public/assets/favicons/favicon.ico rename to src/core/server/core_app/assets/favicons/favicon.ico diff --git a/src/legacy/ui/public/assets/favicons/manifest.json b/src/core/server/core_app/assets/favicons/manifest.json similarity index 100% rename from src/legacy/ui/public/assets/favicons/manifest.json rename to src/core/server/core_app/assets/favicons/manifest.json diff --git a/src/legacy/ui/public/assets/favicons/mstile-144x144.png b/src/core/server/core_app/assets/favicons/mstile-144x144.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/mstile-144x144.png rename to src/core/server/core_app/assets/favicons/mstile-144x144.png diff --git a/src/legacy/ui/public/assets/favicons/mstile-150x150.png b/src/core/server/core_app/assets/favicons/mstile-150x150.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/mstile-150x150.png rename to src/core/server/core_app/assets/favicons/mstile-150x150.png diff --git a/src/legacy/ui/public/assets/favicons/mstile-310x150.png b/src/core/server/core_app/assets/favicons/mstile-310x150.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/mstile-310x150.png rename to src/core/server/core_app/assets/favicons/mstile-310x150.png diff --git a/src/legacy/ui/public/assets/favicons/mstile-310x310.png b/src/core/server/core_app/assets/favicons/mstile-310x310.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/mstile-310x310.png rename to src/core/server/core_app/assets/favicons/mstile-310x310.png diff --git a/src/legacy/ui/public/assets/favicons/mstile-70x70.png b/src/core/server/core_app/assets/favicons/mstile-70x70.png similarity index 100% rename from src/legacy/ui/public/assets/favicons/mstile-70x70.png rename to src/core/server/core_app/assets/favicons/mstile-70x70.png diff --git a/src/legacy/ui/public/assets/favicons/safari-pinned-tab.svg b/src/core/server/core_app/assets/favicons/safari-pinned-tab.svg similarity index 100% rename from src/legacy/ui/public/assets/favicons/safari-pinned-tab.svg rename to src/core/server/core_app/assets/favicons/safari-pinned-tab.svg diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Black.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Black.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Black.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Black.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Black.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Black.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Black.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Black.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BlackItalic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Bold.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Bold.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Bold.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Bold.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Bold.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Bold.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Bold.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Bold.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-BoldItalic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBold.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraBoldItalic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLight-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ExtraLightItalic-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Italic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Italic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Italic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Italic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Italic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Italic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Italic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Italic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Light-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-LightItalic-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Medium.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Medium.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Medium.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Medium.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Medium.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Medium.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Medium.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Medium.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-MediumItalic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Regular.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Regular.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Regular.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Regular.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Regular.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Regular.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Regular.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Regular.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBold.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBold.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBold.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBold.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBold.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBold.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBold.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBold.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-SemiBoldItalic.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-Thin-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-ThinItalic-BETA.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-italic.var.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-italic.var.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-italic.var.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-italic.var.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-upright.var.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-upright.var.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI-upright.var.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI-upright.var.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI.var.woff2 b/src/core/server/core_app/assets/fonts/inter_ui/Inter-UI.var.woff2 similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/Inter-UI.var.woff2 rename to src/core/server/core_app/assets/fonts/inter_ui/Inter-UI.var.woff2 diff --git a/src/legacy/ui/public/assets/fonts/inter_ui/LICENSE.txt b/src/core/server/core_app/assets/fonts/inter_ui/LICENSE.txt similarity index 100% rename from src/legacy/ui/public/assets/fonts/inter_ui/LICENSE.txt rename to src/core/server/core_app/assets/fonts/inter_ui/LICENSE.txt diff --git a/src/legacy/ui/public/assets/fonts/readme.md b/src/core/server/core_app/assets/fonts/readme.md similarity index 100% rename from src/legacy/ui/public/assets/fonts/readme.md rename to src/core/server/core_app/assets/fonts/readme.md diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/LICENSE.txt b/src/core/server/core_app/assets/fonts/roboto_mono/LICENSE.txt similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/LICENSE.txt rename to src/core/server/core_app/assets/fonts/roboto_mono/LICENSE.txt diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Bold.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Bold.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Bold.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Bold.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-BoldItalic.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-BoldItalic.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-BoldItalic.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-BoldItalic.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Italic.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Italic.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Italic.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Italic.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Light.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Light.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Light.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Light.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-LightItalic.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-LightItalic.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-LightItalic.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-LightItalic.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Medium.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Medium.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Medium.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Medium.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-MediumItalic.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-MediumItalic.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-MediumItalic.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-MediumItalic.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Regular.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Regular.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Regular.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Regular.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Thin.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Thin.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-Thin.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-Thin.ttf diff --git a/src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-ThinItalic.ttf b/src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-ThinItalic.ttf similarity index 100% rename from src/legacy/ui/public/assets/fonts/roboto_mono/RobotoMono-ThinItalic.ttf rename to src/core/server/core_app/assets/fonts/roboto_mono/RobotoMono-ThinItalic.ttf diff --git a/src/legacy/ui/public/assets/images/bg_bottom_branded.svg b/src/core/server/core_app/assets/images/bg_bottom_branded.svg similarity index 100% rename from src/legacy/ui/public/assets/images/bg_bottom_branded.svg rename to src/core/server/core_app/assets/images/bg_bottom_branded.svg diff --git a/src/legacy/ui/public/assets/images/bg_bottom_branded_dark.svg b/src/core/server/core_app/assets/images/bg_bottom_branded_dark.svg similarity index 100% rename from src/legacy/ui/public/assets/images/bg_bottom_branded_dark.svg rename to src/core/server/core_app/assets/images/bg_bottom_branded_dark.svg diff --git a/src/legacy/ui/public/assets/images/bg_top_branded.svg b/src/core/server/core_app/assets/images/bg_top_branded.svg similarity index 100% rename from src/legacy/ui/public/assets/images/bg_top_branded.svg rename to src/core/server/core_app/assets/images/bg_top_branded.svg diff --git a/src/legacy/ui/public/assets/images/bg_top_branded_dark.svg b/src/core/server/core_app/assets/images/bg_top_branded_dark.svg similarity index 100% rename from src/legacy/ui/public/assets/images/bg_top_branded_dark.svg rename to src/core/server/core_app/assets/images/bg_top_branded_dark.svg diff --git a/src/legacy/ui/public/assets/images/kibana.svg b/src/core/server/core_app/assets/images/kibana.svg similarity index 100% rename from src/legacy/ui/public/assets/images/kibana.svg rename to src/core/server/core_app/assets/images/kibana.svg diff --git a/src/core/server/core_app/core_app.ts b/src/core/server/core_app/core_app.ts index 2f8c85f47a76e..5e1a3794632ee 100644 --- a/src/core/server/core_app/core_app.ts +++ b/src/core/server/core_app/core_app.ts @@ -16,6 +16,9 @@ * specific language governing permissions and limitations * under the License. */ +import Path from 'path'; +import { fromRoot } from '../../../core/server/utils'; + import { InternalCoreSetup } from '../internal_types'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; @@ -29,6 +32,7 @@ export class CoreApp { setup(coreSetup: InternalCoreSetup) { this.logger.debug('Setting up core app.'); this.registerDefaultRoutes(coreSetup); + this.registerStaticDirs(coreSetup); } private registerDefaultRoutes(coreSetup: InternalCoreSetup) { @@ -49,4 +53,12 @@ export class CoreApp { res.ok({ body: { version: '0.0.1' } }) ); } + private registerStaticDirs(coreSetup: InternalCoreSetup) { + coreSetup.http.registerStaticDir('/ui/{path*}', Path.resolve(__dirname, './assets')); + + coreSetup.http.registerStaticDir( + '/node_modules/@kbn/ui-framework/dist/{path*}', + fromRoot('node_modules/@kbn/ui-framework/dist') + ); + } } diff --git a/src/core/server/core_app/integration_tests/static_assets.test.ts b/src/core/server/core_app/integration_tests/static_assets.test.ts new file mode 100644 index 0000000000000..aad2510ef8c0e --- /dev/null +++ b/src/core/server/core_app/integration_tests/static_assets.test.ts @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import * as kbnTestServer from '../../../../test_utils/kbn_server'; +import { Root } from '../../root'; + +describe('Platform assets', function() { + let root: Root; + + beforeAll(async function() { + root = kbnTestServer.createRoot(); + + await root.setup(); + await root.start(); + }); + + afterAll(async function() { + await root.shutdown(); + }); + + it('exposes static assets', async () => { + await kbnTestServer.request.get(root, '/ui/favicons/favicon.ico').expect(200); + }); + + it('returns 404 if not found', async function() { + await kbnTestServer.request.get(root, '/ui/favicons/not-a-favicon.ico').expect(404); + }); + + it('does not expose folder content', async function() { + await kbnTestServer.request.get(root, '/ui/favicons/').expect(403); + }); + + it('does not allow file tree traversing', async function() { + await kbnTestServer.request.get(root, '/ui/../../../../../README.md').expect(404); + }); +}); diff --git a/src/core/server/http/base_path_proxy_server.ts b/src/core/server/http/base_path_proxy_server.ts index e418726465efa..acefbd00ae2be 100644 --- a/src/core/server/http/base_path_proxy_server.ts +++ b/src/core/server/http/base_path_proxy_server.ts @@ -23,6 +23,7 @@ import { Agent as HttpsAgent, ServerOptions as TlsOptions } from 'https'; import apm from 'elastic-apm-node'; import { ByteSizeValue } from '@kbn/config-schema'; import { Server, Request, ResponseToolkit } from 'hapi'; +import HapiProxy from 'h2o2'; import { sample } from 'lodash'; import BrowserslistUserAgent from 'browserslist-useragent'; import * as Rx from 'rxjs'; @@ -102,7 +103,7 @@ export class BasePathProxyServer { // Register hapi plugin that adds proxying functionality. It can be configured // through the route configuration object (see { handler: { proxy: ... } }). - await this.server.register({ plugin: require('h2o2') }); + await this.server.register([HapiProxy]); if (this.httpConfig.ssl.enabled) { const tlsOptions = serverOptions.tls as TlsOptions; @@ -166,7 +167,8 @@ export class BasePathProxyServer { host: this.server.info.host, passThrough: true, port: this.devConfig.basePathProxyTargetPort, - protocol: this.server.info.protocol, + // typings mismatch. h2o2 doesn't support "socket" + protocol: this.server.info.protocol as HapiProxy.ProxyHandlerOptions['protocol'], xforward: true, }, }, @@ -195,7 +197,7 @@ export class BasePathProxyServer { agent: this.httpsAgent, passThrough: true, xforward: true, - mapUri: (request: Request) => ({ + mapUri: async (request: Request) => ({ uri: Url.format({ hostname: request.server.info.host, port: this.devConfig.basePathProxyTargetPort, diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index f898ed0ea1a99..77d3d99fb48cb 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -17,6 +17,7 @@ * under the License. */ import { Server } from 'hapi'; +import HapiStaticFiles from 'inert'; import url from 'url'; import { Logger, LoggerFactory } from '../logging'; @@ -44,6 +45,7 @@ export interface HttpServerSetup { * @param router {@link IRouter} - a router with registered route handlers. */ registerRouter: (router: IRouter) => void; + registerStaticDir: (path: string, dirPath: string) => void; basePath: HttpServiceSetup['basePath']; csp: HttpServiceSetup['csp']; createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory']; @@ -97,10 +99,11 @@ export class HttpServer { this.registeredRouters.add(router); } - public setup(config: HttpConfig): HttpServerSetup { + public async setup(config: HttpConfig): Promise<HttpServerSetup> { const serverOptions = getServerOptions(config); const listenerOptions = getListenerOptions(config); this.server = createServer(serverOptions, listenerOptions); + await this.server.register([HapiStaticFiles]); this.config = config; const basePathService = new BasePath(config.basePath); @@ -109,6 +112,7 @@ export class HttpServer { return { registerRouter: this.registerRouter.bind(this), + registerStaticDir: this.registerStaticDir.bind(this), registerOnPreAuth: this.registerOnPreAuth.bind(this), registerOnPostAuth: this.registerOnPostAuth.bind(this), registerOnPreResponse: this.registerOnPreResponse.bind(this), @@ -339,4 +343,23 @@ export class HttpServer { return t.next({ headers: authResponseHeaders }); }); } + + private registerStaticDir(path: string, dirPath: string) { + if (this.server === undefined) { + throw new Error('Http server is not setup up yet'); + } + + this.server.route({ + path, + method: 'GET', + handler: { + directory: { + path: dirPath, + listing: false, + lookupCompressed: true, + }, + }, + options: { auth: false }, + }); + } } diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index 442bc93190d86..0788a8f2af7a1 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -72,6 +72,7 @@ const createSetupContractMock = () => { registerRouteHandlerContext: jest.fn(), registerOnPreResponse: jest.fn(), createRouter: jest.fn().mockImplementation(() => mockRouter.create({})), + registerStaticDir: jest.fn(), basePath: createBasePathMock(), csp: CspConfig.DEFAULT, auth: createAuthMock(), diff --git a/src/core/server/http/http_tools.test.ts b/src/core/server/http/http_tools.test.ts index c1322a5aa94db..bdaab4f2999ed 100644 --- a/src/core/server/http/http_tools.test.ts +++ b/src/core/server/http/http_tools.test.ts @@ -18,6 +18,8 @@ */ jest.mock('fs', () => ({ + // Hapi Inert patches native methods + ...jest.requireActual('fs'), readFileSync: jest.fn(), })); diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts index 6327844108055..4be7e59acb7b9 100644 --- a/src/core/server/http/types.ts +++ b/src/core/server/http/types.ts @@ -265,6 +265,7 @@ export interface InternalHttpServiceSetup auth: HttpServerSetup['auth']; server: HttpServerSetup['server']; createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter; + registerStaticDir: (path: string, dirPath: string) => void; getAuthHeaders: GetAuthHeaders; registerRouteHandlerContext: <T extends keyof RequestHandlerContext>( pluginOpaqueId: PluginOpaqueId, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 1b436bfd72622..56ce16a951aa2 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -333,9 +333,13 @@ export interface RequestHandlerContext { /** * Context passed to the plugins `setup` method. * + * @typeParam TPluginsStart - the type of the consuming plugin's start dependencies. Should be the same + * as the consuming {@link Plugin}'s `TPluginsStart` type. Used by `getStartServices`. + * @typeParam TStart - the type of the consuming plugin's start contract. Should be the same as the + * consuming {@link Plugin}'s `TStart` type. Used by `getStartServices`. * @public */ -export interface CoreSetup<TPluginsStart extends object = object> { +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> { /** {@link CapabilitiesSetup} */ capabilities: CapabilitiesSetup; /** {@link ContextSetup} */ @@ -353,7 +357,7 @@ export interface CoreSetup<TPluginsStart extends object = object> { /** {@link MetricsServiceSetup} */ metrics: MetricsServiceSetup; /** {@link StartServicesAccessor} */ - getStartServices: StartServicesAccessor<TPluginsStart>; + getStartServices: StartServicesAccessor<TPluginsStart, TStart>; } /** @@ -364,9 +368,10 @@ export interface CoreSetup<TPluginsStart extends object = object> { * * @public */ -export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise< - [CoreStart, TPluginsStart] ->; +export type StartServicesAccessor< + TPluginsStart extends object = object, + TStart = unknown +> = () => Promise<[CoreStart, TPluginsStart, TStart]>; /** * Context passed to the plugins `start` method. diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index 94e86c39289bc..c6860086e7784 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -87,10 +87,19 @@ beforeEach(() => { }, savedObjects: savedObjectsServiceMock.createInternalSetupContract(), plugins: { + initialized: true, contracts: new Map([['plugin-id', 'plugin-value']]), uiPlugins: { public: new Map([['plugin-id', {} as DiscoveredPlugin]]), - internal: new Map([['plugin-id', { publicTargetDir: 'path/to/target/public' }]]), + internal: new Map([ + [ + 'plugin-id', + { + publicTargetDir: 'path/to/target/public', + publicAssetsDir: '/plugins/name/assets/', + }, + ], + ]), browserConfigs: new Map(), }, }, diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index b19a991fdf0d1..bb5f6d5617aae 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -312,7 +312,7 @@ export class LegacyService implements CoreService { uuid: { getInstanceUuid: setupDeps.core.uuid.getInstanceUuid, }, - getStartServices: () => Promise.resolve([coreStart, startDeps.plugins]), + getStartServices: () => Promise.resolve([coreStart, startDeps.plugins, {}]), }; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -334,6 +334,9 @@ export class LegacyService implements CoreService { plugins: startDeps.plugins, }, __internals: { + http: { + registerStaticDir: setupDeps.core.http.registerStaticDir, + }, hapiServer: setupDeps.core.http.server, kibanaMigrator: startDeps.core.savedObjects.migrator, uiPlugins: setupDeps.core.plugins.uiPlugins, diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 2aa35dff563f0..31bf17da041af 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -96,7 +96,13 @@ function pluginInitializerContextMock<T>(config: T = {} as T) { type CoreSetupMockType = MockedKeys<CoreSetup> & jest.Mocked<Pick<CoreSetup, 'getStartServices'>>; -function createCoreSetupMock() { +function createCoreSetupMock({ + pluginStartDeps = {}, + pluginStartContract, +}: { + pluginStartDeps?: object; + pluginStartContract?: any; +} = {}) { const httpService = httpServiceMock.createSetupContract(); const httpMock: jest.Mocked<CoreSetup['http']> = { createCookieSessionStorageFactory: httpService.createCookieSessionStorageFactory, @@ -131,8 +137,8 @@ function createCoreSetupMock() { uuid: uuidServiceMock.createSetupContract(), metrics: metricsServiceMock.createSetupContract(), getStartServices: jest - .fn<Promise<[ReturnType<typeof createCoreStartMock>, object]>, []>() - .mockResolvedValue([createCoreStartMock(), {}]), + .fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>() + .mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]), }; return mock; diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.ts b/src/core/server/plugins/integration_tests/plugins_service.test.ts index d5531478f03c5..1521fc332bcdb 100644 --- a/src/core/server/plugins/integration_tests/plugins_service.test.ts +++ b/src/core/server/plugins/integration_tests/plugins_service.test.ts @@ -107,7 +107,7 @@ describe('PluginsService', () => { }); it("properly resolves `getStartServices` in plugin's lifecycle", async () => { - expect.assertions(5); + expect.assertions(6); const pluginPath = 'plugin-path'; @@ -125,20 +125,25 @@ describe('PluginsService', () => { let contextFromStart: any = null; let contextFromStartService: any = null; + const pluginStartContract = { + someApi: () => 'foo', + }; + const pluginInitializer = () => ({ setup: async (coreSetup, deps) => { - coreSetup.getStartServices().then(([core, plugins]) => { + coreSetup.getStartServices().then(([core, plugins, pluginStart]) => { startDependenciesResolved = true; - contextFromStartService = { core, plugins }; + contextFromStartService = { core, plugins, pluginStart }; }); }, start: async (core, plugins) => { contextFromStart = { core, plugins }; await new Promise(resolve => setTimeout(resolve, 10)); expect(startDependenciesResolved).toBe(false); + return pluginStartContract; }, - } as Plugin); + } as Plugin<void, typeof pluginStartContract, {}, {}>); jest.doMock( join(pluginPath, 'server'), @@ -163,5 +168,6 @@ describe('PluginsService', () => { expect(startDependenciesResolved).toBe(true); expect(contextFromStart!.core).toEqual(contextFromStartService!.core); expect(contextFromStart!.plugins).toEqual(contextFromStartService!.plugins); + expect(contextFromStartService!.pluginStart).toEqual(pluginStartContract); }); }); diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 6875302f88a9d..1e4d94dd00d0d 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -250,6 +250,9 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async }); const startContext = { any: 'thing' } as any; const pluginDeps = { someDep: 'value' }; + const pluginStartContract = { + someApi: () => 'foo', + }; let startDependenciesResolved = false; @@ -259,6 +262,7 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async // delay to ensure startDependencies is not resolved until after the plugin instance's start resolves. await new Promise(resolve => setTimeout(resolve, 10)); expect(startDependenciesResolved).toBe(false); + return pluginStartContract; }, }; mockPluginInitializer.mockReturnValue(mockPluginInstance); @@ -267,7 +271,7 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async const startDependenciesCheck = plugin.startDependencies.then(resolvedStartDeps => { startDependenciesResolved = true; - expect(resolvedStartDeps).toEqual([startContext, pluginDeps]); + expect(resolvedStartDeps).toEqual([startContext, pluginDeps, pluginStartContract]); }); await plugin.start(startContext, pluginDeps); diff --git a/src/core/server/plugins/plugin.ts b/src/core/server/plugins/plugin.ts index b372874264eb5..7c67ab7a48df1 100644 --- a/src/core/server/plugins/plugin.ts +++ b/src/core/server/plugins/plugin.ts @@ -61,7 +61,7 @@ export class PluginWrapper< private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>; - private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>(); + private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>(); public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise(); constructor( @@ -115,7 +115,7 @@ export class PluginWrapper< this.log.debug('Starting plugin'); const startContract = await this.instance.start(startContext, plugins); - this.startDependencies$.next([startContext, plugins]); + this.startDependencies$.next([startContext, plugins, startContract]); return startContract; } diff --git a/src/core/server/plugins/plugins_service.mock.ts b/src/core/server/plugins/plugins_service.mock.ts index 5a52ebccbd472..29e5b83b2e4c7 100644 --- a/src/core/server/plugins/plugins_service.mock.ts +++ b/src/core/server/plugins/plugins_service.mock.ts @@ -28,6 +28,7 @@ const createSetupContractMock = (): PluginsServiceSetup => ({ internal: new Map(), public: new Map(), }, + initialized: true, }); const createStartContractMock = () => ({ contracts: new Map() }); const createServiceMock = (): PluginsServiceMock => ({ diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index df618b2c0a706..14147ab9f2a8d 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -516,42 +516,63 @@ describe('PluginsService', () => { }); describe('#setup()', () => { - describe('uiPlugins.internal', () => { - it('includes disabled plugins', async () => { - mockDiscover.mockReturnValue({ - error$: from([]), - plugin$: from([ - createPlugin('plugin-1', { - path: 'path-1', - version: 'some-version', - configPath: 'plugin1', - }), - createPlugin('plugin-2', { - path: 'path-2', - version: 'some-version', - configPath: 'plugin2', - }), - ]), - }); + beforeEach(() => { + mockDiscover.mockReturnValue({ + error$: from([]), + plugin$: from([ + createPlugin('plugin-1', { + path: 'path-1', + version: 'some-version', + configPath: 'plugin1', + }), + createPlugin('plugin-2', { + path: 'path-2', + version: 'some-version', + configPath: 'plugin2', + }), + ]), + }); - mockPluginSystem.uiPlugins.mockReturnValue(new Map()); + mockPluginSystem.uiPlugins.mockReturnValue(new Map()); + }); + describe('uiPlugins.internal', () => { + it('includes disabled plugins', async () => { config$.next({ plugins: { initialize: true }, plugin1: { enabled: false } }); - await pluginsService.discover(); - const { uiPlugins } = await pluginsService.setup({} as any); + const { uiPlugins } = await pluginsService.setup(setupDeps); expect(uiPlugins.internal).toMatchInlineSnapshot(` Map { "plugin-1" => Object { + "publicAssetsDir": <absolute path>/path-1/public/assets, "publicTargetDir": <absolute path>/path-1/target/public, }, "plugin-2" => Object { + "publicAssetsDir": <absolute path>/path-2/public/assets, "publicTargetDir": <absolute path>/path-2/target/public, }, } `); }); }); + + describe('plugin initialization', () => { + it('does initialize if plugins.initialize is true', async () => { + config$.next({ plugins: { initialize: true } }); + await pluginsService.discover(); + const { initialized } = await pluginsService.setup(setupDeps); + expect(mockPluginSystem.setupPlugins).toHaveBeenCalled(); + expect(initialized).toBe(true); + }); + + it('does not initialize if plugins.initialize is false', async () => { + config$.next({ plugins: { initialize: false } }); + await pluginsService.discover(); + const { initialized } = await pluginsService.setup(setupDeps); + expect(mockPluginSystem.setupPlugins).not.toHaveBeenCalled(); + expect(initialized).toBe(false); + }); + }); }); describe('#stop()', () => { diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index 427cc19a8614f..a0ecee47c675f 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -33,8 +33,11 @@ import { InternalCoreSetup, InternalCoreStart } from '../internal_types'; import { IConfigService } from '../config'; import { pick } from '../../utils'; -/** @public */ +/** @internal */ export interface PluginsServiceSetup { + /** Indicates whether or not plugins were initialized. */ + initialized: boolean; + /** Setup contracts returned by plugins. */ contracts: Map<PluginName, unknown>; uiPlugins: { /** @@ -55,8 +58,9 @@ export interface PluginsServiceSetup { }; } -/** @public */ +/** @internal */ export interface PluginsServiceStart { + /** Start contracts returned by plugins. */ contracts: Map<PluginName, unknown>; } @@ -103,14 +107,17 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS const config = await this.config$.pipe(first()).toPromise(); let contracts = new Map<PluginName, unknown>(); - if (!config.initialize || this.coreContext.env.isDevClusterMaster) { - this.log.info('Plugin initialization disabled.'); - } else { + const initialize = config.initialize && !this.coreContext.env.isDevClusterMaster; + if (initialize) { contracts = await this.pluginsSystem.setupPlugins(deps); + this.registerPluginStaticDirs(deps); + } else { + this.log.info('Plugin initialization disabled.'); } const uiPlugins = this.pluginsSystem.uiPlugins(); return { + initialized: initialize, contracts, uiPlugins: { internal: this.uiPluginInternalInfo, @@ -217,6 +224,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS if (plugin.includesUiPlugin) { this.uiPluginInternalInfo.set(plugin.name, { publicTargetDir: Path.resolve(plugin.path, 'target/public'), + publicAssetsDir: Path.resolve(plugin.path, 'public/assets'), }); } @@ -256,4 +264,13 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS ) ); } + + private registerPluginStaticDirs(deps: PluginsServiceSetupDeps) { + for (const [pluginName, pluginInfo] of this.uiPluginInternalInfo) { + deps.http.registerStaticDir( + `/plugins/${pluginName}/assets/{path*}`, + pluginInfo.publicAssetsDir + ); + } + } } diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 100e3c2288dbf..4fa4e1780e596 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -194,6 +194,10 @@ export interface InternalPluginInfo { * served */ readonly publicTargetDir: string; + /** + * Path to the plugin assets directory. + */ + readonly publicAssetsDir: string; } /** diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 0af8ea7d0e830..b50e47b9eab73 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -21,8 +21,6 @@ export * from './service'; export { SavedObjectsSchema } from './schema'; -export { SavedObjectsManagement } from './management'; - export * from './import'; export { diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index 58b9abfbcdb3a..018117776dcc8 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -171,14 +171,12 @@ describe('SavedObjectsService', () => { return expect(KibanaMigratorMock.mock.calls[0][0].callCluster()).resolves.toMatch('success'); }); - it('skips KibanaMigrator migrations when --optimize=true', async () => { - const coreContext = createCoreContext({ - env: ({ cliArgs: { optimize: true }, packageInfo: { version: 'x.x.x' } } as unknown) as Env, - }); + it('skips KibanaMigrator migrations when pluginsInitialized=false', async () => { + const coreContext = createCoreContext({ skipMigration: false }); const soService = new SavedObjectsService(coreContext); await soService.setup(createSetupDeps()); - await soService.start({}); + await soService.start({ pluginsInitialized: false }); expect(migratorInstanceMock.runMigrations).not.toHaveBeenCalled(); }); diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 175eac3c1bd95..aa440c6454569 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -269,7 +269,9 @@ interface WrappedClientFactoryWrapper { /** @internal */ // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface SavedObjectsStartDeps {} +export interface SavedObjectsStartDeps { + pluginsInitialized?: boolean; +} export class SavedObjectsService implements CoreService<InternalSavedObjectsServiceSetup, InternalSavedObjectsServiceStart> { @@ -349,7 +351,7 @@ export class SavedObjectsService } public async start( - core: SavedObjectsStartDeps, + { pluginsInitialized = true }: SavedObjectsStartDeps, migrationsRetryDelay?: number ): Promise<InternalSavedObjectsServiceStart> { if (!this.setupDeps || !this.config) { @@ -376,9 +378,11 @@ export class SavedObjectsService * However, our build system optimize step and some tests depend on the * HTTP server running without an Elasticsearch server being available. * So, when the `migrations.skip` is true, we skip migrations altogether. + * + * We also cannot safely run migrations if plugins are not initialized since + * not plugin migrations won't be registered. */ - const cliArgs = this.coreContext.env.cliArgs; - const skipMigrations = cliArgs.optimize || this.config.migration.skip; + const skipMigrations = this.config.migration.skip || !pluginsInitialized; if (skipMigrations) { this.logger.warn( diff --git a/src/core/server/saved_objects/service/index.ts b/src/core/server/saved_objects/service/index.ts index 9f625b4732e26..f44824238aa21 100644 --- a/src/core/server/saved_objects/service/index.ts +++ b/src/core/server/saved_objects/service/index.ts @@ -36,6 +36,7 @@ export interface SavedObjectsLegacyService { getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; SavedObjectsClient: typeof SavedObjectsClient; types: string[]; + importAndExportableTypes: string[]; schema: SavedObjectsSchema; getSavedObjectsRepository(...rest: any[]): any; importExport: { diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 6d4181e5e1ab3..e4e2b8d7adbb7 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -622,7 +622,7 @@ export interface ContextSetup { export type CoreId = symbol; // @public -export interface CoreSetup<TPluginsStart extends object = object> { +export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> { // (undocumented) capabilities: CapabilitiesSetup; // (undocumented) @@ -630,7 +630,7 @@ export interface CoreSetup<TPluginsStart extends object = object> { // (undocumented) elasticsearch: ElasticsearchServiceSetup; // (undocumented) - getStartServices: StartServicesAccessor<TPluginsStart>; + getStartServices: StartServicesAccessor<TPluginsStart, TStart>; // (undocumented) http: HttpServiceSetup; // (undocumented) @@ -1426,10 +1426,10 @@ export type PluginName = string; // @public (undocumented) export type PluginOpaqueId = symbol; -// @public (undocumented) +// @internal (undocumented) export interface PluginsServiceSetup { - // (undocumented) contracts: Map<PluginName, unknown>; + initialized: boolean; // (undocumented) uiPlugins: { internal: Map<PluginName, InternalPluginInfo>; @@ -1438,9 +1438,8 @@ export interface PluginsServiceSetup { }; } -// @public (undocumented) +// @internal (undocumented) export interface PluginsServiceStart { - // (undocumented) contracts: Map<PluginName, unknown>; } @@ -2029,6 +2028,8 @@ export interface SavedObjectsLegacyService { // (undocumented) getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; // (undocumented) + importAndExportableTypes: string[]; + // (undocumented) importExport: { objectLimit: number; importSavedObjects(options: SavedObjectsImportOptions): Promise<SavedObjectsImportResponse>; @@ -2271,7 +2272,7 @@ export type SharedGlobalConfig = RecursiveReadonly_2<{ }>; // @public -export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>; +export type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>; // @public export type StringValidation = StringValidationRegex | StringValidationRegexString; @@ -2348,9 +2349,9 @@ export const validBodyOutput: readonly ["data", "stream"]; // src/core/server/legacy/types.ts:164:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts // src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts // src/core/server/legacy/types.ts:166:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/plugins_service.ts:44:5 - (ae-forgotten-export) The symbol "InternalPluginInfo" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:226:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:226:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:228:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/plugins_service.ts:47:5 - (ae-forgotten-export) The symbol "InternalPluginInfo" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/types.ts:232:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 09a1328f346d8..222be572b75e4 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -72,6 +72,7 @@ export class Server { private readonly metrics: MetricsService; private readonly coreApp: CoreApp; + private pluginsInitialized?: boolean; private coreStart?: InternalCoreStart; constructor( @@ -156,6 +157,7 @@ export class Server { }; const pluginsSetup = await this.plugins.setup(coreSetup); + this.pluginsInitialized = pluginsSetup.initialized; const renderingSetup = await this.rendering.setup({ http: httpSetup, @@ -176,7 +178,9 @@ export class Server { public async start() { this.log.debug('starting server'); - const savedObjectsStart = await this.savedObjects.start({}); + const savedObjectsStart = await this.savedObjects.start({ + pluginsInitialized: this.pluginsInitialized, + }); const capabilitiesStart = this.capabilities.start(); const uiSettingsStart = await this.uiSettings.start(); const elasticsearchStart = await this.elasticsearch.start(); diff --git a/src/dev/build/tasks/nodejs/__tests__/download.js b/src/dev/build/tasks/nodejs/__tests__/download.js index c76ff15b89289..81ed7a6195ae7 100644 --- a/src/dev/build/tasks/nodejs/__tests__/download.js +++ b/src/dev/build/tasks/nodejs/__tests__/download.js @@ -18,27 +18,39 @@ */ import { createServer } from 'http'; -import { resolve } from 'path'; -import { readFileSync } from 'fs'; +import { join } from 'path'; +import { tmpdir } from 'os'; +import { mkdirp, readFileSync } from 'fs-extra'; import del from 'del'; import sinon from 'sinon'; +import { CI_PARALLEL_PROCESS_PREFIX } from '@kbn/test'; import expect from '@kbn/expect'; import Wreck from '@hapi/wreck'; import { ToolingLog } from '@kbn/dev-utils'; import { download } from '../download'; -const TMP_DESTINATION = resolve(__dirname, '__tmp__'); -beforeEach(async () => { - await del(TMP_DESTINATION); -}); -after(async () => { - await del(TMP_DESTINATION); -}); +const getTempFolder = async () => { + const dir = join(tmpdir(), CI_PARALLEL_PROCESS_PREFIX, 'download-js-test-tmp-dir'); + console.log(dir); + await mkdirp(dir); + return dir; +}; describe('src/dev/build/tasks/nodejs/download', () => { const sandbox = sinon.createSandbox(); + let TMP_DESTINATION; + let TMP_DIR; + + beforeEach(async () => { + TMP_DIR = await getTempFolder(); + TMP_DESTINATION = join(TMP_DIR, '__tmp_download_js_test_file__'); + }); + + afterEach(async () => { + await del(TMP_DIR, { force: true }); + }); afterEach(() => sandbox.reset()); const onLogLine = sandbox.stub(); diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index ef114f51f3100..1b5110a61cbc4 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -41,7 +41,7 @@ export const IGNORE_FILE_GLOBS = [ '**/.*', '**/{webpackShims,__mocks__}/**/*', 'x-pack/docs/**/*', - 'src/legacy/ui/public/assets/fonts/**/*', + 'src/core/server/core_app/assets/fonts/**/*', 'packages/kbn-utility-types/test-d/**/*', '**/Jenkinsfile*', 'Dockerfile*', @@ -123,18 +123,18 @@ export const TEMPORARILY_IGNORED_PATHS = [ 'src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js', 'src/fixtures/config_upgrade_from_4.0.0_to_4.0.1-snapshot.json', 'src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_seriesMultiple.js', - 'src/legacy/ui/public/assets/favicons/android-chrome-192x192.png', - 'src/legacy/ui/public/assets/favicons/android-chrome-256x256.png', - 'src/legacy/ui/public/assets/favicons/android-chrome-512x512.png', - 'src/legacy/ui/public/assets/favicons/apple-touch-icon.png', - 'src/legacy/ui/public/assets/favicons/favicon-16x16.png', - 'src/legacy/ui/public/assets/favicons/favicon-32x32.png', - 'src/legacy/ui/public/assets/favicons/mstile-70x70.png', - 'src/legacy/ui/public/assets/favicons/mstile-144x144.png', - 'src/legacy/ui/public/assets/favicons/mstile-150x150.png', - 'src/legacy/ui/public/assets/favicons/mstile-310x150.png', - 'src/legacy/ui/public/assets/favicons/mstile-310x310.png', - 'src/legacy/ui/public/assets/favicons/safari-pinned-tab.svg', + 'src/core/server/core_app/assets/favicons/android-chrome-192x192.png', + 'src/core/server/core_app/assets/favicons/android-chrome-256x256.png', + 'src/core/server/core_app/assets/favicons/android-chrome-512x512.png', + 'src/core/server/core_app/assets/favicons/apple-touch-icon.png', + 'src/core/server/core_app/assets/favicons/favicon-16x16.png', + 'src/core/server/core_app/assets/favicons/favicon-32x32.png', + 'src/core/server/core_app/assets/favicons/mstile-70x70.png', + 'src/core/server/core_app/assets/favicons/mstile-144x144.png', + 'src/core/server/core_app/assets/favicons/mstile-150x150.png', + 'src/core/server/core_app/assets/favicons/mstile-310x150.png', + 'src/core/server/core_app/assets/favicons/mstile-310x310.png', + 'src/core/server/core_app/assets/favicons/safari-pinned-tab.svg', 'src/legacy/ui/public/styles/bootstrap/component-animations.less', 'src/legacy/ui/public/styles/bootstrap/input-groups.less', 'src/legacy/ui/public/styles/bootstrap/list-group.less', diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 370abc120d475..8ed64f004c9be 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -18,14 +18,12 @@ */ export const storybookAliases = { - advanced_ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js', apm: 'x-pack/legacy/plugins/apm/scripts/storybook.js', canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js', codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts', - dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/scripts/storybook.js', drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js', embeddable: 'src/plugins/embeddable/scripts/storybook.js', infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js', siem: 'x-pack/legacy/plugins/siem/scripts/storybook.js', - ui_actions: 'src/plugins/ui_actions/scripts/storybook.js', + ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js', }; diff --git a/src/legacy/core_plugins/input_control_vis/index.ts b/src/legacy/core_plugins/input_control_vis/index.ts index d67472ac4b95f..0529aa24dffd7 100644 --- a/src/legacy/core_plugins/input_control_vis/index.ts +++ b/src/legacy/core_plugins/input_control_vis/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const inputControlVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'input_control_vis', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter'], + require: ['kibana', 'elasticsearch', 'interpreter'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx b/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx index d7a62e07b26f3..db2af742c70bc 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/controls_tab.test.tsx @@ -23,7 +23,7 @@ import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; import { getDepsMock, getIndexPatternMock } from '../../test_utils'; import { ControlsTab, ControlsTabUiProps } from './controls_tab'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../plugins/visualizations/public'; const indexPatternsMock = { get: getIndexPatternMock, diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.tsx b/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.tsx index 8c77f1b7c4b4f..639e3d2f68c75 100644 --- a/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/options_tab.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../plugins/visualizations/public'; import { OptionsTab, OptionsTabProps } from './options_tab'; describe('OptionsTab', () => { diff --git a/src/legacy/core_plugins/input_control_vis/public/legacy.ts b/src/legacy/core_plugins/input_control_vis/public/legacy.ts index 438cdffdb323a..67299068819e8 100644 --- a/src/legacy/core_plugins/input_control_vis/public/legacy.ts +++ b/src/legacy/core_plugins/input_control_vis/public/legacy.ts @@ -26,21 +26,17 @@ import { InputControlVisPluginSetupDependencies, InputControlVisPluginStartDependencies, } from './plugin'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../visualizations/public/np_ready/public/legacy'; const setupPlugins: Readonly<InputControlVisPluginSetupDependencies> = { expressions: npSetup.plugins.expressions, data: npSetup.plugins.data, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, }; const startPlugins: Readonly<InputControlVisPluginStartDependencies> = { expressions: npStart.plugins.expressions, data: npStart.plugins.data, - visualizations: visualizationsStart, + visualizations: npStart.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/input_control_vis/public/plugin.ts b/src/legacy/core_plugins/input_control_vis/public/plugin.ts index e85ccd94f9e6a..b743468065430 100644 --- a/src/legacy/core_plugins/input_control_vis/public/plugin.ts +++ b/src/legacy/core_plugins/input_control_vis/public/plugin.ts @@ -20,11 +20,14 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'kibana/p import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public'; +import { + VisualizationsSetup, + VisualizationsStart, +} from '../../../../plugins/visualizations/public'; import { createInputControlVisFn } from './input_control_fn'; import { createInputControlVisTypeDefinition } from './input_control_vis_type'; -type InputControlVisCoreSetup = CoreSetup<InputControlVisPluginStartDependencies>; +type InputControlVisCoreSetup = CoreSetup<InputControlVisPluginStartDependencies, void>; export interface InputControlVisDependencies { core: InputControlVisCoreSetup; @@ -46,7 +49,7 @@ export interface InputControlVisPluginStartDependencies { } /** @internal */ -export class InputControlVisPlugin implements Plugin<Promise<void>, void> { +export class InputControlVisPlugin implements Plugin<void, void> { constructor(public initializerContext: PluginInitializerContext) {} public async setup( diff --git a/src/legacy/core_plugins/input_control_vis/public/vis_controller.tsx b/src/legacy/core_plugins/input_control_vis/public/vis_controller.tsx index c0ab235c1b9d1..c4a7d286850e3 100644 --- a/src/legacy/core_plugins/input_control_vis/public/vis_controller.tsx +++ b/src/legacy/core_plugins/input_control_vis/public/vis_controller.tsx @@ -31,7 +31,7 @@ import { RangeControl } from './control/range_control_factory'; import { ListControl } from './control/list_control_factory'; import { InputControlVisDependencies } from './plugin'; import { FilterManager, Filter } from '../../../../plugins/data/public'; -import { VisParams, Vis } from '../../visualizations/public'; +import { VisParams, Vis } from '../../../../plugins/visualizations/public'; export const createInputControlVisController = (deps: InputControlVisDependencies) => { return class InputControlVisController { diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 1d772536fa1ea..cac9ef30fba4f 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -24,7 +24,6 @@ import { promisify } from 'util'; import { migrations } from './migrations'; import { importApi } from './server/routes/api/import'; import { exportApi } from './server/routes/api/export'; -import { managementApi } from './server/routes/api/management'; import mappings from './mappings.json'; import { getUiSettingDefaults } from './ui_setting_defaults'; import { registerCspCollector } from './server/lib/csp_usage_collector'; @@ -259,7 +258,6 @@ export default function(kibana) { // routes importApi(server); exportApi(server); - managementApi(server); registerCspCollector(usageCollection, server); server.injectUiAppVars('kibana', () => injectVars(server)); }, diff --git a/src/legacy/core_plugins/kibana/inject_vars.js b/src/legacy/core_plugins/kibana/inject_vars.js index 01623341e4d38..76d1704907ab5 100644 --- a/src/legacy/core_plugins/kibana/inject_vars.js +++ b/src/legacy/core_plugins/kibana/inject_vars.js @@ -20,12 +20,7 @@ export function injectVars(server) { const serverConfig = server.config(); - // Get types that are import and exportable, by default yes unless isImportableAndExportable is set to false - const { types: allTypes } = server.savedObjects; - const savedObjectsManagement = server.getSavedObjectsManagement(); - const importAndExportableTypes = allTypes.filter(type => - savedObjectsManagement.isImportAndExportable(type) - ); + const { importAndExportableTypes } = server.savedObjects; return { importAndExportableTypes, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts index 55e1475fcb03a..86bce5997cdd2 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -25,7 +25,6 @@ */ export { npSetup, npStart } from 'ui/new_platform'; -export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; export { configureAppAngularModule, migrateLegacyQuery, diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.test.ts deleted file mode 100644 index 60ca1b39d29d6..0000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -jest.mock('../', () => ({ - DashboardConstants: { - ADD_EMBEDDABLE_ID: 'addEmbeddableId', - ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', - }, -})); - -jest.mock('../legacy_imports', () => { - return { - absoluteToParsedUrl: jest.fn(() => { - return { - basePath: '/pep', - appId: 'kibana', - appPath: '/dashboard?addEmbeddableType=lens&addEmbeddableId=123eb456cd&x=1&y=2&z=3', - hostname: 'localhost', - port: 5601, - protocol: 'http:', - addQueryParameter: () => {}, - getAbsoluteUrl: () => { - return 'http://localhost:5601/pep/app/kibana#/dashboard?addEmbeddableType=lens&addEmbeddableId=123eb456cd&x=1&y=2&z=3'; - }, - }; - }), - }; -}); - -import { - addEmbeddableToDashboardUrl, - getLensUrlFromDashboardAbsoluteUrl, - getUrlVars, -} from './url_helper'; - -describe('Dashboard URL Helper', () => { - beforeEach(() => { - jest.resetModules(); - }); - - it('addEmbeddableToDashboardUrl', () => { - const id = '123eb456cd'; - const type = 'lens'; - const urlVars = { - x: '1', - y: '2', - z: '3', - }; - const basePath = '/pep'; - const url = - "http://localhost:5601/pep/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(addEmbeddableToDashboardUrl(url, basePath, id, urlVars, type)).toEqual( - `http://localhost:5601/pep/app/kibana#/dashboard?addEmbeddableType=${type}&addEmbeddableId=${id}&x=1&y=2&z=3` - ); - }); - - it('getUrlVars', () => { - let url = - "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getUrlVars(url)).toEqual({ - _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))', - _a: "(description:'',filters:!()", - }); - url = 'http://mybusiness.mydomain.com/app/kibana#/dashboard?x=y&y=z'; - expect(getUrlVars(url)).toEqual({ - x: 'y', - y: 'z', - }); - url = 'http://localhost:5601/app/kibana#/dashboard/777182'; - expect(getUrlVars(url)).toEqual({}); - url = - 'http://localhost:5601/app/kibana#/dashboard/777182?title=Some%20Dashboard%20With%20Spaces'; - expect(getUrlVars(url)).toEqual({ title: 'Some Dashboard With Spaces' }); - }); - - it('getLensUrlFromDashboardAbsoluteUrl', () => { - const id = '1244'; - const basePath = '/wev'; - let url = - "http://localhost:5601/wev/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( - 'http://localhost:5601/wev/app/kibana#/lens/edit/1244' - ); - - url = - "http://localhost:5601/wev/app/kibana#/dashboard/625357282?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"; - expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( - 'http://localhost:5601/wev/app/kibana#/lens/edit/1244' - ); - - url = 'http://myserver.mydomain.com:5601/wev/app/kibana#/dashboard/777182'; - expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( - 'http://myserver.mydomain.com:5601/wev/app/kibana#/lens/edit/1244' - ); - - url = - "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getLensUrlFromDashboardAbsoluteUrl(url, '', id)).toEqual( - 'http://localhost:5601/app/kibana#/lens/edit/1244' - ); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts deleted file mode 100644 index 73383f2ff3f68..0000000000000 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { parse } from 'url'; -import { absoluteToParsedUrl } from '../legacy_imports'; -import { DashboardConstants } from './dashboard_constants'; -/** - * Return query params from URL - * @param url given url - */ -export function getUrlVars(url: string): Record<string, string> { - const vars: Record<string, string> = {}; - for (const [, key, value] of url.matchAll(/[?&]+([^=&]+)=([^&]*)/gi)) { - vars[key] = decodeURIComponent(value); - } - return vars; -} - -/** * - * Returns dashboard URL with added embeddableType and embeddableId query params - * eg. - * input: url: http://localhost:5601/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)), embeddableId: 12345, embeddableType: 'lens' - * output: http://localhost:5601/lib/app/kibana#dashboard?addEmbeddableType=lens&addEmbeddableId=12345&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)) - * @param url dasbhoard absolute url - * @param embeddableId id of the saved visualization - * @param basePath current base path - * @param urlVars url query params (optional) - * @param embeddableType 'lens' or 'visualization' (optional, default is 'lens') - */ -export function addEmbeddableToDashboardUrl( - url: string | undefined, - basePath: string, - embeddableId: string, - urlVars?: Record<string, string>, - embeddableType?: string -): string | null { - if (!url) { - return null; - } - const dashboardUrl = getUrlWithoutQueryParams(url); - const dashboardParsedUrl = absoluteToParsedUrl(dashboardUrl, basePath); - if (urlVars) { - const keys = Object.keys(urlVars).sort(); - keys.forEach(key => { - dashboardParsedUrl.addQueryParameter(key, urlVars[key]); - }); - } - dashboardParsedUrl.addQueryParameter( - DashboardConstants.ADD_EMBEDDABLE_TYPE, - embeddableType || 'lens' - ); - dashboardParsedUrl.addQueryParameter(DashboardConstants.ADD_EMBEDDABLE_ID, embeddableId); - return dashboardParsedUrl.getAbsoluteUrl(); -} - -/** - * Return Lens URL from dashboard absolute URL - * @param dashboardAbsoluteUrl - * @param basePath current base path - * @param id Lens id - */ -export function getLensUrlFromDashboardAbsoluteUrl( - dashboardAbsoluteUrl: string | undefined | null, - basePath: string | null | undefined, - id: string -): string | null { - if (!dashboardAbsoluteUrl || basePath === null || basePath === undefined) { - return null; - } - const { host, protocol } = parse(dashboardAbsoluteUrl); - return `${protocol}//${host}${basePath}/app/kibana#/lens/edit/${id}`; -} - -/** - * Returns the portion of the URL without query params - * eg. - * input: http://localhost:5601/lib/app/kibana#/dashboard?param1=x¶m2=y¶m3=z - * output:http://localhost:5601/lib/app/kibana#/dashboard - * input: http://localhost:5601/lib/app/kibana#/dashboard/39292992?param1=x¶m2=y¶m3=z - * output: http://localhost:5601/lib/app/kibana#/dashboard/39292992 - * @param url url to parse - */ -function getUrlWithoutQueryParams(url: string): string { - return url.split('?')[0]; -} diff --git a/src/legacy/core_plugins/kibana/public/discover/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/build_services.ts index f881eb96e4e81..180ff13cdddc0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/build_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/build_services.ts @@ -36,7 +36,7 @@ import { import { DiscoverStartPlugins } from './plugin'; import { SharePluginStart } from '../../../../../plugins/share/public'; import { ChartsPluginStart } from '../../../../../plugins/charts/public'; -import { VisualizationsStart } from '../../../visualizations/public'; +import { VisualizationsStart } from '../../../../../plugins/visualizations/public'; import { createSavedSearchesLoader, DocViewerComponent, diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index 7a3a6949baa94..2ceb06f325a9e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -47,10 +47,15 @@ export function setServices(newServices: any) { services = newServices; } +export const [getUrlTracker, setUrlTracker] = createGetterSetter<{ + setTrackedUrl: (url: string) => void; +}>('urlTracker'); + // EXPORT legacy static dependencies, should be migrated when available in a new version; export { angular }; export { wrapInI18nContext } from 'ui/i18n'; import { search } from '../../../../../plugins/data/public'; +import { createGetterSetter } from '../../../../../plugins/kibana_utils/common'; export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search; export { unhashUrl, @@ -75,6 +80,5 @@ export { EsQuerySortValue, SortDirection, } from '../../../../../plugins/data/public'; -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; // @ts-ignore export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; diff --git a/src/legacy/core_plugins/kibana/public/discover/legacy.ts b/src/legacy/core_plugins/kibana/public/discover/legacy.ts index a1ef646f4fe85..f08fd22c71850 100644 --- a/src/legacy/core_plugins/kibana/public/discover/legacy.ts +++ b/src/legacy/core_plugins/kibana/public/discover/legacy.ts @@ -20,18 +20,8 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; import { plugin } from './index'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../../../core_plugins/visualizations/public/np_ready/public/legacy'; // Legacy compatibility part - to be removed at cutover, replaced by a kibana.json file export const pluginInstance = plugin({} as PluginInitializerContext); -export const setup = pluginInstance.setup(npSetup.core, { - ...npSetup.plugins, - visualizations: visualizationsSetup, -}); -export const start = pluginInstance.start(npStart.core, { - ...npStart.plugins, - visualizations: visualizationsStart, -}); +export const setup = pluginInstance.setup(npSetup.core, npSetup.plugins); +export const start = pluginInstance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html index 2334e33deadba..e9338b8bd57cc 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html @@ -1,4 +1,4 @@ -<discover-app class="app-container"> +<discover-app class="app-container" data-fetch-counter="{{fetchCounter}}"> <h1 class="euiScreenReaderOnly">{{screenTitle}}</h1> <!-- Local nav. --> diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 8e4e77b2d18a6..630ba22d4f3a6 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -44,6 +44,7 @@ import { getRequestInspectorStats, getResponseInspectorStats, getServices, + getUrlTracker, unhashUrl, subscribeWithScope, tabifyAggResponse, @@ -160,6 +161,9 @@ app.config($routeProvider => { '/management/kibana/objects/savedSearches/' + $route.current.params.id, }, toastNotifications, + onBeforeRedirect() { + getUrlTracker().setTrackedUrl('/discover'); + }, }) ), }); @@ -194,6 +198,8 @@ function discoverController( const savedSearch = $route.current.locals.savedObjects.savedSearch; $scope.searchSource = savedSearch.searchSource; $scope.indexPattern = resolveIndexPatternLoading(); + //used for functional testing + $scope.fetchCounter = 0; const getTimeField = () => { return isDefaultType($scope.indexPattern) ? $scope.indexPattern.timeFieldName : undefined; @@ -275,6 +281,7 @@ function discoverController( filterManager.getUpdates$(), { next: () => { + $scope.state.filters = filterManager.getAppFilters(); $scope.updateDataSource(); }, }, @@ -784,7 +791,7 @@ function discoverController( $scope.opts.fetch = $scope.fetch = function() { // ignore requests to fetch before the app inits if (!init.complete) return; - + $scope.fetchCounter++; $scope.fetchError = undefined; // Abort any in-progress requests before fetching again @@ -821,9 +828,11 @@ function discoverController( }); }; - $scope.updateQuery = function({ query }) { - setAppState({ query }); - $fetchObservable.next(); + $scope.updateQuery = function({ query }, isUpdate = true) { + if (!_.isEqual(query, appStateContainer.getState().query) || isUpdate === false) { + setAppState({ query }); + $fetchObservable.next(); + } }; $scope.updateSavedQueryId = newSavedQueryId => { diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js index e49f43a443719..0c19c10841535 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js @@ -17,7 +17,7 @@ * under the License. */ -import { buildPointSeriesData, getFormat } from '../../kibana_services'; +import { buildPointSeriesData, getServices } from '../../kibana_services'; function tableResponseHandler(table, dimensions) { const converted = { tables: [] }; @@ -26,7 +26,7 @@ function tableResponseHandler(table, dimensions) { if (split) { converted.direction = dimensions.splitRow ? 'row' : 'column'; const splitColumnIndex = split[0].accessor; - const splitColumnFormatter = getFormat(split[0].format); + const splitColumnFormatter = getServices().data.fieldFormats.deserialize(split[0].format); const splitColumn = table.columns[splitColumnIndex]; const splitMap = {}; let splitIndex = 0; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/field_chooser/lib/visualize_url_utils.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/field_chooser/lib/visualize_url_utils.ts index 7ea1863693e0d..21e8e9f5e39a0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/field_chooser/lib/visualize_url_utils.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/field_chooser/lib/visualize_url_utils.ts @@ -84,6 +84,7 @@ export function getMapsAppUrl( // create initial layer descriptor const hasColumns = columns && columns.length && columns[0] !== '_source'; + const supportsClustering = field.aggregatable; mapAppParams.set( 'initialLayers', // @ts-ignore @@ -97,9 +98,10 @@ export function getMapsAppUrl( geoField: field.name, tooltipProperties: hasColumns ? columns : [], indexPatternId: indexPattern.id, + scalingType: supportsClustering ? 'CLUSTERS' : 'LIMIT', }, visible: true, - type: 'VECTOR', + type: supportsClustering ? 'BLENDED_VECTOR' : 'VECTOR', }, ]) ); diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index d3cdeb49fba71..fcac7aa74f54a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -31,7 +31,7 @@ import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; import { EmbeddableStart, EmbeddableSetup } from '../../../../../plugins/embeddable/public'; import { getInnerAngularModule, getInnerAngularModuleEmbeddable } from './get_inner_angular'; -import { setAngularModule, setServices } from './kibana_services'; +import { setAngularModule, setServices, setUrlTracker } from './kibana_services'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { ChartsPluginStart } from '../../../../../plugins/charts/public'; import { buildServices } from './build_services'; @@ -45,7 +45,7 @@ import { HomePublicPluginSetup } from '../../../../../plugins/home/public'; import { VisualizationsStart, VisualizationsSetup, -} from '../../../visualizations/public/np_ready/public'; +} from '../../../../../plugins/visualizations/public'; import { createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public'; export interface DiscoverSetupPlugins { @@ -91,8 +91,13 @@ export class DiscoverPlugin implements Plugin<void, void> { public initializeInnerAngular?: () => void; public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; - setup(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins) { - const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ + setup(core: CoreSetup<DiscoverStartPlugins, void>, plugins: DiscoverSetupPlugins) { + const { + appMounted, + appUnMounted, + stop: stopUrlTracker, + setActiveUrl: setTrackedUrl, + } = createKbnUrlTracker({ baseUrl: core.http.basePath.prepend('/app/kibana'), defaultSubUrl: '#/discover', storageKey: 'lastUrl:discover', @@ -113,6 +118,7 @@ export class DiscoverPlugin implements Plugin<void, void> { }, ], }); + setUrlTracker({ setTrackedUrl }); this.stopUrlTracking = () => { stopUrlTracker(); }; diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg index 20694ba6e62c7..8d525c23e6801 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/activemq.svg @@ -1,31 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 128 128"> - <defs> - <filter id="a" color-interpolation-filters="sRGB"> - <feFlood flood-opacity=".498" flood-color="#000" result="flood" /> - <feComposite in="flood" in2="SourceGraphic" operator="in" result="composite1" /> - <feGaussianBlur in="composite1" stdDeviation=".2" result="blur" /> - <feOffset dx="1" dy="1" result="offset" /> - <feComposite in="SourceGraphic" in2="offset" result="composite2" /> - </filter> - </defs> - <g filter="url(#a)" fill="#fff" transform="matrix(2.8 0 0 2.8 -90 -305)"> - <path d="M64.697 153.552l-8.352-.05-4.133-7.257 4.218-7.208 8.352.049 4.134 7.257z" /> - <path d="M52.632 146.553l-8.352-.049-4.133-7.257 4.218-7.209 8.352.05 4.134 7.257z" /> - <path d="M64.771 139.589l-8.352-.05-4.133-7.257 4.218-7.208 8.352.05 4.134 7.257z" /> - <path d="M64.765 125.702l-8.351-.049-4.134-7.257 4.219-7.209 8.352.05 4.133 7.257z" /> - <path d="M52.696 132.676l-8.352-.049-4.133-7.257 4.218-7.209 8.352.05 4.133 7.257z" /> - </g> - <g transform="matrix(2.8 0 0 2.8 -90 -305)"> - <path d="M64.266 138.661l-7.296-.022-3.628-6.33L57.009 126l7.297.023 3.628 6.33z" fill="#c12766" /> - <path d="M52.127 145.626l-7.296-.023-3.628-6.33 3.667-6.307 7.296.022 3.629 6.33z" fill="#3e489f" /> - <path d="M64.19 152.624l-7.295-.023-3.629-6.33 3.668-6.307 7.296.023 3.629 6.33z" fill="#714099" /> - <path d="M52.191 131.749l-7.296-.023-3.629-6.33 3.668-6.307 7.296.022 3.629 6.33z" fill="#78932c" /> - <path d="M64.26 124.775l-7.296-.023-3.628-6.33 3.668-6.307 7.296.022 3.628 6.33z" fill="#cf242a" /> - <circle cy="146.294" cx="60.564" r="1.6" fill="#fff" /> - <path d="M61.748 117.71l-14.267 8.174M48.514 124.197l.048 16.442M47.525 138.715l14.136 8.397M60.59 117.133l.048 16.442M60.657 131.093l.048 16.442M61.766 131.708l-14.267 8.174M47.564 124.84l14.136 8.398" fill="none" stroke="#fff" stroke-width=".524" /> - <circle cy="139.242" cx="48.334" r="1.6" fill="#fff" /> - <circle cy="132.486" cx="60.901" r="1.6" fill="#fff" /> - <circle cy="125.419" cx="48.563" r="1.6" fill="#fff" /> - <circle cy="118.445" cx="60.632" r="1.6" fill="#fff" /> - </g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 128 128"><defs><filter id="a" color-interpolation-filters="sRGB"><feFlood flood-opacity=".498" flood-color="#000" result="flood"/><feComposite in="flood" in2="SourceGraphic" operator="in" result="composite1"/><feGaussianBlur in="composite1" stdDeviation=".2" result="blur"/><feOffset dx="1" dy="1" result="offset"/><feComposite in="SourceGraphic" in2="offset" result="composite2"/></filter></defs><g filter="url(#a)" fill="#fff" transform="matrix(2.8 0 0 2.8 -90 -305)"><path d="M64.697 153.552l-8.352-.05-4.133-7.257 4.218-7.208 8.352.049 4.134 7.257z"/><path d="M52.632 146.553l-8.352-.049-4.133-7.257 4.218-7.209 8.352.05 4.134 7.257z"/><path d="M64.771 139.589l-8.352-.05-4.133-7.257 4.218-7.208 8.352.05 4.134 7.257z"/><path d="M64.765 125.702l-8.351-.049-4.134-7.257 4.219-7.209 8.352.05 4.133 7.257z"/><path d="M52.696 132.676l-8.352-.049-4.133-7.257 4.218-7.209 8.352.05 4.133 7.257z"/></g><g transform="matrix(2.8 0 0 2.8 -90 -305)"><path d="M64.266 138.661l-7.296-.022-3.628-6.33L57.009 126l7.297.023 3.628 6.33z" fill="#c12766"/><path d="M52.127 145.626l-7.296-.023-3.628-6.33 3.667-6.307 7.296.022 3.629 6.33z" fill="#3e489f"/><path d="M64.19 152.624l-7.295-.023-3.629-6.33 3.668-6.307 7.296.023 3.629 6.33z" fill="#714099"/><path d="M52.191 131.749l-7.296-.023-3.629-6.33 3.668-6.307 7.296.022 3.629 6.33z" fill="#78932c"/><path d="M64.26 124.775l-7.296-.023-3.628-6.33 3.668-6.307 7.296.022 3.628 6.33z" fill="#cf242a"/><circle cy="146.294" cx="60.564" r="1.6" fill="#fff"/><path d="M61.748 117.71l-14.267 8.174m1.033-1.687l.048 16.442m-1.037-1.924l14.136 8.397m-1.071-29.979l.048 16.442m.019-2.482l.048 16.442m1.061-15.827l-14.267 8.174m.065-15.042l14.136 8.398" fill="none" stroke="#fff" stroke-width=".524"/><circle cy="139.242" cx="48.334" r="1.6" fill="#fff"/><circle cy="132.486" cx="60.901" r="1.6" fill="#fff"/><circle cy="125.419" cx="48.563" r="1.6" fill="#fff"/><circle cy="118.445" cx="60.632" r="1.6" fill="#fff"/></g></svg> \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg index f8df12ba05c50..a93c83b4b4ae0 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/azure.svg @@ -1,17 +1 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" - "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> -<svg version="1.0" xmlns="http://www.w3.org/2000/svg" - width="251.000000pt" height="200.000000pt" viewBox="0 0 251.000000 200.000000" - preserveAspectRatio="xMidYMid meet"> - -<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)" -fill="#000000" stroke="none"> -<path d="M993 1670 l-358 -311 -309 -552 c-169 -304 -310 -558 -313 -564 -4 --10 55 -13 275 -13 l279 0 363 803 c200 441 378 835 397 875 18 39 31 72 29 -72 -2 0 -165 -140 -363 -310z"/> -<path d="M1462 1819 c-5 -13 -76 -212 -157 -441 l-147 -417 300 -378 c192 --241 297 -380 289 -384 -7 -3 -260 -48 -564 -100 l-552 -94 931 -3 c512 -1 -933 0 936 2 2 3 -228 417 -512 922 -450 800 -517 914 -524 893z"/> -</g> -</svg> +<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="334.667" height="266.667" viewBox="0 0 251 200"><path d="M99.3 33L63.5 64.1l-30.9 55.2c-16.9 30.4-31 55.8-31.3 56.4-.4 1 5.5 1.3 27.5 1.3h27.9L93 96.7c20-44.1 37.8-83.5 39.7-87.5 1.8-3.9 3.1-7.2 2.9-7.2-.2 0-16.5 14-36.3 31zM146.2 18.1c-.5 1.3-7.6 21.2-15.7 44.1l-14.7 41.7 30 37.8c19.2 24.1 29.7 38 28.9 38.4-.7.3-26 4.8-56.4 10l-55.2 9.4 93.1.3c51.2.1 93.3 0 93.6-.2.2-.3-22.8-41.7-51.2-92.2-45-80-51.7-91.4-52.4-89.3z"/></svg> \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg new file mode 100644 index 0000000000000..20ebebf19741e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cisco.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216" height="216" fill="#049fd9"><g transform="translate(0 50.059)"><path d="M106.48 76.238c-.282-.077-4.621-1.196-9.232-1.196-8.73 0-13.986 4.714-13.986 11.734 0 6.214 4.397 9.313 9.674 10.98.585.193 1.447.463 2.021.653 2.349.739 4.224 1.837 4.224 3.739 0 2.127-2.167 3.504-6.878 3.504-4.14 0-8.109-1.184-8.945-1.395v8.637c.466.099 5.183 1.025 10.222 1.025 7.248 0 15.539-3.167 15.539-12.595 0-4.573-2.8-8.783-8.947-10.737l-2.613-.832c-1.559-.492-4.342-1.289-4.342-3.574 0-1.805 2.062-3.076 5.859-3.076 3.276 0 7.263 1.101 7.404 1.145zm80.041 18.243c0 5.461-4.183 9.879-9.796 9.879-5.619 0-9.791-4.418-9.791-9.879 0-5.45 4.172-9.87 9.791-9.87 5.613 0 9.796 4.42 9.796 9.87m-9.796-19.427c-11.544 0-19.823 8.707-19.823 19.427 0 10.737 8.279 19.438 19.823 19.438 11.543 0 19.834-8.701 19.834-19.438 0-10.72-8.291-19.427-19.834-19.427M70.561 113.251h-9.472V75.719h9.472"/><path id="a" d="M48.07 76.399c-.89-.264-4.18-1.345-8.636-1.345-11.526 0-19.987 8.218-19.987 19.427 0 12.093 9.34 19.438 19.987 19.438 4.23 0 7.459-1.002 8.636-1.336v-10.075c-.407.226-3.503 1.992-7.957 1.992-6.31 0-10.38-4.441-10.38-10.019 0-5.748 4.246-10.011 10.38-10.011 4.53 0 7.576 1.805 7.957 2.004"/><use transform="translate(98.86)" xlink:href="#a" width="100%" height="100%"/><g id="c"><path id="b" d="M61.061 4.759c0-2.587-2.113-4.685-4.703-4.685-2.589 0-4.702 2.098-4.702 4.685v49.84a4.701 4.701 0 004.702 4.699 4.701 4.701 0 004.703-4.699zM35.232 22.451c0-2.586-2.112-4.687-4.702-4.687s-4.702 2.101-4.702 4.687v22.785a4.701 4.701 0 004.702 4.699 4.701 4.701 0 004.702-4.699zM9.404 35.383c0-2.587-2.112-4.684-4.702-4.684C2.115 30.699 0 32.796 0 35.383v9.853a4.703 4.703 0 009.404 0"/><use transform="matrix(-1 0 0 1 112.717 0)" xlink:href="#b" width="100%" height="100%"/></g><use transform="matrix(-1 0 0 1 216 0)" xlink:href="#c" width="100%" height="100%"/></g></svg> \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg index 72f0958f52824..08a4bdabb380f 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/cockroachdb.svg @@ -1,666 +1 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - version="1.1" - id="Layer_1" - x="0px" - y="0px" - viewBox="-12.06 13.62 35.251247 35.398594" - xml:space="preserve" - sodipodi:docname="cockroachdb-logo.svg" - width="35.251247" - height="35.398594" - inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata - id="metadata32"><rdf:RDF><cc:Work - rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs - id="defs30"> - - <defs - id="defs9"> - <filter - height="71.5" - width="56.200001" - y="41.400002" - x="555.70001" - filterUnits="userSpaceOnUse" - id="Adobe_OpacityMaskFilter"> - <feColorMatrix - id="feColorMatrix6" - values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" - type="matrix" /> - </filter> - </defs> - <mask - id="b_1_" - height="71.5" - width="56.2" - y="41.4" - x="555.7" - maskUnits="userSpaceOnUse"> - <g - style="filter:url(#Adobe_OpacityMaskFilter)" - id="g12" - class="st549"> - <path - style="fill:#ffffff" - inkscape:connector-curvature="0" - d="M 306.3,12.4 H 0.8 V 133.3 H 611.9 V 12.4 Z" - class="st550" - id="a_1_" /> - </g> - </mask> - - - - - -</defs><sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1025" - id="namedview28" - showgrid="false" - inkscape:zoom="3.2474375" - inkscape:cx="122.58339" - inkscape:cy="-49.295899" - inkscape:window-x="6" - inkscape:window-y="27" - inkscape:window-maximized="1" - inkscape:current-layer="Layer_1" - fit-margin-top="1" - fit-margin-left="1" - fit-margin-right="1" - fit-margin-bottom="1" /> -<style - type="text/css" - id="style2"> - .st0{fill:#4A8FE1;} - .st1{fill:#FEFEFE;} - .st2{fill:#716F73;} - .st3{fill:#4D8951;} - .st4{fill:#A6D3EA;} - .st5{fill:#3A3868;} - .st6{fill:#717073;} - .st7{fill:#1B995A;} - .st8{fill:#717B83;} - .st9{fill:#2BA3A4;} - .st10{fill:#717074;} - .st11{fill:#717173;} - .st12{fill:#707B83;} - .st13{fill:#67A3D1;} - .st14{fill:#2B5B68;} - .st15{fill:#B9DCF3;} - .st16{fill:#2A4B38;} - .st17{fill:#83939F;} - .st18{fill:#9DCCE8;} - .st19{fill:#85939C;} - .st20{fill:#82929C;} - .st21{fill:#40A6D5;} - .st22{fill:#2B4B39;} - .st23{fill:#28493A;} - .st24{fill:#2EA3A7;} - .st25{fill:#F8FCFC;} - .st26{fill:#568F52;} - .st27{fill:#94C453;} - .st28{fill:#206289;} - .st29{fill:#F1FBFD;} - .st30{fill:#F6FDFE;} - .st31{fill:#F8FCFB;} - .st32{fill:#FAFDFB;} - .st33{fill:#F4FCFD;} - .st34{fill:#65AC62;} - .st35{fill:#F8FAF3;} - .st36{fill:#5EAD5A;} - .st37{fill:#F6FCFA;} - .st38{fill:#85C5B8;} - .st39{fill:#3CA0D5;} - .st40{fill:#727A80;} - .st41{fill:#F6FCFD;} - .st42{fill:#FEFEFA;} - .st43{fill:#459ED2;} - .st44{fill:#5DAE5B;} - .st45{fill:#5E7F47;} - .st46{fill:#FCFCFC;} - .st47{fill:#C1DBED;} - .st48{fill:#FBFDF8;} - .st49{fill:#EBF5F7;} - .st50{fill:#294949;} - .st51{fill:#8FC8E5;} - .st52{fill:#F7FCFC;} - .st53{fill:#FCFEFA;} - .st54{fill:#4E8A56;} - .st55{fill:#64BDE8;} - .st56{fill:#FEFDFA;} - .st57{fill:#FBFDFC;} - .st58{fill:#449DD5;} - .st59{fill:#F6FBF7;} - .st60{fill:#279A5B;} - .st61{fill:#30493D;} - .st62{fill:#F5FBF9;} - .st63{fill:#35583B;} - .st64{fill:#323C62;} - .st65{fill:#F8FBF9;} - .st66{fill:#E7EFF2;} - .st67{fill:#8DC1B6;} - .st68{fill:#FAFCFA;} - .st69{fill:#F1FBF9;} - .st70{fill:#F7FEFE;} - .st71{fill:#FDFEFA;} - .st72{fill:#31A1A1;} - .st73{fill:#F9FEFD;} - .st74{fill:#FAFAFC;} - .st75{fill:#FDFCF8;} - .st76{fill:#2D5C60;} - .st77{fill:#FDFCF9;} - .st78{fill:#F9FDFB;} - .st79{fill:#FBFBFB;} - .st80{fill:#518B58;} - .st81{fill:#5A82AF;} - .st82{fill:#FDFEF8;} - .st83{fill:#244C40;} - .st84{fill:#266495;} - .st85{fill:#42A0D3;} - .st86{fill:#5B80A9;} - .st87{fill:#2E5B63;} - .st88{fill:#FDFBF9;} - .st89{fill:#F8FDFB;} - .st90{fill:#FDFDF7;} - .st91{fill:#F3F9FB;} - .st92{fill:#309F96;} - .st93{fill:#93C367;} - .st94{fill:#3B3C68;} - .st95{fill:#E0F1F9;} - .st96{fill:#E4F6F9;} - .st97{fill:#FEFEF9;} - .st98{fill:#224C38;} - .st99{fill:#498AB2;} - .st100{fill:#FDFDF9;} - .st101{fill:#F9FEFE;} - .st102{fill:#F6FCF2;} - .st103{fill:#FEFCF9;} - .st104{fill:#EEFCFE;} - .st105{fill:#FDFDF8;} - .st106{fill:#FBFDFA;} - .st107{fill:#275962;} - .st108{fill:#FDFEF9;} - .st109{fill:#F2F8F2;} - .st110{fill:#F8FBFB;} - .st111{fill:#8A8A8A;} - .st112{fill:#F7FEFD;} - .st113{fill:#EFF8FB;} - .st114{fill:#FAFCFB;} - .st115{fill:#E5F3F8;} - .st116{fill:#ECF7FA;} - .st117{fill:#FDFDF6;} - .st118{fill:#F5FDFD;} - .st119{fill:#7799BF;} - .st120{fill:#5C8055;} - .st121{fill:#6EAECC;} - .st122{fill:#FEFEF7;} - .st123{fill:#3282B5;} - .st124{fill:#F3FCF5;} - .st125{fill:#F4FAFB;} - .st126{fill:#FEF8FA;} - .st127{fill:#F5FCF9;} - .st128{fill:#3C9392;} - .st129{fill:#EBF6F6;} - .st130{fill:#98BFD6;} - .st131{fill:#FEFDF7;} - .st132{fill:#658796;} - .st133{fill:#EEF7F6;} - .st134{fill:#FAFBF5;} - .st135{fill:#F8FCF9;} - .st136{fill:#FDFDF4;} - .st137{fill:#FDFBF8;} - .st138{fill:#FDFDF5;} - .st139{fill:#EFF9FD;} - .st140{fill:#FDFEF6;} - .st141{fill:#37586D;} - .st142{fill:#FDFEF5;} - .st143{fill:#FDFBF6;} - .st144{fill:#324A49;} - .st145{fill:#F8F8F9;} - .st146{fill:#CDF5CD;} - .st147{fill:#FEFDF3;} - .st148{fill:#ECFBFE;} - .st149{fill:#858585;} - .st150{fill:#C5C5C5;} - .st151{fill:#6C6C6C;} - .st152{fill:#498B4F;} - .st153{fill:#478A4D;} - .st154{fill:#4A884D;} - .st155{fill:#429169;} - .st156{fill:#3CA29D;} - .st157{fill:#518654;} - .st158{fill:#51855F;} - .st159{fill:#289FA0;} - .st160{fill:#448E49;} - .st161{fill:#458B55;} - .st162{fill:#568356;} - .st163{fill:#89C9ED;} - .st164{fill:#246081;} - .st165{fill:#206186;} - .st166{fill:#8EC8E9;} - .st167{fill:#2B5D7D;} - .st168{fill:#215F80;} - .st169{fill:#A0D4EF;} - .st170{fill:#A4D3F2;} - .st171{fill:#245E84;} - .st172{fill:#69BADA;} - .st173{fill:#9AC9D1;} - .st174{fill:#9AC7DD;} - .st175{fill:#3B396C;} - .st176{fill:#3A376D;} - .st177{fill:#3D366C;} - .st178{fill:#6A9BC9;} - .st179{fill:#57B156;} - .st180{fill:#2A9762;} - .st181{fill:#139C59;} - .st182{fill:#169A5E;} - .st183{fill:#139C5D;} - .st184{fill:#129652;} - .st185{fill:#61839B;} - .st186{fill:#637F92;} - .st187{fill:#289193;} - .st188{fill:#288F8D;} - .st189{fill:#34A3A8;} - .st190{fill:#23A7A5;} - .st191{fill:#36A2A8;} - .st192{fill:#32A1A0;} - .st193{fill:#23A7A2;} - .st194{fill:#249A96;} - .st195{fill:#FCFCFD;} - .st196{fill:#FDFDFD;} - .st197{fill:#6B7B8C;} - .st198{fill:#4C84B0;} - .st199{fill:#4F81BA;} - .st200{fill:#5280B6;} - .st201{fill:#6CA1CE;} - .st202{fill:#6CA0CF;} - .st203{fill:#7AA4CC;} - .st204{fill:#71A3D5;} - .st205{fill:#6AA3C9;} - .st206{fill:#6EA5D6;} - .st207{fill:#6C97B9;} - .st208{fill:#4F6684;} - .st209{fill:#2D5D62;} - .st210{fill:#275C5E;} - .st211{fill:#2B5859;} - .st212{fill:#285C5E;} - .st213{fill:#9FCCE5;} - .st214{fill:#BCDBEF;} - .st215{fill:#B5DDF9;} - .st216{fill:#234D37;} - .st217{fill:#2E483A;} - .st218{fill:#8294A2;} - .st219{fill:#256286;} - .st220{fill:#8095A3;} - .st221{fill:#3FA6DA;} - .st222{fill:#62BEEC;} - .st223{fill:#40A7D6;} - .st224{fill:#43A3DF;} - .st225{fill:#274C3B;} - .st226{fill:#4C9FC8;} - .st227{fill:#234D32;} - .st228{fill:#2C473D;} - .st229{fill:#27572D;} - .st230{fill:#2D473F;} - .st231{fill:#22A69E;} - .st232{fill:#22A1A1;} - .st233{fill:#378E8D;} - .st234{fill:#268C8A;} - .st235{fill:#40817E;} - .st236{fill:#528E4D;} - .st237{fill:#94C15C;} - .st238{fill:#518D4F;} - .st239{fill:#4B954A;} - .st240{fill:#95C350;} - .st241{fill:#93C451;} - .st242{fill:#90C147;} - .st243{fill:#90B254;} - .st244{fill:#1A6292;} - .st245{fill:#2F82B5;} - .st246{fill:#3FA7DA;} - .st247{fill:#43A5D7;} - .st248{fill:#51ADD8;} - .st249{fill:#57B0E2;} - .st250{fill:#4C95B8;} - .st251{fill:#7BC2EB;} - .st252{fill:#7BC2E8;} - .st253{fill:#439DCE;} - .st254{fill:#1A66A0;} - .st255{fill:#429FD0;} - .st256{fill:#22669E;} - .st257{fill:#42A1D2;} - .st258{fill:#42A6D7;} - .st259{fill:#4EA6CD;} - .st260{fill:#90B15F;} - .st261{fill:#5EAF59;} - .st262{fill:#1568A3;} - .st263{fill:#44A4D8;} - .st264{fill:#2D5F86;} - .st265{fill:#82C6B7;} - .st266{fill:#93C6B3;} - .st267{fill:#81C7BD;} - .st268{fill:#8CC3BB;} - .st269{fill:#3EA0D1;} - .st270{fill:#429ED2;} - .st271{fill:#449DD7;} - .st272{fill:#3AA1DA;} - .st273{fill:#3D9FD7;} - .st274{fill:#439DD3;} - .st275{fill:#69A46E;} - .st276{fill:#74B273;} - .st277{fill:#58AB52;} - .st278{fill:#325946;} - .st279{fill:#214A49;} - .st280{fill:#244B3F;} - .st281{fill:#3181B4;} - .st282{fill:#1DA3A4;} - .st283{fill:#346E9F;} - .st284{fill:#869197;} - .st285{fill:#53B0EA;} - .st286{fill:#5181C0;} - .st287{fill:#1767A6;} - .st288{fill:#3F9FD5;} - .st289{fill:#399291;} - .st290{fill:#27A2A7;} - .st291{fill:#81969C;} - .st292{fill:#46A4D7;} - .st293{fill:#C7DCB8;} - .st294{fill:#B5B5B5;} - .st295{fill:#4F9A83;} - .st296{fill:#63BDE8;} - .st297{fill:#95C3E7;} - .st298{fill:#1D618B;} - .st299{fill:#1D6286;} - .st300{fill:#3181B5;} - .st301{fill:#249190;} - .st302{fill:#2C9096;} - .st303{fill:#23918E;} - .st304{fill:#2E939A;} - .st305{fill:#469DD6;} - .st306{fill:#40A0D2;} - .st307{fill:#4B82C0;} - .st308{fill:#809398;} - .st309{fill:#69BCE2;} - .st310{fill:#5BBFEB;} - .st311{fill:#5DBEF5;} - .st312{fill:#42A6D8;} - .st313{fill:#39A4DC;} - .st314{fill:#94C356;} - .st315{fill:#95C446;} - .st316{fill:#2B83B5;} - .st317{fill:#2A83B8;} - .st318{fill:#3EA7DE;} - .st319{fill:#37A8DF;} - .st320{fill:#7CC9F7;} - .st321{fill:#1568A7;} - .st322{fill:#3EA7DD;} - .st323{fill:#3AA9DA;} - .st324{fill:#55B0E2;} - .st325{fill:#5FAF60;} - .st326{fill:#16639A;} - .st327{fill:#16689E;} - .st328{fill:#419FCE;} - .st329{fill:#216186;} - .st330{fill:#21607D;} - .st331{fill:#3BA7DD;} - .st332{fill:#6E408A;} - .st333{fill:#3A3A3C;} - .st334{fill:none;} - .st335{fill:#44546A;} - .st336{fill:#E67C0C;} - .st337{fill:#922A50;} - .st338{fill:#E67C0D;} - .st339{fill:#4471CD;} - .st340{fill:#922B50;} - .st341{fill:#45556B;} - .st342{fill:#922B51;} - .st343{fill:#4571CD;} - .st344{fill:#46556B;} - .st345{fill:#45556A;} - .st346{fill:#F0B272;} - .st347{fill:#1D94D2;} - .st348{fill:#3C3F3F;} - .st349{fill:#080809;} - .st350{fill:#048DC9;} - .st351{fill:#7496A2;} - .st352{fill:#9DAAC1;} - .st353{fill:#868689;} - .st354{fill:#052C50;} - .st355{fill:#101214;} - .st356{fill:#191C1E;} - .st357{fill:#242C35;} - .st358{fill:#343C42;} - .st359{fill:#343B44;} - .st360{fill:#3D4A5B;} - .st361{fill:#73AAFE;} - .st362{fill:#4CCAFE;} - .st363{fill:#CFE1FD;} - .st364{fill:#87DCFE;} - .st365{fill:#0090CC;} - .st366{fill:#008FCC;} - .st367{fill:none;stroke:#407DCC;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;} - .st368{fill:#407DCC;} - .st369{fill:#15191E;} - .st370{fill:#10191F;} - .st371{fill:#12161B;} - .st372{fill:#0E181E;} - .st373{fill:#121D24;} - .st374{fill:#3F7BC7;} - .st375{fill:#222932;} - .st376{fill:#22404E;} - .st377{fill:#202831;} - .st378{fill:#010101;} - .st379{fill:#161A1F;} - .st380{fill:#323C47;} - .st381{fill:#303B48;} - .st382{fill:#14181B;} - .st383{fill:#353F4A;} - .st384{fill:#194691;} - .st385{fill:#164C96;} - .st386{fill:#184893;} - .st387{fill:#174A94;} - .st388{fill:#184792;} - .st389{fill:#184892;} - .st390{fill:#0090CD;} - .st391{fill:#018CCA;} - .st392{fill:#FDBB87;} - .st393{fill:#FE9545;} - .st394{fill:#FE8B00;} - .st395{fill:#DC5900;} - .st396{fill:#DE6D45;} - .st397{fill:#292925;} - .st398{fill:#63A1BF;} - .st399{fill:#61A1BF;} - .st400{fill:#8DC53F;} - .st401{fill:#8EC642;} - .st402{fill:#61853A;} - .st403{fill:#424243;} - .st404{fill:#8EC641;} - .st405{fill:#8DC640;} - .st406{fill:#414142;} - .st407{fill:#94C94C;} - .st408{fill:#4C4C4D;} - .st409{fill:#62863C;} - .st410{fill:#8DC540;} - .st411{fill:#577138;} - .st412{fill:#A2B24F;} - .st413{fill:#DCDF72;} - .st414{fill:#5E3108;} - .st415{fill:#074354;} - .st416{fill:#04C594;} - .st417{fill:#95AEB6;} - .st418{fill:#4B4B4B;} - .st419{fill:#5C5B5B;} - .st420{fill:#ABABAB;} - .st421{fill:#474646;} - .st422{fill:#454444;} - .st423{fill:#8C8C8C;} - .st424{fill:#292828;} - .st425{fill:#818181;} - .st426{fill:#C1C1C1;} - .st427{fill:#AAAAAA;} - .st428{fill:#A1A0A0;} - .st429{fill:#7A7879;} - .st430{fill:#C9C9C9;} - .st431{fill:#787878;} - .st432{fill:#474747;} - .st433{fill:#939393;} - .st434{fill:#9D9D9D;} - .st435{fill:#323131;} - .st436{fill:#646464;} - .st437{fill:#5F5F5F;} - .st438{fill:#454545;} - .st439{fill:#565555;} - .st440{fill:#504F4F;} - .st441{fill:#464646;} - .st442{fill:#807F7F;} - .st443{fill:#515050;} - .st444{fill:#444242;} - .st445{fill:#A8A8A8;} - .st446{fill:#B6B6B6;} - .st447{fill:#545454;} - .st448{fill:#6E6E6E;} - .st449{fill:#9C9C9C;} - .st450{fill:#A9A9A9;} - .st451{fill:#949494;} - .st452{fill:#353434;} - .st453{fill:#727272;} - .st454{fill:#585858;} - .st455{fill:#585757;} - .st456{fill:#7E7D7D;} - .st457{fill:#4C4B4B;} - .st458{fill:#3A3A3A;} - .st459{fill:#989898;} - .st460{fill:#484848;} - .st461{fill:#817F80;} - .st462{fill:#7A7A7A;} - .st463{fill:#5B5A5B;} - .st464{fill:#ADADAD;} - .st465{fill:#737373;} - .st466{fill:#2E2D2D;} - .st467{fill:#757575;} - .st468{fill:#5A5959;} - .st469{fill:#717171;} - .st470{fill:#595859;} - .st471{fill:#989797;} - .st472{fill:#393939;} - .st473{fill:#818080;} - .st474{fill:#929292;} - .st475{fill:#3F3F3F;} - .st476{fill:#BEBEBE;} - .st477{fill:#494949;} - .st478{fill:#494848;} - .st479{fill:#696868;} - .st480{fill:#828181;} - .st481{fill:#C8C8C8;} - .st482{fill:#616060;} - .st483{fill:#615F60;} - .st484{fill:#686767;} - .st485{fill:#7F7E7E;} - .st486{fill:#B3B3B3;} - .st487{fill:#A09F9F;} - .st488{fill:#4D4C4C;} - .st489{fill:#E2E2E2;} - .st490{fill:#D8D8D8;} - .st491{fill:#3E3E3E;} - .st492{fill:#A4A4A4;} - .st493{fill:#8B898A;} - .st494{fill:#4C4C4C;} - .st495{fill:#A3A3A3;} - .st496{fill:#333232;} - .st497{fill:#6C6B6B;} - .st498{fill:#7B7A7A;} - .st499{fill:#C0C0C0;} - .st500{fill:#313131;} - .st501{fill:#7C7B7B;} - .st502{fill:#393838;} - .st503{fill:#414141;} - .st504{fill:#676666;} - .st505{fill:#6F6E6E;} - .st506{fill:#414040;} - .st507{fill:#7F7F7F;} - .st508{fill:#4D4D4D;} - .st509{fill:#6A6969;} - .st510{fill:#6B6A6A;} - .st511{fill:#7E7E7E;} - .st512{fill:#787777;} - .st513{fill:#777777;} - .st514{fill:#D5D5D5;} - .st515{fill:#A1A1A1;} - .st516{fill:#848384;} - .st517{fill:#595959;} - .st518{fill:#575757;} - .st519{fill:#ACACAC;} - .st520{fill:#8A8889;} - .st521{fill:#CFCFCF;} - .st522{fill:#CACACA;} - .st523{fill:#8D8D8D;} - .st524{fill:none;stroke:#A3A3A3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;} - .st525{fill:#4D4C4D;} - .st526{fill:#9F9F9F;} - .st527{fill:#8B8A8A;} - .st528{fill:#BBBBBB;} - .st529{fill:#5B5A5A;} - .st530{fill:#C2C2C2;} - .st531{fill:#A6A6A6;} - .st532{fill:#B4B4B4;} - .st533{fill:#C6C6C6;} - .st534{fill:#A3A2A2;} - .st535{fill:#B7B7B7;} - .st536{fill:#828081;} - .st537{fill:#AFAFAF;} - .st538{fill:#D1D1D1;} - .st539{fill:#D3D3D3;} - .st540{fill:#CECECE;} - .st541{fill:#BABABA;} - .st542{fill:#A4A3A3;} - .st543{fill:#E0E0E0;} - .st544{fill:#D7D7D7;} - .st545{fill:#B1B1B1;} - .st546{fill:#A7A7A7;} - .st547{fill:#D2D2D2;} - .st548{fill:#151F34;} - .st549{filter:url(#Adobe_OpacityMaskFilter);} - .st550{fill:#FFFFFF;} - .st551{mask:url(#b_1_);fill:#151F34;} - .st552{fill:#348540;} - .st553{fill:#7DBC42;} -</style> -<g - id="g859" - transform="matrix(1.7707274,0,0,1.7707274,0.85183359,-43.009452)"><path - class="st548" - d="m 4.7276613,37.955902 c -0.680236,0.165912 -1.3770631,0.232276 -2.0738902,0.232276 -0.7134182,0 -1.4102454,-0.08296 -2.07389025,-0.232276 0.54750705,-0.879329 1.26092525,-1.659112 2.07389025,-2.306166 0.812965,0.647054 1.5263832,1.426837 2.0738902,2.306166 z m 6.2548527,-5.076883 c -0.862738,-0.232276 -1.7420675,-0.348414 -2.6213969,-0.331822 -2.0241169,0 -4.0150516,0.59728 -5.707346,1.725476 -1.69229445,-1.128196 -3.666638,-1.742068 -5.707346,-1.725476 -0.9125117,0 -1.7918411,0.116137 -2.6213972,0.331822 -0.3484136,0.08296 -0.6968272,0.199093 -1.0286496,0.331822 -0.016591,0.01659 -0.033182,0.03318 -0.016591,0.04977 0,0 0,0 0,0 0.1493201,0.315231 0.3152313,0.630462 0.4811425,0.929103 0.016591,0.01659 0.033182,0.01659 0.049773,0.01659 1.0120584,-0.365005 2.0738902,-0.547507 3.135722,-0.547507 1.7420678,0 3.3679978,0.481142 4.761652,1.327289 -0.87932942,0.746601 -1.64252103,1.642522 -2.2232103,2.637989 -0.31523132,0.514325 -0.5640982,1.061832 -0.7797827,1.62593 -0.4313692,1.144787 -0.6470538,2.37253 -0.6470538,3.583682 0,2.920038 1.22774303,5.558026 3.1854954,7.432823 0.1493201,0.14932 0.3152313,0.29864 0.4811426,0.431369 0.1327289,0.116138 0.2654579,0.215685 0.3981869,0.315231 0.1659112,0.132729 0.3484136,0.265458 0.5309159,0.381596 0.016591,0.01659 0.033182,0.01659 0.049773,0 C 2.8860461,51.278568 3.0519573,51.145839 3.2344597,51.01311 3.3671886,50.91356 3.4999176,50.814017 3.6326466,50.697879 3.7985578,50.56515 3.964469,50.41583 4.1137891,50.26651 c 1.9577524,-1.874797 3.1689043,-4.512785 3.1689043,-7.432823 0,-1.460019 -0.3152313,-2.903446 -0.9125117,-4.230736 C 6.3038179,38.470227 6.2374534,38.320907 6.171089,38.188178 6.0715422,37.989085 5.9554044,37.789991 5.8392665,37.607489 5.2419861,36.612021 4.4953856,35.716101 3.6160562,34.9695 c 1.4434276,-0.862738 3.0859487,-1.327289 4.761652,-1.327289 1.0618318,0 2.1402548,0.182502 3.1357218,0.547507 0.01659,0 0.03318,0 0.04977,-0.01659 0.182502,-0.29864 0.331822,-0.613871 0.481142,-0.912511 0.01659,-0.01659 0,-0.04977 -0.01659,-0.04977 0,0 0,0 0,0 -0.348414,-0.132729 -0.696827,-0.248866 -1.045241,-0.331822 z" - id="path19" - inkscape:connector-curvature="0" - style="fill:#151f34;stroke-width:0.16591121" /><path - class="st552" - d="m 6.1379067,42.850283 c 0,2.438895 -0.9456939,4.662106 -2.5052594,6.304627 -0.2820491,-0.895921 -0.4147781,-1.825024 -0.4147781,-2.754127 0,-2.438895 0.945694,-4.662105 2.5052595,-6.304626 0.2654579,0.862738 0.414778,1.791841 0.414778,2.754126" - id="path21" - inkscape:connector-curvature="0" - style="fill:#348540;stroke-width:0.16591121" /><path - class="st553" - d="m 2.1062641,46.384192 c 0,0.962285 -0.1493201,1.891388 -0.4147781,2.754127 -1.60933881,-1.708886 -2.5052594,-3.965279 -2.5052594,-6.304627 0,-0.962285 0.1493201,-1.891388 0.43136917,-2.754126 1.59274773,1.708885 2.48866833,3.965278 2.48866833,6.304626" - id="path23" - inkscape:connector-curvature="0" - style="fill:#7dbc42;stroke-width:0.16591121" /></g> -</svg> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0" y="0" viewBox="-12.06 13.62 35.251 35.399" xml:space="preserve" width="35.251" height="35.399"><defs id="defs30"><mask id="b_1_" height="71.5" width="56.2" y="41.4" x="555.7" maskUnits="userSpaceOnUse"><g id="g12" filter="url(#Adobe_OpacityMaskFilter)"><path d="M306.3 12.4H.8v120.9h611.1V12.4z" id="a_1_" fill="#fff"/></g></mask><defs id="defs9"><filter height="71.5" width="56.2" y="41.4" x="555.7" filterUnits="userSpaceOnUse" id="Adobe_OpacityMaskFilter"><feColorMatrix id="feColorMatrix6" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0" type="matrix"/></filter></defs></defs><style type="text/css" id="style2"></style><g id="g859" transform="matrix(1.77073 0 0 1.77073 .852 -43.01)" stroke-width=".166"><path d="M4.728 37.956a8.738 8.738 0 01-2.074.232c-.714 0-1.41-.083-2.074-.232a9.157 9.157 0 012.074-2.306 9.157 9.157 0 012.074 2.306zm6.255-5.077a9.394 9.394 0 00-2.622-.332c-2.024 0-4.015.597-5.707 1.726a10.127 10.127 0 00-5.708-1.726c-.912 0-1.791.116-2.621.332-.348.083-.697.2-1.029.332-.016.016-.033.033-.016.05.15.315.315.63.48.929.018.016.034.016.05.016a9.244 9.244 0 013.136-.547c1.742 0 3.368.48 4.762 1.327a10.278 10.278 0 00-2.223 2.638 10.214 10.214 0 00-1.427 5.21 10.27 10.27 0 003.186 7.433c.149.149.315.298.48.43.133.117.266.217.399.316.166.133.348.266.53.382.017.016.034.016.05 0 .183-.116.349-.25.531-.382.133-.1.266-.199.399-.315.166-.133.331-.282.48-.431a10.255 10.255 0 003.17-7.433c0-1.46-.316-2.904-.913-4.231-.066-.133-.133-.282-.199-.415a6.59 6.59 0 00-.332-.58 10.62 10.62 0 00-2.223-2.639 9.284 9.284 0 014.762-1.327c1.062 0 2.14.183 3.135.548.017 0 .034 0 .05-.017.183-.299.332-.614.481-.912.017-.017 0-.05-.016-.05a8.458 8.458 0 00-1.045-.332z" id="path19" fill="#151f34"/><path d="M6.138 42.85a9.124 9.124 0 01-2.505 6.305 9.163 9.163 0 01-.415-2.754c0-2.44.946-4.662 2.505-6.305.266.863.415 1.792.415 2.754" id="path21" fill="#348540"/><path d="M2.106 46.384c0 .962-.15 1.892-.415 2.754a9.2 9.2 0 01-2.505-6.304c0-.963.15-1.892.432-2.754a9.261 9.261 0 012.488 6.304" id="path23" fill="#7dbc42"/></g></svg> \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg index 28bbadd24c8a6..5ef8feaded689 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79.97 113.78"><defs><style>.cls-1{fill:#961d59;}.cls-1,.cls-2{fill-rule:evenodd;}.cls-2,.cls-3{fill:#d62783;}</style></defs><title>Asset 1 \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg index 863a81e0f40e7..e38616a15a11c 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/coredns.svg @@ -1 +1 @@ -CoreDNS_Colour_Icon + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg index 2512c2eb2a011..3c3ecb66d8c87 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/couchdb.svg @@ -1,86 +1 @@ - - - -image/svg+xml \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg index 45c995b19603b..a22132d415c40 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/envoyproxy.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg index e474d93359beb..396d5a67a20eb 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ibmmq.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg new file mode 100644 index 0000000000000..99964448d33c5 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/iis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg new file mode 100644 index 0000000000000..738507c5809c0 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/mssql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg new file mode 100644 index 0000000000000..b35a39498c9ec --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/munin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg index f7593c51a4c42..5a1d6e9a52f17 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/nats.svg @@ -1,102 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg index feccb88a3f34b..1a00be6ab30a2 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/openmetrics.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg index f4458439fceb4..a745cd71efafe 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/statsd.svg @@ -1,41 +1 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg new file mode 100644 index 0000000000000..06e627a7e4ba7 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/suricata.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg new file mode 100644 index 0000000000000..0aba96275e24e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/system.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg index 8ee3448f5626e..10b38261eca5e 100644 --- a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/traefik.svg @@ -1,342 +1 @@ - - - -image/svg+xml \ No newline at end of file + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg new file mode 100644 index 0000000000000..99a911e32863e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/ubiquiti.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg new file mode 100644 index 0000000000000..43818ab211ee3 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/uwsgi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg new file mode 100644 index 0000000000000..2a04026e46432 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/vsphere.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg new file mode 100644 index 0000000000000..0e346f98c7238 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zeek.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg new file mode 100644 index 0000000000000..80db65f670d1d --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/zookeeper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts index f3a37e2b7348f..7261b2ba03372 100644 --- a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts +++ b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts @@ -21,7 +21,6 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { npStart } from 'ui/new_platform'; import { SavedObjectLoader } from '../../../../../plugins/saved_objects/public'; -import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; import { createSavedSearchesLoader } from '../../../../../plugins/discover/public'; /** @@ -63,7 +62,7 @@ const services = { savedObjectManagementRegistry.register({ id: 'savedVisualizations', - service: visualizations.savedVisualizationsLoader, + service: npStart.plugins.visualizations.savedVisualizationsLoader, title: 'visualizations', }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js index fba249670ce60..9b3e2314c9f84 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js @@ -21,7 +21,7 @@ import React from 'react'; import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; import { keyCodes } from '@elastic/eui/lib/services'; -import { mockManagementPlugin } from '../../../../../../../../../../management/public/np_ready/mocks'; +import { npSetup as mockNpSetup } from '../../../../../../../../../../../ui/public/new_platform/__mocks__'; jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); @@ -29,9 +29,8 @@ jest.mock('ui/chrome', () => ({ addBasePath: () => '', })); -jest.mock('../../../../../../../../../../management/public/legacy', () => ({ - setup: mockManagementPlugin.createSetupContract(), - start: mockManagementPlugin.createStartContract(), +jest.mock('ui/new_platform', () => ({ + npSetup: mockNpSetup, })); import { Table } from '../table'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js index 5342693113bca..132fa1e691c1c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js @@ -18,7 +18,7 @@ */ import chrome from 'ui/chrome'; -import { setup as managementSetup } from '../../../../../../../../../management/public/legacy'; +import { npSetup } from 'ui/new_platform'; import React, { PureComponent, Fragment } from 'react'; import PropTypes from 'prop-types'; @@ -79,7 +79,7 @@ export class Table extends PureComponent { constructor(props) { super(props); - this.extraActions = managementSetup.savedObjects.registry.get(); + this.extraActions = npSetup.plugins.savedObjectsManagement.actionRegistry.getAll(); } onChange = ({ query, error }) => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/import_legacy_file.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/import_legacy_file.test.js deleted file mode 100644 index 57b8557fb9afe..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/import_legacy_file.test.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { importLegacyFile } from '../import_legacy_file'; - -describe('importFile', () => { - it('should import a file', async () => { - class FileReader { - readAsText(text) { - this.onload({ - target: { - result: JSON.stringify({ text }), - }, - }); - } - } - - const file = 'foo'; - - const imported = await importLegacyFile(file, FileReader); - expect(imported).toEqual({ text: file }); - }); - - it('should throw errors', async () => { - class FileReader { - readAsText() { - this.onload({ - target: { - result: 'not_parseable', - }, - }); - } - } - - const file = 'foo'; - - try { - await importLegacyFile(file, FileReader); - } catch (e) { - // There isn't a great way to handle throwing exceptions - // with async/await but this seems to work :shrug: - expect(() => { - throw e; - }).toThrow(); - } - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.test.ts similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.test.ts index 4ecc3583e76ce..76f5c6e87ec90 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/extract_export_details.test.ts +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { extractExportDetails, SavedObjectsExportResultDetails } from '../extract_export_details'; +import { extractExportDetails, SavedObjectsExportResultDetails } from './extract_export_details'; describe('extractExportDetails', () => { const objLine = (id: string, type: string) => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts similarity index 86% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts index 788a4635d8dac..d3e527b9f96b7 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts @@ -19,7 +19,11 @@ import { kfetch } from 'ui/kfetch'; -export async function fetchExportByTypeAndSearch(types, search, includeReferencesDeep = false) { +export async function fetchExportByTypeAndSearch( + types: string[], + search: string | undefined, + includeReferencesDeep: boolean = false +): Promise { return await kfetch({ method: 'POST', pathname: '/api/saved_objects/_export', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts index 2521113f53752..744f8ef38af47 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts @@ -19,7 +19,10 @@ import { kfetch } from 'ui/kfetch'; -export async function fetchExportObjects(objects, includeReferencesDeep = false) { +export async function fetchExportObjects( + objects: any[], + includeReferencesDeep: boolean = false +): Promise { return await kfetch({ method: 'POST', pathname: '/api/saved_objects/_export', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts index caf2b5f503440..24e08f0524f62 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts @@ -18,13 +18,14 @@ */ import { kfetch } from 'ui/kfetch'; +import { SavedObjectsFindOptions } from 'src/core/public'; import { keysToCamelCaseShallow } from './case_conversion'; -export async function findObjects(findOptions) { +export async function findObjects(findOptions: SavedObjectsFindOptions) { const response = await kfetch({ method: 'GET', pathname: '/api/kibana/management/saved_objects/_find', - query: findOptions, + query: findOptions as Record, }); return keysToCamelCaseShallow(response); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.ts index 5aa9601f04baa..0abfeee72915c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.ts @@ -17,6 +17,6 @@ * under the License. */ -export function getDefaultTitle(object) { +export function getDefaultTitle(object: { id: string; type: string }) { return `${object.type} [id=${object.id}]`; } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/get_relationships.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts similarity index 71% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/get_relationships.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts index 880d577a9373e..b45b51b4de293 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/get_relationships.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts @@ -17,24 +17,24 @@ * under the License. */ -import { getRelationships } from '../get_relationships'; +import { getRelationships } from './get_relationships'; describe('getRelationships', () => { it('should make an http request', async () => { - const $http = jest.fn(); + const $http = jest.fn() as any; const basePath = 'test'; - await getRelationships('dashboard', 1, ['search', 'index-pattern'], $http, basePath); + await getRelationships('dashboard', '1', ['search', 'index-pattern'], $http, basePath); expect($http.mock.calls.length).toBe(1); }); it('should handle successful responses', async () => { - const $http = jest.fn().mockImplementation(() => ({ data: [1, 2] })); + const $http = jest.fn().mockImplementation(() => ({ data: [1, 2] })) as any; const basePath = 'test'; const response = await getRelationships( 'dashboard', - 1, + '1', ['search', 'index-pattern'], $http, basePath @@ -44,23 +44,17 @@ describe('getRelationships', () => { it('should handle errors', async () => { const $http = jest.fn().mockImplementation(() => { - throw { - data: { - error: 'Test error', - statusCode: 500, - }, + const err = new Error(); + (err as any).data = { + error: 'Test error', + statusCode: 500, }; - }); + throw err; + }) as any; const basePath = 'test'; - try { - await getRelationships('dashboard', 1, ['search', 'index-pattern'], $http, basePath); - } catch (e) { - // There isn't a great way to handle throwing exceptions - // with async/await but this seems to work :shrug: - expect(() => { - throw e; - }).toThrow(); - } + await expect( + getRelationships('dashboard', '1', ['search', 'index-pattern'], $http, basePath) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"Test error"`); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts similarity index 69% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts index d5060eb2dd735..07bdf2db68fa2 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts @@ -17,9 +17,17 @@ * under the License. */ +import { IHttpService } from 'angular'; import { get } from 'lodash'; +import { SavedObjectRelation } from '../types'; -export async function getRelationships(type, id, savedObjectTypes, $http, basePath) { +export async function getRelationships( + type: string, + id: string, + savedObjectTypes: string[], + $http: IHttpService, + basePath: string +): Promise { const url = `${basePath}/api/kibana/management/saved_objects/relationships/${encodeURIComponent( type )}/${encodeURIComponent(id)}`; @@ -27,19 +35,19 @@ export async function getRelationships(type, id, savedObjectTypes, $http, basePa method: 'GET', url, params: { - savedObjectTypes: savedObjectTypes, + savedObjectTypes, }, }; try { - const response = await $http(options); - return response ? response.data : undefined; + const response = await $http(options); + return response?.data; } catch (resp) { - const respBody = get(resp, 'data', {}); + const respBody = get(resp, 'data', {}) as any; const err = new Error(respBody.message || respBody.error || `${resp.status} Response`); - err.statusCode = respBody.statusCode || resp.status; - err.body = respBody; + (err as any).statusCode = respBody.statusCode || resp.status; + (err as any).body = respBody; throw err; } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts similarity index 74% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts index 9fc531d53d378..d4dda1190bc43 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts @@ -17,10 +17,18 @@ * under the License. */ +import { IHttpService } from 'angular'; import chrome from 'ui/chrome'; const apiBase = chrome.addBasePath('/api/kibana/management/saved_objects/scroll'); -export async function getSavedObjectCounts($http, typesToInclude, searchString) { - const results = await $http.post(`${apiBase}/counts`, { typesToInclude, searchString }); +export async function getSavedObjectCounts( + $http: IHttpService, + typesToInclude: string[], + searchString: string +): Promise> { + const results = await $http.post>(`${apiBase}/counts`, { + typesToInclude, + searchString, + }); return results.data; } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.ts similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.ts index b28d254f61d0d..9b34d8d0af321 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.ts @@ -17,7 +17,7 @@ * under the License. */ -export function getSavedObjectLabel(type) { +export function getSavedObjectLabel(type: string) { switch (type) { case 'index-pattern': case 'index-patterns': diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts index a76078d7e06e7..9bd5fbeed3a4c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts @@ -19,7 +19,7 @@ import { kfetch } from 'ui/kfetch'; -export async function importFile(file, overwriteAll = false) { +export async function importFile(file: Blob, overwriteAll: boolean = false) { const formData = new FormData(); formData.append('file', file); return await kfetch({ diff --git a/src/legacy/core_plugins/visualizations/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.test.ts similarity index 57% rename from src/legacy/core_plugins/visualizations/index.ts rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.test.ts index a2779cfe4346d..b2132979d3d19 100644 --- a/src/legacy/core_plugins/visualizations/index.ts +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.test.ts @@ -17,18 +17,21 @@ * under the License. */ -import { resolve } from 'path'; -import { LegacyPluginInitializer } from '../../../../src/legacy/types'; +import { importLegacyFile } from './import_legacy_file'; -export const visualizations: LegacyPluginInitializer = kibana => - new kibana.Plugin({ - id: 'visualizations', - publicDir: resolve(__dirname, 'public'), - require: [], - uiExports: { - styleSheetPaths: resolve(__dirname, 'public/index.scss'), - }, +describe('importFile', () => { + it('should import a file with valid json format', async () => { + const file = new File([`{"text": "foo"}`], 'file.json'); + + const imported = await importLegacyFile(file); + expect(imported).toEqual({ text: 'foo' }); }); -// eslint-disable-next-line import/no-default-export -export default visualizations; + it('should throw errors when file content is not parseable', async () => { + const file = new File([`not_parseable`], 'file.json'); + + await expect(importLegacyFile(file)).rejects.toThrowErrorMatchingInlineSnapshot( + `"Unexpected token o in JSON at position 1"` + ); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.ts similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.ts index 12aaf46b29445..0d86866fa3c1b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.ts @@ -17,10 +17,11 @@ * under the License. */ -export async function importLegacyFile(file, FileReader = window.FileReader) { +export async function importLegacyFile(file: File) { return new Promise((resolve, reject) => { const fr = new FileReader(); - fr.onload = ({ target: { result } }) => { + fr.onload = event => { + const result = event.target!.result as string; try { resolve(JSON.parse(result)); } catch (e) { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/in_app_url.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts similarity index 79% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/in_app_url.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts index af2e7dcf704df..c0d6716391a1f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/in_app_url.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts @@ -17,100 +17,110 @@ * under the License. */ -import { canViewInApp } from '../in_app_url'; +import { Capabilities } from '../../../../../../../../core/public'; +import { canViewInApp } from './in_app_url'; + +const createCapabilities = (sections: Record): Capabilities => { + return { + navLinks: {}, + management: {}, + catalogue: {}, + ...sections, + }; +}; describe('canViewInApp', () => { it('should handle saved searches', () => { - let uiCapabilities = { + let uiCapabilities = createCapabilities({ discover: { show: true, }, - }; + }); expect(canViewInApp(uiCapabilities, 'search')).toEqual(true); expect(canViewInApp(uiCapabilities, 'searches')).toEqual(true); - uiCapabilities = { + uiCapabilities = createCapabilities({ discover: { show: false, }, - }; + }); expect(canViewInApp(uiCapabilities, 'search')).toEqual(false); expect(canViewInApp(uiCapabilities, 'searches')).toEqual(false); }); it('should handle visualizations', () => { - let uiCapabilities = { + let uiCapabilities = createCapabilities({ visualize: { show: true, }, - }; + }); expect(canViewInApp(uiCapabilities, 'visualization')).toEqual(true); expect(canViewInApp(uiCapabilities, 'visualizations')).toEqual(true); - uiCapabilities = { + uiCapabilities = createCapabilities({ visualize: { show: false, }, - }; + }); expect(canViewInApp(uiCapabilities, 'visualization')).toEqual(false); expect(canViewInApp(uiCapabilities, 'visualizations')).toEqual(false); }); it('should handle index patterns', () => { - let uiCapabilities = { + let uiCapabilities = createCapabilities({ management: { kibana: { index_patterns: true, }, }, - }; + }); expect(canViewInApp(uiCapabilities, 'index-pattern')).toEqual(true); expect(canViewInApp(uiCapabilities, 'index-patterns')).toEqual(true); expect(canViewInApp(uiCapabilities, 'indexPatterns')).toEqual(true); - uiCapabilities = { + uiCapabilities = createCapabilities({ management: { kibana: { index_patterns: false, }, }, - }; + }); expect(canViewInApp(uiCapabilities, 'index-pattern')).toEqual(false); expect(canViewInApp(uiCapabilities, 'index-patterns')).toEqual(false); expect(canViewInApp(uiCapabilities, 'indexPatterns')).toEqual(false); }); it('should handle dashboards', () => { - let uiCapabilities = { + let uiCapabilities = createCapabilities({ dashboard: { show: true, }, - }; + }); expect(canViewInApp(uiCapabilities, 'dashboard')).toEqual(true); expect(canViewInApp(uiCapabilities, 'dashboards')).toEqual(true); - uiCapabilities = { + uiCapabilities = createCapabilities({ dashboard: { show: false, }, - }; + }); expect(canViewInApp(uiCapabilities, 'dashboard')).toEqual(false); expect(canViewInApp(uiCapabilities, 'dashboards')).toEqual(false); }); it('should have a default case', () => { - let uiCapabilities = { + let uiCapabilities = createCapabilities({ foo: { show: true, }, - }; + }); expect(canViewInApp(uiCapabilities, 'foo')).toEqual(true); - uiCapabilities = { + uiCapabilities = createCapabilities({ foo: { show: false, }, - }; + }); expect(canViewInApp(uiCapabilities, 'foo')).toEqual(false); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.js deleted file mode 100644 index b6c8d25568446..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './fetch_export_by_type_and_search'; -export * from './fetch_export_objects'; -export * from './in_app_url'; -export * from './get_relationships'; -export * from './get_saved_object_counts'; -export * from './get_saved_object_label'; -export * from './import_file'; -export * from './import_legacy_file'; -export * from './parse_query'; -export * from './resolve_import_errors'; -export * from './resolve_saved_objects'; -export * from './log_legacy_import'; -export * from './process_import_response'; -export * from './get_default_title'; -export * from './find_objects'; -export * from './extract_export_details'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts new file mode 100644 index 0000000000000..ecdfa6549a54e --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { fetchExportByTypeAndSearch } from './fetch_export_by_type_and_search'; +export { fetchExportObjects } from './fetch_export_objects'; +export { canViewInApp } from './in_app_url'; +export { getRelationships } from './get_relationships'; +export { getSavedObjectCounts } from './get_saved_object_counts'; +export { getSavedObjectLabel } from './get_saved_object_label'; +export { importFile } from './import_file'; +export { importLegacyFile } from './import_legacy_file'; +export { parseQuery } from './parse_query'; +export { resolveImportErrors } from './resolve_import_errors'; +export { + resolveIndexPatternConflicts, + resolveSavedObjects, + resolveSavedSearches, + saveObject, + saveObjects, +} from './resolve_saved_objects'; +export { logLegacyImport } from './log_legacy_import'; +export { + processImportResponse, + ProcessedImportResponse, + FailedImport, +} from './process_import_response'; +export { getDefaultTitle } from './get_default_title'; +export { findObjects } from './find_objects'; +export { extractExportDetails, SavedObjectsExportResultDetails } from './extract_export_details'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/parse_query.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts similarity index 96% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/parse_query.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts index 1b6c8e0d49dd2..77b34eccd9c6f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/parse_query.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { parseQuery } from '../parse_query'; +import { parseQuery } from './parse_query'; describe('getQueryText', () => { it('should know how to get the text out of the AST', () => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts index 8e7419bb924de..9b33deedafd95 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts @@ -17,15 +17,15 @@ * under the License. */ -export function parseQuery(query) { - let queryText = undefined; - let visibleTypes = undefined; +export function parseQuery(query: any) { + let queryText; + let visibleTypes; if (query) { if (query.ast.getTermClauses().length) { queryText = query.ast .getTermClauses() - .map(clause => clause.value) + .map((clause: any) => clause.value) .join(' '); } if (query.ast.getFieldClauses('type')) { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/process_import_response.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.test.ts similarity index 66% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/process_import_response.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.test.ts index dc4d81dae8081..c1a153b800550 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/process_import_response.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.test.ts @@ -17,7 +17,12 @@ * under the License. */ -import { processImportResponse } from '../process_import_response'; +import { + SavedObjectsImportConflictError, + SavedObjectsImportUnknownError, + SavedObjectsImportMissingReferencesError, +} from 'src/core/public'; +import { processImportResponse } from './process_import_response'; describe('processImportResponse()', () => { test('works when no errors exist in the response', () => { @@ -36,32 +41,28 @@ describe('processImportResponse()', () => { successCount: 0, errors: [ { - obj: { - type: 'a', - id: '1', - }, + type: 'a', + id: '1', error: { type: 'conflict', - }, + } as SavedObjectsImportConflictError, }, ], }; const result = processImportResponse(response); expect(result.failedImports).toMatchInlineSnapshot(` -Array [ - Object { - "error": Object { - "type": "conflict", - }, - "obj": Object { - "obj": Object { - "id": "1", - "type": "a", - }, - }, - }, -] -`); + Array [ + Object { + "error": Object { + "type": "conflict", + }, + "obj": Object { + "id": "1", + "type": "a", + }, + }, + ] + `); }); test('unknown errors get added to failedImports', () => { @@ -70,32 +71,28 @@ Array [ successCount: 0, errors: [ { - obj: { - type: 'a', - id: '1', - }, + type: 'a', + id: '1', error: { type: 'unknown', - }, + } as SavedObjectsImportUnknownError, }, ], }; const result = processImportResponse(response); expect(result.failedImports).toMatchInlineSnapshot(` -Array [ - Object { - "error": Object { - "type": "unknown", - }, - "obj": Object { - "obj": Object { - "id": "1", - "type": "a", - }, - }, - }, -] -`); + Array [ + Object { + "error": Object { + "type": "unknown", + }, + "obj": Object { + "id": "1", + "type": "a", + }, + }, + ] + `); }); test('missing references get added to failedImports', () => { @@ -104,10 +101,8 @@ Array [ successCount: 0, errors: [ { - obj: { - type: 'a', - id: '1', - }, + type: 'a', + id: '1', error: { type: 'missing_references', references: [ @@ -116,31 +111,29 @@ Array [ id: '2', }, ], - }, + } as SavedObjectsImportMissingReferencesError, }, ], }; const result = processImportResponse(response); expect(result.failedImports).toMatchInlineSnapshot(` -Array [ - Object { - "error": Object { - "references": Array [ + Array [ Object { - "id": "2", - "type": "index-pattern", + "error": Object { + "references": Array [ + Object { + "id": "2", + "type": "index-pattern", + }, + ], + "type": "missing_references", + }, + "obj": Object { + "id": "1", + "type": "a", + }, }, - ], - "type": "missing_references", - }, - "obj": Object { - "obj": Object { - "id": "1", - "type": "a", - }, - }, - }, -] -`); + ] + `); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts index 2444d18133af4..cfb2eb29e7885 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts @@ -26,15 +26,17 @@ import { SavedObjectsImportError, } from 'src/core/public'; +export interface FailedImport { + obj: Pick; + error: + | SavedObjectsImportConflictError + | SavedObjectsImportUnsupportedTypeError + | SavedObjectsImportMissingReferencesError + | SavedObjectsImportUnknownError; +} + export interface ProcessedImportResponse { - failedImports: Array<{ - obj: Pick; - error: - | SavedObjectsImportConflictError - | SavedObjectsImportUnsupportedTypeError - | SavedObjectsImportMissingReferencesError - | SavedObjectsImportUnknownError; - }>; + failedImports: FailedImport[]; unmatchedReferences: Array<{ existingIndexPatternId: string; list: Array>; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_import_errors.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts similarity index 90% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_import_errors.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts index ecdf3d5abced6..b94b0a9d1291f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_import_errors.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts @@ -17,12 +17,16 @@ * under the License. */ -import { resolveImportErrors } from '../resolve_import_errors'; - jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); -function getFormData(form) { - const formData = {}; +import { SavedObjectsImportUnknownError } from 'src/core/public'; +import { kfetch } from 'ui/kfetch'; +import { resolveImportErrors } from './resolve_import_errors'; + +const kfetchMock = kfetch as jest.Mock; + +function getFormData(form: Map) { + const formData: Record = {}; for (const [key, val] of form.entries()) { if (key === 'retries') { formData[key] = JSON.parse(val); @@ -69,7 +73,7 @@ Object { }, error: { type: 'unknown', - }, + } as SavedObjectsImportUnknownError, }, ], }, @@ -94,8 +98,7 @@ Object { }); test('resolves conflicts', async () => { - const { kfetch } = require('ui/kfetch'); - kfetch.mockResolvedValueOnce({ + kfetchMock.mockResolvedValueOnce({ success: true, successCount: 1, }); @@ -136,7 +139,7 @@ Object { "status": "success", } `); - const formData = getFormData(kfetch.mock.calls[0][0].body); + const formData = getFormData(kfetchMock.mock.calls[0][0].body); expect(formData).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -153,8 +156,7 @@ Object { }); test('resolves missing references', async () => { - const { kfetch } = require('ui/kfetch'); - kfetch.mockResolvedValueOnce({ + kfetchMock.mockResolvedValueOnce({ success: true, successCount: 2, }); @@ -201,7 +203,7 @@ Object { "status": "success", } `); - const formData = getFormData(kfetch.mock.calls[0][0].body); + const formData = getFormData(kfetchMock.mock.calls[0][0].body); expect(formData).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -274,8 +276,7 @@ Object { }); test('handles missing references then conflicts on the same errored objects', async () => { - const { kfetch } = require('ui/kfetch'); - kfetch.mockResolvedValueOnce({ + kfetchMock.mockResolvedValueOnce({ success: false, successCount: 0, errors: [ @@ -288,7 +289,7 @@ Object { }, ], }); - kfetch.mockResolvedValueOnce({ + kfetchMock.mockResolvedValueOnce({ success: true, successCount: 1, }); @@ -333,7 +334,7 @@ Object { "status": "success", } `); - const formData1 = getFormData(kfetch.mock.calls[0][0].body); + const formData1 = getFormData(kfetchMock.mock.calls[0][0].body); expect(formData1).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -353,7 +354,7 @@ Object { ], } `); - const formData2 = getFormData(kfetch.mock.calls[1][0].body); + const formData2 = getFormData(kfetchMock.mock.calls[1][0].body); expect(formData2).toMatchInlineSnapshot(` Object { "file": "undefined", diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts similarity index 84% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts index f59e776b18046..dcc282402147d 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts @@ -18,8 +18,16 @@ */ import { kfetch } from 'ui/kfetch'; +import { FailedImport } from './process_import_response'; -async function callResolveImportErrorsApi(file, retries) { +interface RetryObject { + id: string; + type: string; + overwrite?: boolean; + replaceReferences?: any[]; +} + +async function callResolveImportErrorsApi(file: File, retries: any) { const formData = new FormData(); formData.append('file', file); formData.append('retries', JSON.stringify(retries)); @@ -39,7 +47,12 @@ function mapImportFailureToRetryObject({ overwriteDecisionCache, replaceReferencesCache, state, -}) { +}: { + failure: FailedImport; + overwriteDecisionCache: Map; + replaceReferencesCache: Map; + state: any; +}): RetryObject | undefined { const { isOverwriteAllChecked, unmatchedReferences } = state; const isOverwriteGranted = isOverwriteAllChecked || @@ -86,27 +99,32 @@ function mapImportFailureToRetryObject({ }; } -export async function resolveImportErrors({ getConflictResolutions, state }) { +export async function resolveImportErrors({ + getConflictResolutions, + state, +}: { + getConflictResolutions: (objects: any[]) => Promise>; + state: { importCount: number; failedImports?: FailedImport[] } & Record; +}) { const overwriteDecisionCache = new Map(); const replaceReferencesCache = new Map(); let { importCount: successImportCount, failedImports: importFailures = [] } = state; const { file, isOverwriteAllChecked } = state; - const doesntHaveOverwriteDecision = ({ obj }) => { + const doesntHaveOverwriteDecision = ({ obj }: FailedImport) => { return !overwriteDecisionCache.has(`${obj.type}:${obj.id}`); }; - const getOverwriteDecision = ({ obj }) => { + const getOverwriteDecision = ({ obj }: FailedImport) => { return overwriteDecisionCache.get(`${obj.type}:${obj.id}`); }; - const callMapImportFailure = failure => { - return mapImportFailureToRetryObject({ + const callMapImportFailure = (failure: FailedImport) => + mapImportFailureToRetryObject({ failure, overwriteDecisionCache, replaceReferencesCache, state, }); - }; - const isNotSkipped = failure => { + const isNotSkipped = (failure: FailedImport) => { return ( (failure.error.type !== 'conflict' && failure.error.type !== 'missing_references') || getOverwriteDecision(failure) @@ -131,7 +149,7 @@ export async function resolveImportErrors({ getConflictResolutions, state }) { } // Build retries array - const retries = importFailures.map(callMapImportFailure).filter(obj => !!obj); + const retries = importFailures.map(callMapImportFailure).filter(obj => !!obj) as RetryObject[]; for (const { error, obj } of importFailures) { if (error.type !== 'missing_references') { continue; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_saved_objects.test.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_saved_objects.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts index 96c178b35a7b3..8243aa69ac082 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/__jest__/resolve_saved_objects.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts @@ -22,21 +22,30 @@ import { resolveIndexPatternConflicts, saveObjects, saveObject, -} from '../resolve_saved_objects'; - -jest.mock('../../../../../../../../../plugins/kibana_utils/public', () => ({ - SavedObjectNotFound: class SavedObjectNotFound extends Error { - constructor(options) { - super(); - for (const option in options) { - if (options.hasOwnProperty(option)) { - this[option] = options[option]; - } +} from './resolve_saved_objects'; +import { + SavedObject, + SavedObjectLoader, +} from '../../../../../../../../plugins/saved_objects/public'; +import { IndexPatternsContract } from '../../../../../../../../plugins/data/public'; + +class SavedObjectNotFound extends Error { + constructor(options: Record) { + super(); + for (const option in options) { + if (options.hasOwnProperty(option)) { + (this as any)[option] = options[option]; } } - }, -})); -import { SavedObjectNotFound } from '../../../../../../../../../plugins/kibana_utils/public'; + } +} + +const openModalMock = jest.fn(); + +const createObj = (props: Partial): SavedObject => + ({ + ...props, + } as SavedObject); describe('resolveSavedObjects', () => { describe('resolveSavedObjects', () => { @@ -61,7 +70,7 @@ describe('resolveSavedObjects', () => { }, ]; - const indexPatterns = { + const indexPatterns = ({ get: async () => { return { create: () => '2', @@ -73,7 +82,7 @@ describe('resolveSavedObjects', () => { cache: { clear: () => {}, }, - }; + } as unknown) as IndexPatternsContract; const services = [ { @@ -115,11 +124,17 @@ describe('resolveSavedObjects', () => { }; }, }, - ]; + ] as SavedObjectLoader[]; const overwriteAll = false; - const result = await resolveSavedObjects(savedObjects, overwriteAll, services, indexPatterns); + const result = await resolveSavedObjects( + savedObjects, + overwriteAll, + services, + indexPatterns, + openModalMock + ); expect(result.conflictedIndexPatterns.length).toBe(3); expect(result.conflictedSavedObjectsLinkedToSavedSearches.length).toBe(0); @@ -147,7 +162,7 @@ describe('resolveSavedObjects', () => { }, ]; - const indexPatterns = { + const indexPatterns = ({ get: async () => { return { create: () => '2', @@ -159,7 +174,7 @@ describe('resolveSavedObjects', () => { cache: { clear: () => {}, }, - }; + } as unknown) as IndexPatternsContract; const services = [ { @@ -202,11 +217,17 @@ describe('resolveSavedObjects', () => { }; }, }, - ]; + ] as SavedObjectLoader[]; const overwriteAll = false; - const result = await resolveSavedObjects(savedObjects, overwriteAll, services, indexPatterns); + const result = await resolveSavedObjects( + savedObjects, + overwriteAll, + services, + indexPatterns, + openModalMock + ); expect(result.conflictedIndexPatterns.length).toBe(1); expect(result.conflictedSavedObjectsLinkedToSavedSearches.length).toBe(1); @@ -223,7 +244,7 @@ describe('resolveSavedObjects', () => { { obj: { searchSource: { - getOwnField: field => { + getOwnField: (field: string) => { return field === 'index' ? '1' : undefined; }, }, @@ -234,7 +255,7 @@ describe('resolveSavedObjects', () => { { obj: { searchSource: { - getOwnField: field => { + getOwnField: (field: string) => { return field === 'index' ? '3' : undefined; }, }, @@ -277,7 +298,7 @@ describe('resolveSavedObjects', () => { { obj: { searchSource: { - getOwnField: field => { + getOwnField: (field: string) => { return field === 'index' ? '1' : [{ meta: { index: 'filterIndex' } }]; }, setField: jest.fn(), @@ -289,7 +310,7 @@ describe('resolveSavedObjects', () => { { obj: { searchSource: { - getOwnField: field => { + getOwnField: (field: string) => { return field === 'index' ? '3' : undefined; }, }, @@ -330,12 +351,12 @@ describe('resolveSavedObjects', () => { const save = jest.fn(); const objs = [ - { + createObj({ save, - }, - { + }), + createObj({ save, - }, + }), ]; const overwriteAll = false; @@ -349,9 +370,9 @@ describe('resolveSavedObjects', () => { describe('saveObject', () => { it('should save the object', async () => { const save = jest.fn(); - const obj = { + const obj = createObj({ save, - }; + }); const overwriteAll = false; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts similarity index 78% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts index e13e8c1efe8f7..902de654f5f85 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts @@ -18,9 +18,17 @@ */ import { i18n } from '@kbn/i18n'; +import { OverlayStart } from 'src/core/public'; +import { + SavedObject, + SavedObjectLoader, +} from '../../../../../../../../plugins/saved_objects/public'; +import { IndexPatternsContract, IIndexPattern } from '../../../../../../../../plugins/data/public'; -async function getSavedObject(doc, services) { - const service = services.find(service => service.type === doc._type); +type SavedObjectsRawDoc = Record; + +async function getSavedObject(doc: SavedObjectsRawDoc, services: SavedObjectLoader[]) { + const service = services.find(s => s.type === doc._type); if (!service) { return; } @@ -31,7 +39,12 @@ async function getSavedObject(doc, services) { return obj; } -function addJsonFieldToIndexPattern(target, sourceString, fieldName, indexName) { +function addJsonFieldToIndexPattern( + target: Record, + sourceString: string, + fieldName: string, + indexName: string +) { if (sourceString) { try { target[fieldName] = JSON.parse(sourceString); @@ -50,7 +63,12 @@ function addJsonFieldToIndexPattern(target, sourceString, fieldName, indexName) } } } -async function importIndexPattern(doc, indexPatterns, overwriteAll, confirmModalPromise) { +async function importIndexPattern( + doc: SavedObjectsRawDoc, + indexPatterns: IndexPatternsContract, + overwriteAll: boolean, + openConfirm: OverlayStart['openConfirm'] +) { // TODO: consolidate this is the code in create_index_pattern_wizard.js const emptyPattern = await indexPatterns.make(); const { @@ -66,7 +84,7 @@ async function importIndexPattern(doc, indexPatterns, overwriteAll, confirmModal id: doc._id, title, timeFieldName, - }; + } as IIndexPattern; if (type) { importedIndexPattern.type = type; } @@ -79,9 +97,9 @@ async function importIndexPattern(doc, indexPatterns, overwriteAll, confirmModal let newId = await emptyPattern.create(overwriteAll); if (!newId) { // We can override and we want to prompt for confirmation - const isConfirmed = await confirmModalPromise( + const isConfirmed = await openConfirm( i18n.translate('kbn.management.indexPattern.confirmOverwriteLabel', { - values: { title: this.title }, + values: { title }, defaultMessage: "Are you sure you want to overwrite '{title}'?", }), { @@ -96,7 +114,7 @@ async function importIndexPattern(doc, indexPatterns, overwriteAll, confirmModal ); if (isConfirmed) { - newId = await emptyPattern.create(true); + newId = (await emptyPattern.create(true)) as string; } else { return; } @@ -105,7 +123,7 @@ async function importIndexPattern(doc, indexPatterns, overwriteAll, confirmModal return newId; } -async function importDocument(obj, doc, overwriteAll) { +async function importDocument(obj: SavedObject, doc: SavedObjectsRawDoc, overwriteAll: boolean) { await obj.applyESResp({ references: doc._references || [], ...doc, @@ -113,12 +131,12 @@ async function importDocument(obj, doc, overwriteAll) { return await obj.save({ confirmOverwrite: !overwriteAll }); } -function groupByType(docs) { +function groupByType(docs: SavedObjectsRawDoc[]): Record { const defaultDocTypes = { searches: [], indexPatterns: [], other: [], - }; + } as Record; return docs.reduce((types, doc) => { switch (doc._type) { @@ -135,14 +153,14 @@ function groupByType(docs) { }, defaultDocTypes); } -async function awaitEachItemInParallel(list, op) { +async function awaitEachItemInParallel(list: T[], op: (item: T) => R) { return await Promise.all(list.map(item => op(item))); } export async function resolveIndexPatternConflicts( - resolutions, - conflictedIndexPatterns, - overwriteAll + resolutions: Array<{ oldId: string; newId: string }>, + conflictedIndexPatterns: any[], + overwriteAll: boolean ) { let importCount = 0; @@ -160,15 +178,13 @@ export async function resolveIndexPatternConflicts( } // Resolve filter index reference: - const filter = (obj.searchSource.getOwnField('filter') || []).map(filter => { - if (!(filter.meta && filter.meta.index)) { - return filter; + const filter = (obj.searchSource.getOwnField('filter') || []).map((f: any) => { + if (!(f.meta && f.meta.index)) { + return f; } - resolution = resolutions.find(({ oldId }) => oldId === filter.meta.index); - return resolution - ? { ...filter, ...{ meta: { ...filter.meta, index: resolution.newId } } } - : filter; + resolution = resolutions.find(({ oldId }) => oldId === f.meta.index); + return resolution ? { ...f, ...{ meta: { ...f.meta, index: resolution.newId } } } : f; }); if (filter.length > 0) { @@ -186,7 +202,7 @@ export async function resolveIndexPatternConflicts( return importCount; } -export async function saveObjects(objs, overwriteAll) { +export async function saveObjects(objs: SavedObject[], overwriteAll: boolean) { let importCount = 0; await awaitEachItemInParallel(objs, async obj => { if (await saveObject(obj, overwriteAll)) { @@ -196,11 +212,16 @@ export async function saveObjects(objs, overwriteAll) { return importCount; } -export async function saveObject(obj, overwriteAll) { +export async function saveObject(obj: SavedObject, overwriteAll: boolean) { return await obj.save({ confirmOverwrite: !overwriteAll }); } -export async function resolveSavedSearches(savedSearches, services, indexPatterns, overwriteAll) { +export async function resolveSavedSearches( + savedSearches: any[], + services: SavedObjectLoader[], + indexPatterns: IndexPatternsContract, + overwriteAll: boolean +) { let importCount = 0; await awaitEachItemInParallel(savedSearches, async searchDoc => { const obj = await getSavedObject(searchDoc, services); @@ -216,18 +237,18 @@ export async function resolveSavedSearches(savedSearches, services, indexPattern } export async function resolveSavedObjects( - savedObjects, - overwriteAll, - services, - indexPatterns, - confirmModalPromise + savedObjects: SavedObjectsRawDoc[], + overwriteAll: boolean, + services: SavedObjectLoader[], + indexPatterns: IndexPatternsContract, + confirmModalPromise: OverlayStart['openConfirm'] ) { const docTypes = groupByType(savedObjects); // Keep track of how many we actually import because the user // can cancel an override let importedObjectCount = 0; - const failedImports = []; + const failedImports: any[] = []; // Start with the index patterns since everything is dependent on them await awaitEachItemInParallel(docTypes.indexPatterns, async indexPatternDoc => { try { @@ -247,18 +268,18 @@ export async function resolveSavedObjects( // We want to do the same for saved searches, but we want to keep them separate because they need // to be applied _first_ because other saved objects can be dependent on those saved searches existing - const conflictedSearchDocs = []; + const conflictedSearchDocs: any[] = []; // Keep a record of the index patterns assigned to our imported saved objects that do not // exist. We will provide a way for the user to manually select a new index pattern for those // saved objects. - const conflictedIndexPatterns = []; + const conflictedIndexPatterns: any[] = []; // Keep a record of any objects which fail to import for unknown reasons. // It's possible to have saved objects that link to saved searches which then link to index patterns // and those could error out, but the error comes as an index pattern not found error. We can't resolve // those the same as way as normal index pattern not found errors, but when those are fixed, it's very // likely that these saved objects will work once resaved so keep them around to resave them. - const conflictedSavedObjectsLinkedToSavedSearches = []; + const conflictedSavedObjectsLinkedToSavedSearches: any[] = []; await awaitEachItemInParallel(docTypes.searches, async searchDoc => { const obj = await getSavedObject(searchDoc, services); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts index 32436e96d4829..6a89142bc9798 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts +++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts @@ -17,7 +17,25 @@ * under the License. */ -import { SavedObjectReference } from 'src/core/public'; +import { SavedObject, SavedObjectReference } from 'src/core/public'; + +export interface SavedObjectMetadata { + icon?: string; + title?: string; + editUrl?: string; + inAppUrl?: { path: string; uiCapabilitiesPath: string }; +} + +export type SavedObjectWithMetadata = SavedObject & { + meta: SavedObjectMetadata; +}; + +export interface SavedObjectRelation { + id: string; + type: string; + relationship: 'child' | 'parent'; + meta: SavedObjectMetadata; +} export interface ObjectField { type: FieldType; diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts index 7e96d7bde6e13..2ed7e3d43168c 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts @@ -32,7 +32,7 @@ import { Storage } from '../../../../../plugins/kibana_utils/public'; import { EmbeddableStart } from '../../../../../plugins/embeddable/public'; import { SharePluginStart } from '../../../../../plugins/share/public'; import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plugins/data/public'; -import { VisualizationsStart } from '../../../visualizations/public'; +import { VisualizationsStart } from '../../../../../plugins/visualizations/public'; import { SavedVisualizations } from './np_ready/types'; import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; import { KibanaLegacyStart } from '../../../../../plugins/kibana_legacy/public'; @@ -45,7 +45,6 @@ export interface VisualizeKibanaServices { core: CoreStart; data: DataPublicPluginStart; embeddable: EmbeddableStart; - getBasePath: () => string; indexPatterns: IndexPatternsContract; localStorage: Storage; navigation: NavigationStart; diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts index fbbc7ab944daf..4ef2c93689714 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts @@ -19,14 +19,10 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; import { plugin } from './index'; const instance = plugin({ env: npSetup.plugins.kibanaLegacy.env, } as PluginInitializerContext); instance.setup(npSetup.core, npSetup.plugins); -instance.start(npStart.core, { - ...npStart.plugins, - visualizations, -}); +instance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index a2e2ba3543104..6a2034d9a62e4 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -24,11 +24,11 @@ * directly where they are needed. */ -export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; -export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url'; -export { wrapInI18nContext } from 'ui/i18n'; export { DashboardConstants } from '../dashboard/np_ready/dashboard_constants'; -export { VisSavedObject, VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/'; +export { + VisSavedObject, + VISUALIZE_EMBEDDABLE_TYPE, +} from '../../../../../plugins/visualizations/public/'; export { configureAppAngularModule, migrateLegacyQuery, diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index c5325ca3108b4..9ccd45dfc1b45 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -26,14 +26,14 @@ import { EventEmitter } from 'events'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { makeStateful, useVisualizeAppState } from './lib'; +import { makeStateful, useVisualizeAppState, addEmbeddableToDashboardUrl } from './lib'; import { VisualizeConstants } from '../visualize_constants'; import { getEditBreadcrumbs } from '../breadcrumbs'; import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; import { unhashUrl, removeQueryParam } from '../../../../../../../plugins/kibana_utils/public'; import { MarkdownSimple, toMountPoint } from '../../../../../../../plugins/kibana_react/public'; -import { addFatalError, kbnBaseUrl } from '../../../../../../../plugins/kibana_legacy/public'; +import { addFatalError } from '../../../../../../../plugins/kibana_legacy/public'; import { SavedObjectSaveModal, showSaveModal, @@ -46,14 +46,7 @@ import { import { initVisEditorDirective } from './visualization_editor'; import { initVisualizationDirective } from './visualization'; -import { - VISUALIZE_EMBEDDABLE_TYPE, - subscribeWithScope, - absoluteToParsedUrl, - KibanaParsedUrl, - migrateLegacyQuery, - DashboardConstants, -} from '../../legacy_imports'; +import { subscribeWithScope, migrateLegacyQuery, DashboardConstants } from '../../legacy_imports'; import { getServices } from '../../kibana_services'; @@ -79,7 +72,6 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState data: { query: queryService }, toastNotifications, chrome, - getBasePath, core: { docLinks, fatalErrors }, savedQueryService, uiSettings, @@ -653,29 +645,14 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState }); if ($scope.isAddToDashMode()) { - const savedVisualizationParsedUrl = new KibanaParsedUrl({ - basePath: getBasePath(), - appId: kbnBaseUrl.slice('/app/'.length), - appPath: `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`, - }); + const appPath = `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`; // Manually insert a new url so the back button will open the saved visualization. - history.replace(savedVisualizationParsedUrl.appPath); - setActiveUrl(savedVisualizationParsedUrl.appPath); + history.replace(appPath); + setActiveUrl(appPath); - const lastDashboardAbsoluteUrl = chrome.navLinks.get('kibana:dashboard').url; - const dashboardParsedUrl = absoluteToParsedUrl( - lastDashboardAbsoluteUrl, - getBasePath() - ); - dashboardParsedUrl.addQueryParameter( - DashboardConstants.ADD_EMBEDDABLE_TYPE, - VISUALIZE_EMBEDDABLE_TYPE - ); - dashboardParsedUrl.addQueryParameter( - DashboardConstants.ADD_EMBEDDABLE_ID, - savedVis.id - ); - history.push(dashboardParsedUrl.appPath); + const lastDashboardUrl = chrome.navLinks.get('kibana:dashboard').url; + const dashboardUrl = addEmbeddableToDashboardUrl(lastDashboardUrl, savedVis.id); + history.push(dashboardUrl); } else if (savedVis.id === $route.current.params.id) { chrome.docTitle.change(savedVis.lastSavedTitle); chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs)); diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts index fa5b91b00edaf..6e2f759c73f2f 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts @@ -19,3 +19,4 @@ export { useVisualizeAppState } from './visualize_app_state'; export { makeStateful } from './make_stateful'; +export { addEmbeddableToDashboardUrl } from './url_helper'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.test.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.test.ts new file mode 100644 index 0000000000000..e6974af9af832 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.test.ts @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { addEmbeddableToDashboardUrl } from './url_helper'; + +jest.mock('../../../legacy_imports', () => ({ + DashboardConstants: { + ADD_EMBEDDABLE_ID: 'addEmbeddableId', + ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', + CREATE_NEW_DASHBOARD_URL: '/dashboard', + }, + VISUALIZE_EMBEDDABLE_TYPE: 'visualization', +})); + +describe('', () => { + it('addEmbeddableToDashboardUrl when dashboard is not saved', () => { + const id = '123eb456cd'; + const url = + "/pep/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!())"; + expect(addEmbeddableToDashboardUrl(url, id)).toEqual( + `/dashboard?_a=%28description%3A%27%27%2Cfilters%3A%21%28%29%29&_g=%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29&addEmbeddableId=${id}&addEmbeddableType=visualization` + ); + }); + it('addEmbeddableToDashboardUrl when dashboard is saved', () => { + const id = '123eb456cd'; + const url = + "/pep/app/kibana#/dashboard/9b780cd0-3dd3-11e8-b2b9-5d5dc1715159?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!())"; + expect(addEmbeddableToDashboardUrl(url, id)).toEqual( + `/dashboard/9b780cd0-3dd3-11e8-b2b9-5d5dc1715159?_a=%28description%3A%27%27%2Cfilters%3A%21%28%29%29&_g=%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29&addEmbeddableId=${id}&addEmbeddableType=visualization` + ); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.ts new file mode 100644 index 0000000000000..c7937c856184a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/url_helper.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { parseUrl, stringify } from 'query-string'; +import { DashboardConstants, VISUALIZE_EMBEDDABLE_TYPE } from '../../../legacy_imports'; + +/** * + * Returns relative dashboard URL with added embeddableType and embeddableId query params + * eg. + * input: url: lol/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)), embeddableId: 12345 + * output: /dashboard?addEmbeddableType=visualization&addEmbeddableId=12345&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)) + * @param url dasbhoard absolute url + * @param embeddableId id of the saved visualization + */ +export function addEmbeddableToDashboardUrl(dashboardUrl: string, embeddableId: string) { + const { url, query } = parseUrl(dashboardUrl); + const [, dashboardId] = url.split(DashboardConstants.CREATE_NEW_DASHBOARD_URL); + + query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = VISUALIZE_EMBEDDABLE_TYPE; + query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + + return `${DashboardConstants.CREATE_NEW_DASHBOARD_URL}${dashboardId}?${stringify(query)}`; +} diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js index b0b1ae31a02a5..d1bf4411cac2a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js @@ -204,6 +204,9 @@ export function initVisualizeApp(app, deps) { '/management/kibana/objects/savedVisualizations/' + $route.current.params.id, }, toastNotifications, + onBeforeRedirect() { + deps.setActiveUrl(VisualizeConstants.LANDING_PAGE_PATH); + }, }) ); }, diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js index 6c02afb672e4c..098633d046062 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js @@ -18,19 +18,17 @@ */ import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; -import { VisualizeListingTable } from './visualize_listing_table'; +import { withI18nContext } from './visualize_listing_table'; import { VisualizeConstants } from '../visualize_constants'; import { i18n } from '@kbn/i18n'; import { getServices } from '../../kibana_services'; -import { wrapInI18nContext } from '../../legacy_imports'; - import { syncQueryStateWithUrl } from '../../../../../../../plugins/data/public'; -export function initListingDirective(app) { +export function initListingDirective(app, I18nContext) { app.directive('visualizeListingTable', reactDirective => - reactDirective(wrapInI18nContext(VisualizeListingTable)) + reactDirective(withI18nContext(I18nContext)) ); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing_table.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing_table.js index b770625cd3d70..932ac8996e97e 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing_table.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing_table.js @@ -230,4 +230,10 @@ VisualizeListingTable.propTypes = { listingLimit: PropTypes.number.isRequired, }; -export { VisualizeListingTable }; +const withI18nContext = I18nContext => props => ( + + + +); + +export { withI18nContext }; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts index 246a031f05769..e376b4f2bbacf 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts @@ -27,9 +27,8 @@ import { import { EmbeddableStart } from 'src/plugins/embeddable/public'; import { PersistedState } from 'src/plugins/visualizations/public'; import { LegacyCoreStart } from 'kibana/public'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; import { VisSavedObject } from '../legacy_imports'; -import { SavedVisState } from '../../../../visualizations/public/np_ready/public/types'; +import { SavedVisState } from '../../../../../../plugins/visualizations/public'; import { SavedSearch } from '../../../../../../plugins/discover/public'; export type PureVisState = SavedVisState; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/visualize_app.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/visualize_app.ts index 1e7ac668697de..a4afac23f4842 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/visualize_app.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/visualize_app.ts @@ -27,5 +27,5 @@ import { initListingDirective } from './listing/visualize_listing'; export function initVisualizeAppDirective(app: IModule, deps: VisualizeKibanaServices) { initEditorDirective(app, deps); - initListingDirective(app); + initListingDirective(app, deps.core.i18n.Context); } diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts index 9d88152c59aa7..6d32579f5c541 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts @@ -43,7 +43,7 @@ import { KibanaLegacySetup, AngularRenderedAppUpdater, } from '../../../../../plugins/kibana_legacy/public'; -import { VisualizationsStart } from '../../../visualizations/public'; +import { VisualizationsStart } from '../../../../../plugins/visualizations/public'; import { VisualizeConstants } from './np_ready/visualize_constants'; import { setServices, VisualizeKibanaServices } from './kibana_services'; import { @@ -140,7 +140,6 @@ export class VisualizePlugin implements Plugin { chrome: coreStart.chrome, data: dataStart, embeddable, - getBasePath: core.http.basePath.get, indexPatterns: dataStart.indexPatterns, localStorage: new Storage(localStorage), navigation, diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/index.js b/src/legacy/core_plugins/kibana/server/routes/api/management/index.js deleted file mode 100644 index b98ce360f57d3..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/management/index.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { registerFind } from './saved_objects/find'; -import { registerRelationships } from './saved_objects/relationships'; -import { registerScrollForExportRoute, registerScrollForCountRoute } from './saved_objects/scroll'; - -export function managementApi(server) { - registerRelationships(server); - registerFind(server); - registerScrollForExportRoute(server); - registerScrollForCountRoute(server); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/find.js b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/find.js deleted file mode 100644 index 920b5c43678d1..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/find.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * This file wraps the saved object `_find` API and is designed specifically for the saved object - * management UI. The main difference is this will inject a root `meta` attribute on each saved object - * that the UI depends on. The meta fields come from functions within uiExports which can't be - * injected into the front end when defined within uiExports. There are alternatives to this but have - * decided to go with this approach at the time of development. - */ - -import Joi from 'joi'; -import { injectMetaAttributes } from '../../../../lib/management/saved_objects/inject_meta_attributes'; - -export function registerFind(server) { - server.route({ - path: '/api/kibana/management/saved_objects/_find', - method: 'GET', - config: { - validate: { - query: Joi.object() - .keys({ - perPage: Joi.number() - .min(0) - .default(20), - page: Joi.number() - .min(0) - .default(1), - type: Joi.array() - .items(Joi.string()) - .single() - .required(), - search: Joi.string() - .allow('') - .optional(), - defaultSearchOperator: Joi.string() - .valid('OR', 'AND') - .default('OR'), - sortField: Joi.string(), - hasReference: Joi.object() - .keys({ - type: Joi.string().required(), - id: Joi.string().required(), - }) - .optional(), - fields: Joi.array() - .items(Joi.string()) - .single(), - }) - .default(), - }, - }, - async handler(request) { - const searchFields = new Set(); - const searchTypes = request.query.type; - const savedObjectsClient = request.getSavedObjectsClient(); - const savedObjectsManagement = server.getSavedObjectsManagement(); - const importAndExportableTypes = searchTypes.filter(type => - savedObjectsManagement.isImportAndExportable(type) - ); - - // Accumulate "defaultSearchField" attributes from savedObjectsManagement. Unfortunately - // search fields apply to all types of saved objects, the sum of these fields will - // be searched on for each object. - for (const type of importAndExportableTypes) { - const searchField = savedObjectsManagement.getDefaultSearchField(type); - if (searchField) { - searchFields.add(searchField); - } - } - - const findResponse = await savedObjectsClient.find({ - ...request.query, - fields: undefined, - searchFields: [...searchFields], - }); - return { - ...findResponse, - saved_objects: findResponse.saved_objects - .map(obj => injectMetaAttributes(obj, savedObjectsManagement)) - .map(obj => { - const result = { ...obj, attributes: {} }; - for (const field of request.query.fields || []) { - result.attributes[field] = obj.attributes[field]; - } - return result; - }), - }; - }, - }); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js deleted file mode 100644 index eb6a7fc7b5195..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; -import { findRelationships } from '../../../../lib/management/saved_objects/relationships'; - -export function registerRelationships(server) { - server.route({ - path: '/api/kibana/management/saved_objects/relationships/{type}/{id}', - method: ['GET'], - config: { - validate: { - params: Joi.object().keys({ - type: Joi.string(), - id: Joi.string(), - }), - query: Joi.object().keys({ - size: Joi.number().default(10000), - savedObjectTypes: Joi.array() - .single() - .items(Joi.string()) - .required(), - }), - }, - }, - - handler: async req => { - const type = req.params.type; - const id = req.params.id; - const size = req.query.size; - const savedObjectTypes = req.query.savedObjectTypes; - const savedObjectsClient = req.getSavedObjectsClient(); - const savedObjectsManagement = req.server.getSavedObjectsManagement(); - - return await findRelationships(type, id, { - size, - savedObjectsClient, - savedObjectsManagement, - savedObjectTypes, - }); - }, - }); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js deleted file mode 100644 index b3edd42149d45..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; - -async function findAll(savedObjectsClient, findOptions, page = 1, allObjects = []) { - const objects = await savedObjectsClient.find({ - ...findOptions, - page, - }); - - allObjects.push(...objects.saved_objects); - if (allObjects.length < objects.total) { - return findAll(savedObjectsClient, findOptions, page + 1, allObjects); - } - - return allObjects; -} - -export function registerScrollForExportRoute(server) { - server.route({ - path: '/api/kibana/management/saved_objects/scroll/export', - method: ['POST'], - config: { - validate: { - payload: Joi.object() - .keys({ - typesToInclude: Joi.array() - .items(Joi.string()) - .required(), - }) - .required(), - }, - }, - - handler: async req => { - const savedObjectsClient = req.getSavedObjectsClient(); - const objects = await findAll(savedObjectsClient, { - perPage: 1000, - type: req.payload.typesToInclude, - }); - - return objects.map(hit => { - return { - _id: hit.id, - _source: hit.attributes, - _meta: { - savedObjectVersion: 2, - }, - _migrationVersion: hit.migrationVersion, - _references: hit.references || [], - }; - }); - }, - }); -} - -export function registerScrollForCountRoute(server) { - server.route({ - path: '/api/kibana/management/saved_objects/scroll/counts', - method: ['POST'], - config: { - validate: { - payload: Joi.object() - .keys({ - typesToInclude: Joi.array() - .items(Joi.string()) - .required(), - searchString: Joi.string(), - }) - .required(), - }, - }, - - handler: async req => { - const savedObjectsClient = req.getSavedObjectsClient(); - const findOptions = { - type: req.payload.typesToInclude, - perPage: 1000, - }; - - if (req.payload.searchString) { - findOptions.search = `${req.payload.searchString}*`; - findOptions.searchFields = ['title']; - } - - const objects = await findAll(savedObjectsClient, findOptions); - const counts = objects.reduce((accum, result) => { - const type = result.type; - accum[type] = accum[type] || 0; - accum[type]++; - return accum; - }, {}); - - for (const type of req.payload.typesToInclude) { - if (!counts[type]) { - counts[type] = 0; - } - } - - return counts; - }, - }); -} diff --git a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js b/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js deleted file mode 100644 index 0d14da39d73b3..0000000000000 --- a/src/legacy/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.test.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import Hapi from 'hapi'; -import { registerScrollForExportRoute } from './scroll'; - -const createMockServer = () => { - const mockServer = new Hapi.Server({ - debug: false, - port: 8080, - routes: { - validate: { - failAction: (r, h, err) => { - throw err; - }, - }, - }, - }); - return mockServer; -}; - -describe(`POST /api/kibana/management/saved_objects/scroll/export`, () => { - test('requires "typesToInclude"', async () => { - const mockServer = createMockServer(); - registerScrollForExportRoute(mockServer); - - const headers = {}; - const payload = {}; - - const request = { - method: 'POST', - url: `/api/kibana/management/saved_objects/scroll/export`, - headers, - payload, - }; - - const { result, statusCode } = await mockServer.inject(request); - expect(statusCode).toEqual(400); - expect(result).toMatchObject({ - message: `child "typesToInclude" fails because ["typesToInclude" is required]`, - }); - }); - - test(`uses "typesToInclude" when searching for objects to export`, async () => { - const mockServer = createMockServer(); - const mockClient = { - find: jest.fn(() => { - return { - saved_objects: [], - }; - }), - }; - - mockServer.decorate('request', 'getSavedObjectsClient', () => mockClient); - - registerScrollForExportRoute(mockServer); - - const headers = {}; - const payload = { - typesToInclude: ['foo', 'bar'], - }; - - const request = { - method: 'POST', - url: `/api/kibana/management/saved_objects/scroll/export`, - headers, - payload, - }; - - const { result, statusCode } = await mockServer.inject(request); - expect(statusCode).toEqual(200); - expect(result).toEqual([]); - - expect(mockClient.find).toHaveBeenCalledWith({ - page: 1, - perPage: 1000, - type: ['foo', 'bar'], - }); - }); -}); diff --git a/src/legacy/core_plugins/management/public/index.ts b/src/legacy/core_plugins/management/public/index.ts index 3d64b6d2aa2bb..bc3737524e125 100644 --- a/src/legacy/core_plugins/management/public/index.ts +++ b/src/legacy/core_plugins/management/public/index.ts @@ -30,8 +30,6 @@ export { plugin, IndexPatternCreationConfig, IndexPatternListConfig, - SavedObjectsManagementAction, - SavedObjectsManagementRecord, } from './np_ready'; export { diff --git a/src/legacy/core_plugins/management/public/legacy.ts b/src/legacy/core_plugins/management/public/legacy.ts index 4481bad79c47d..96d2c74398a0e 100644 --- a/src/legacy/core_plugins/management/public/legacy.ts +++ b/src/legacy/core_plugins/management/public/legacy.ts @@ -29,7 +29,7 @@ * simply delete this shim file. * * We are also calling `setup/start` here and exporting our public contract so that - * other legacy plugins are able to import from '../core_plugins/visualizations/legacy' + * other legacy plugins are able to import from '../core_plugins/management/legacy' * and receive the response value of the `setup/start` contract, mimicking the * data that will eventually be injected by the new platform. */ diff --git a/src/legacy/core_plugins/management/public/np_ready/index.ts b/src/legacy/core_plugins/management/public/np_ready/index.ts index ec93516df8349..bae0f1d3e23cd 100644 --- a/src/legacy/core_plugins/management/public/np_ready/index.ts +++ b/src/legacy/core_plugins/management/public/np_ready/index.ts @@ -40,8 +40,3 @@ export { IndexPatternCreationConfig, IndexPatternListConfig, } from './services/index_pattern_management'; - -export { - SavedObjectsManagementAction, - SavedObjectsManagementRecord, -} from './services/saved_objects_management'; diff --git a/src/legacy/core_plugins/management/public/np_ready/mocks.ts b/src/legacy/core_plugins/management/public/np_ready/mocks.ts index 5ed7c045d1f64..ae0be98de63f3 100644 --- a/src/legacy/core_plugins/management/public/np_ready/mocks.ts +++ b/src/legacy/core_plugins/management/public/np_ready/mocks.ts @@ -40,13 +40,6 @@ const createSetupContract = (): ManagementSetup => ({ areScriptedFieldsEnabled: jest.fn(), } as any, }, - savedObjects: { - registry: { - register: jest.fn(), - has: jest.fn(), - get: jest.fn(() => []), - }, - }, }); const createStartContract = (): ManagementStart => ({}); diff --git a/src/legacy/core_plugins/management/public/np_ready/plugin.ts b/src/legacy/core_plugins/management/public/np_ready/plugin.ts index 7dd2b23d40610..2a8ef10c817cc 100644 --- a/src/legacy/core_plugins/management/public/np_ready/plugin.ts +++ b/src/legacy/core_plugins/management/public/np_ready/plugin.ts @@ -19,10 +19,6 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { HomePublicPluginSetup } from 'src/plugins/home/public'; import { IndexPatternManagementService, IndexPatternManagementSetup } from './services'; -import { - SavedObjectsManagementService, - SavedObjectsManagementServiceSetup, -} from './services/saved_objects_management'; export interface ManagementPluginSetupDependencies { home: HomePublicPluginSetup; @@ -33,7 +29,6 @@ interface ManagementPluginStartDependencies {} export interface ManagementSetup { indexPattern: IndexPatternManagementSetup; - savedObjects: SavedObjectsManagementServiceSetup; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -48,14 +43,12 @@ export class ManagementPlugin ManagementPluginStartDependencies > { private readonly indexPattern = new IndexPatternManagementService(); - private readonly savedObjects = new SavedObjectsManagementService(); constructor(initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup, { home }: ManagementPluginSetupDependencies) { return { indexPattern: this.indexPattern.setup({ httpClient: core.http, home }), - savedObjects: this.savedObjects.setup({ home }), }; } diff --git a/src/legacy/core_plugins/management/public/np_ready/services/index.ts b/src/legacy/core_plugins/management/public/np_ready/services/index.ts index 4d55fce3d8a7d..9df010223542b 100644 --- a/src/legacy/core_plugins/management/public/np_ready/services/index.ts +++ b/src/legacy/core_plugins/management/public/np_ready/services/index.ts @@ -18,4 +18,3 @@ */ export * from './index_pattern_management'; -export * from './saved_objects_management'; diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.test.ts b/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.test.ts deleted file mode 100644 index 902b7f01c19f4..0000000000000 --- a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SavedObjectsManagementActionRegistry } from './saved_objects_management_action_registry'; -import { SavedObjectsManagementAction } from './saved_objects_management_action'; - -describe('SavedObjectsManagementActionRegistry', () => { - it('allows actions to be registered and retrieved', () => { - const action = { id: 'foo' } as SavedObjectsManagementAction; - SavedObjectsManagementActionRegistry.register(action); - expect(SavedObjectsManagementActionRegistry.get()).toContain(action); - }); - - it('requires an "id" property', () => { - expect(() => - SavedObjectsManagementActionRegistry.register({} as SavedObjectsManagementAction) - ).toThrowErrorMatchingInlineSnapshot(`"Saved Objects Management Actions must have an id"`); - }); - - it('does not allow actions with duplicate ids to be registered', () => { - const action = { id: 'my-action' } as SavedObjectsManagementAction; - SavedObjectsManagementActionRegistry.register(action); - expect(() => - SavedObjectsManagementActionRegistry.register(action) - ).toThrowErrorMatchingInlineSnapshot( - `"Saved Objects Management Action with id 'my-action' already exists"` - ); - }); - - it('#has returns true when an action with a matching ID exists', () => { - const action = { id: 'existing-action' } as SavedObjectsManagementAction; - SavedObjectsManagementActionRegistry.register(action); - expect(SavedObjectsManagementActionRegistry.has('existing-action')).toEqual(true); - }); - - it(`#has returns false when an action with doesn't exist`, () => { - expect(SavedObjectsManagementActionRegistry.has('missing-action')).toEqual(false); - }); -}); diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 23ca99791e92e..3880f42d52561 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -37,11 +37,13 @@ import afterdatachangePng from './afterdatachange.png'; import afterdatachangeandresizePng from './afterdatachangeandresize.png'; import aftercolorchangePng from './aftercolorchange.png'; import changestartupPng from './changestartup.png'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createRegionMapVisualization } from '../region_map_visualization'; import { createRegionMapTypeDefinition } from '../region_map_type'; -import { ExprVis } from '../../../visualizations/public/np_ready/public/expressions/vis'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; const THRESHOLD = 0.45; const PIXEL_DIFF = 96; @@ -50,6 +52,7 @@ describe('RegionMapsVisualizationTests', function() { let domNode; let RegionMapsVisualization; let vis; + let regionMapVisType; let dependencies; let imageComparator; @@ -84,8 +87,6 @@ describe('RegionMapsVisualizationTests', function() { ], }; - let visRegComplete = false; - beforeEach(ngMock.module('kibana')); let getManifestStub; @@ -105,11 +106,7 @@ describe('RegionMapsVisualizationTests', function() { uiSettings, }; - if (!visRegComplete) { - visRegComplete = true; - visualizationsSetup.createBaseVisualization(createRegionMapTypeDefinition(dependencies)); - } - + regionMapVisType = new BaseVisType(createRegionMapTypeDefinition(dependencies)); RegionMapsVisualization = createRegionMapVisualization(dependencies); ChoroplethLayer.prototype._makeJsonAjaxCall = async function() { @@ -154,7 +151,7 @@ describe('RegionMapsVisualizationTests', function() { imageComparator = new ImageComparator(); vis = new ExprVis({ - type: 'region_map', + type: regionMapVisType, }); vis.params.bucket = { diff --git a/src/legacy/core_plugins/region_map/public/legacy.ts b/src/legacy/core_plugins/region_map/public/legacy.ts index 495e558e29dd7..08615946affa2 100644 --- a/src/legacy/core_plugins/region_map/public/legacy.ts +++ b/src/legacy/core_plugins/region_map/public/legacy.ts @@ -20,7 +20,6 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { RegionMapPluginSetupDependencies, RegionMapsConfig } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; @@ -31,7 +30,7 @@ const regionmapsConfig = npSetup.core.injectedMetadata.getInjectedVar( const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index 98fb5604c3d65..cae569f8fd26d 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -24,7 +24,7 @@ import { IUiSettingsClient, } from '../../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim'; diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index 3b8a7dfbed313..2c142b19d9096 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -31,11 +31,13 @@ import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_ import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; import { createTileMapVisualization } from '../tile_map_visualization'; import { createTileMapTypeDefinition } from '../tile_map_type'; -import { ExprVis } from '../../../visualizations/public/np_ready/public/expressions/vis'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; function mockRawData() { const stack = [dummyESResponse]; @@ -59,13 +61,13 @@ mockRawData(); const THRESHOLD = 0.45; const PIXEL_DIFF = 64; -let visRegComplete = false; describe('CoordinateMapsVisualizationTest', function() { let domNode; let CoordinateMapsVisualization; let vis; let dependencies; + let visType; let imageComparator; @@ -82,10 +84,7 @@ describe('CoordinateMapsVisualizationTest', function() { $injector, }; - if (!visRegComplete) { - visRegComplete = true; - visualizationsSetup.createBaseVisualization(createTileMapTypeDefinition(dependencies)); - } + visType = new BaseVisType(createTileMapTypeDefinition(dependencies)); CoordinateMapsVisualization = createTileMapVisualization(dependencies); @@ -120,7 +119,7 @@ describe('CoordinateMapsVisualizationTest', function() { imageComparator = new ImageComparator(); vis = new ExprVis({ - type: 'tile_map', + type: visType, }); vis.params = { mapType: 'Scaled Circle Markers', diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx index 204ad5efa9b40..27127b781cd4d 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { TmsLayer } from 'ui/vis/map/service_settings'; -import { Vis } from '../../../visualizations/public'; +import { Vis } from '../../../../../plugins/visualizations/public'; import { RegionMapVisParams } from '../../../region_map/public/types'; import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; import { WmsInternalOptions } from './wms_internal_options'; diff --git a/src/legacy/core_plugins/tile_map/public/legacy.ts b/src/legacy/core_plugins/tile_map/public/legacy.ts index 74be8482bfd30..7b1f916076f61 100644 --- a/src/legacy/core_plugins/tile_map/public/legacy.ts +++ b/src/legacy/core_plugins/tile_map/public/legacy.ts @@ -20,14 +20,13 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { TileMapPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index a12c2753cc525..f2addbe3ab872 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -24,7 +24,7 @@ import { IUiSettingsClient, } from '../../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim'; diff --git a/src/legacy/core_plugins/timelion/public/app.js b/src/legacy/core_plugins/timelion/public/app.js index a50f8a2cd3e8d..c15318d29e761 100644 --- a/src/legacy/core_plugins/timelion/public/app.js +++ b/src/legacy/core_plugins/timelion/public/app.js @@ -41,7 +41,6 @@ import './directives/saved_object_save_as_checkbox'; import './services/saved_sheet_register'; import rootTemplate from 'plugins/timelion/index.html'; -import { start as visualizations } from '../../visualizations/public/np_ready/public/legacy'; import { loadKbnTopNavDirectives } from '../../../../plugins/kibana_legacy/public'; loadKbnTopNavDirectives(npStart.plugins.navigation.ui); @@ -125,7 +124,7 @@ app.controller('timelion', function( timefilter.enableAutoRefreshSelector(); timefilter.enableTimeRangeSelector(); - const savedVisualizations = visualizations.savedVisualizationsLoader; + const savedVisualizations = npStart.plugins.visualizations.savedVisualizationsLoader; const timezone = getTimezone(config); const defaultExpression = '.es(*)'; diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/agg_common_props.ts b/src/legacy/core_plugins/vis_default_editor/public/components/agg_common_props.ts index 3aae10879138a..0c130a96230b4 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/agg_common_props.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/components/agg_common_props.ts @@ -17,7 +17,7 @@ * under the License. */ -import { VisParams } from 'src/legacy/core_plugins/visualizations/public'; +import { VisParams } from 'src/plugins/visualizations/public'; import { IAggType, IAggConfig, IAggGroupNames } from 'src/plugins/data/public'; import { Schema } from '../schemas'; import { EditorVisState } from './sidebar/state/reducers'; diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/controls/agg_control_props.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/controls/agg_control_props.tsx index 98540d3414f2d..329704ca106db 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/controls/agg_control_props.tsx +++ b/src/legacy/core_plugins/vis_default_editor/public/components/controls/agg_control_props.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { VisParams } from 'src/legacy/core_plugins/visualizations/public'; +import { VisParams } from 'src/plugins/visualizations/public'; import { IAggConfig } from 'src/plugins/data/public'; import { DefaultEditorAggCommonProps } from '../agg_common_props'; diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/controls/field.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/controls/field.tsx index 59642ae4c25f7..fc1cbb51b70a7 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/controls/field.tsx +++ b/src/legacy/core_plugins/vis_default_editor/public/components/controls/field.tsx @@ -80,6 +80,8 @@ function FieldParamEditor({ } const isValid = !!value && !errors.length && !isDirty; + // we show an error message right away if there is no compatible fields + const showErrorMessage = (showValidation || !indexedFields.length) && !isValid; useValidation(setValidity, isValid); @@ -103,7 +105,7 @@ function FieldParamEditor({ return ( ); - const errors = []; - - if (!isValid && value) { - errors.push( - i18n.translate('visDefaultEditor.controls.timeInterval.invalidFormatErrorMessage', { - defaultMessage: 'Invalid interval format.', - }) - ); - } - - const onCustomInterval = (customValue: string) => { - const normalizedCustomValue = customValue.trim(); - setValue(normalizedCustomValue); - - if (normalizedCustomValue && search.aggs.isValidInterval(normalizedCustomValue, timeBase)) { - agg.write(); - } - }; + const onCustomInterval = (customValue: string) => setValue(customValue.trim()); const onChange = (opts: EuiComboBoxOptionOption[]) => { const selectedOpt: ComboBoxOption = get(opts, '0'); setValue(selectedOpt ? selectedOpt.key : ''); - - if (selectedOpt) { - agg.write(); - } }; useEffect(() => { @@ -121,10 +166,10 @@ function TimeIntervalParamEditor({ return ( + - , + , this.el ); } diff --git a/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx b/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx index 3239e871a2465..a9b20ec0f00da 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx +++ b/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx @@ -17,9 +17,8 @@ * under the License. */ -import { PersistedState } from 'src/plugins/visualizations/public'; +import { Vis, PersistedState } from 'src/plugins/visualizations/public'; import { IAggConfigs } from 'src/plugins/data/public'; -import { Vis } from '../../visualizations/public'; export interface VisOptionsProps { aggs: IAggConfigs; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts index d4a5290df865c..1cfc583f6e005 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/legacy.ts @@ -19,14 +19,12 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MarkdownPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts b/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts index 71d6c1c69ef2d..0445d270c9330 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_markdown/public/plugin.ts @@ -19,7 +19,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { markdownVisDefinition } from './markdown_vis'; import { createMarkdownVisFn } from './markdown_fn'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap b/src/legacy/core_plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap index d84424cc6179a..47ca3f1e0465e 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap +++ b/src/legacy/core_plugins/vis_type_metric/public/components/__snapshots__/metric_vis_component.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`MetricVisComponent should render correct structure for single metric 1`] = ` +exports[`MetricVisComponent should render correct structure for multi-value metrics 1`] = `
@@ -10,45 +10,45 @@ exports[`MetricVisComponent should render correct structure for single metric 1` Object { "bgColor": undefined, "color": undefined, - "label": "Count", + "label": "1st percentile of bytes", "lightText": false, "rowIndex": 0, - "value": "4301021", + "value": 182, } } showLabel={true} /> -
-`; - -exports[`MetricVisComponent should render correct structure for multi-value metrics 1`] = ` -
182", + "value": 445842.4634666484, } } showLabel={true} /> +
+`; + +exports[`MetricVisComponent should render correct structure for single metric 1`] = ` +
445842.4634666484", + "value": 4301021, } } showLabel={true} diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx index 7ba4fe017522d..2bd423656b0f0 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.test.tsx @@ -21,13 +21,17 @@ import React from 'react'; import { shallow } from 'enzyme'; import { MetricVisComponent, MetricVisComponentProps } from './metric_vis_component'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { npStart } from 'ui/new_platform'; -import { fieldFormats } from '../../../../../plugins/data/public'; -import { identity } from 'lodash'; -import { ExprVis } from '../../../visualizations/public/np_ready/public/expressions/vis'; +import { ExprVis } from '../../../../../plugins/visualizations/public'; -jest.mock('ui/new_platform'); +jest.mock('../services', () => ({ + getFormatService: () => ({ + deserialize: () => { + return { + convert: (x: unknown) => x, + }; + }, + }), +})); type Props = MetricVisComponentProps; @@ -66,12 +70,6 @@ describe('MetricVisComponent', function() { return shallow(); }; - beforeAll(() => { - (npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(() => { - return new (fieldFormats.FieldFormat.from(identity))(); - }); - }); - it('should render component', () => { expect(getComponent().exists()).toBe(true); }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx index 175458497a05e..de2cc66a99c79 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_component.tsx @@ -20,15 +20,14 @@ import { last, findIndex, isNaN } from 'lodash'; import React, { Component } from 'react'; import { isColorDark } from '@elastic/eui'; -import { getFormat } from '../legacy_imports'; import { MetricVisValue } from './metric_vis_value'; import { Input } from '../metric_vis_fn'; import { FieldFormatsContentType, IFieldFormat } from '../../../../../plugins/data/public'; import { KibanaDatatable } from '../../../../../plugins/expressions/public'; import { getHeatmapColors } from '../../../../../plugins/charts/public'; import { VisParams, MetricVisMetric } from '../types'; -import { SchemaConfig } from '../../../visualizations/public'; -import { ExprVis } from '../../../visualizations/public/np_ready/public/expressions/vis'; +import { getFormatService } from '../services'; +import { SchemaConfig, ExprVis } from '../../../../../plugins/visualizations/public'; export interface MetricVisComponentProps { visParams: VisParams; @@ -122,13 +121,13 @@ export class MetricVisComponent extends Component { if (dimensions.bucket) { bucketColumnId = table.columns[dimensions.bucket.accessor].id; - bucketFormatter = getFormat(dimensions.bucket.format); + bucketFormatter = getFormatService().deserialize(dimensions.bucket.format); } dimensions.metrics.forEach((metric: SchemaConfig) => { const columnIndex = metric.accessor; const column = table?.columns[columnIndex]; - const formatter = getFormat(metric.format); + const formatter = getFormatService().deserialize(metric.format); table.rows.forEach((row, rowIndex) => { let title = column.name; let value: any = row[column.id]; diff --git a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts index 87355c57926b6..ba883601e5d65 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/legacy.ts @@ -19,18 +19,16 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MetricVisPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, charts: npSetup.plugins.charts, }; const pluginInstance = plugin({} as PluginInitializerContext); export const setup = pluginInstance.setup(npSetup.core, plugins); -export const start = pluginInstance.start(npStart.core); +export const start = pluginInstance.start(npStart.core, { data: npStart.plugins.data }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_metric/public/legacy_imports.ts deleted file mode 100644 index cd7a8e740d85d..0000000000000 --- a/src/legacy/core_plugins/vis_type_metric/public/legacy_imports.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts index c0bfa47bff502..459da47556307 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.test.ts @@ -17,22 +17,8 @@ * under the License. */ -import $ from 'jquery'; - -// TODO This is an integration test and thus requires a running platform. When moving to the new platform, -// this test has to be migrated to the newly created integration test environment. -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { npStart } from 'ui/new_platform'; -// @ts-ignore -import getStubIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; - -import { Vis } from '../../visualizations/public'; -import { fieldFormats } from '../../../../plugins/data/public'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../visualizations/public/np_ready/public/legacy'; import { createMetricVisTypeDefinition } from './metric_vis_type'; +import { MetricVisComponent } from './components/metric_vis_component'; jest.mock('ui/new_platform'); @@ -41,87 +27,9 @@ jest.mock('../../vis_default_editor/public', () => ({ })); describe('metric_vis - createMetricVisTypeDefinition', () => { - let vis: Vis; - - beforeAll(() => { - visualizationsSetup.createReactVisualization(createMetricVisTypeDefinition()); - (npStart.plugins.data.fieldFormats.getType as jest.Mock).mockImplementation(() => { - return fieldFormats.UrlFormat; - }); - (npStart.plugins.data.fieldFormats.deserialize as jest.Mock).mockImplementation(mapping => { - return new fieldFormats.UrlFormat(mapping ? mapping.params : {}); - }); - }); - - const setup = () => { - const stubIndexPattern = getStubIndexPattern(); - - stubIndexPattern.stubSetFieldFormat('ip', 'url', { - urlTemplate: 'http://ip.info?address={{value}}', - labelTemplate: 'ip[{{value}}]', - }); - - const searchSource = { - getField: (name: string) => { - if (name === 'index') { - return stubIndexPattern; - } - }, - }; - - // TODO: remove when Vis is converted to typescript. Only importing Vis as type - // @ts-ignore - vis = visualizationsStart.createVis('metric', { - type: 'metric', - data: { - searchSource, - aggs: [{ id: '1', type: 'top_hits', schema: 'metric', params: { field: 'ip' } }], - }, - }); - - vis.params.dimensions = { - metrics: [ - { - accessor: 0, - format: { - id: 'url', - params: { - urlTemplate: 'http://ip.info?address={{value}}', - labelTemplate: 'ip[{{value}}]', - }, - }, - }, - ], - }; - - const el = document.createElement('div'); - const metricVisType = visualizationsStart.get('metric'); - const Controller = metricVisType.visualization; - const controller = new Controller(el, vis); - const render = (esResponse: any) => { - controller.render(esResponse, vis.params); - }; - - return { el, render }; - }; - - it('renders html value from field formatter', () => { - const { el, render } = setup(); - - const ip = '235.195.237.208'; - render({ - columns: [{ id: 'col-0', name: 'ip' }], - rows: [{ 'col-0': ip }], - }); - - const links = $(el) - .find('a[href]') - .filter(function() { - // @ts-ignore - return this.href.includes('ip.info'); - }); + it('has metric vis component set', () => { + const def = createMetricVisTypeDefinition(); - expect(links.length).toBe(1); - expect(links.text()).toBe(`ip[${ip}]`); + expect(def.visConfig.component).toBe(MetricVisComponent); }); }); diff --git a/src/legacy/core_plugins/vis_type_metric/public/plugin.ts b/src/legacy/core_plugins/vis_type_metric/public/plugin.ts index 28b435cbc7980..cb65d5cafbdd2 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/plugin.ts @@ -19,11 +19,13 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { createMetricVisFn } from './metric_vis_fn'; import { createMetricVisTypeDefinition } from './metric_vis_type'; import { ChartsPluginSetup } from '../../../../plugins/charts/public'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { setFormatService } from './services'; /** @internal */ export interface MetricVisPluginSetupDependencies { @@ -32,6 +34,11 @@ export interface MetricVisPluginSetupDependencies { charts: ChartsPluginSetup; } +/** @internal */ +export interface MetricVisPluginStartDependencies { + data: DataPublicPluginStart; +} + /** @internal */ export class MetricVisPlugin implements Plugin { initializerContext: PluginInitializerContext; @@ -48,7 +55,7 @@ export class MetricVisPlugin implements Plugin { visualizations.createReactVisualization(createMetricVisTypeDefinition()); } - public start(core: CoreStart) { - // nothing to do here yet + public start(core: CoreStart, { data }: MetricVisPluginStartDependencies) { + setFormatService(data.fieldFormats); } } diff --git a/src/legacy/core_plugins/vis_type_metric/public/services.ts b/src/legacy/core_plugins/vis_type_metric/public/services.ts new file mode 100644 index 0000000000000..5af11bc7f0b03 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_metric/public/services.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter } from '../../../../plugins/kibana_utils/common'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; + +export const [getFormatService, setFormatService] = createGetterSetter< + DataPublicPluginStart['fieldFormats'] +>('metric data.fieldFormats'); diff --git a/src/legacy/core_plugins/vis_type_metric/public/types.ts b/src/legacy/core_plugins/vis_type_metric/public/types.ts index 298eebf23027d..cae18dd8a2ab1 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/types.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/types.ts @@ -18,7 +18,7 @@ */ import { Range } from '../../../../plugins/expressions/public'; -import { SchemaConfig } from '../../visualizations/public'; +import { SchemaConfig } from '../../../../plugins/visualizations/public'; import { ColorModes, Labels, Style } from '../../vis_type_vislib/public'; import { ColorSchemas } from '../../../../plugins/charts/public'; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js index 211b79e915038..a23407a599ae2 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js @@ -21,105 +21,17 @@ import $ from 'jquery'; import moment from 'moment'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import { - metricOnly, - threeTermBuckets, - oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, -} from 'fixtures/fake_hierarchical_data'; import sinon from 'sinon'; import { npStart } from '../../legacy_imports'; -import { search } from '../../../../../../plugins/data/public'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { round } from 'lodash'; -import { tableVisTypeDefinition } from '../../table_vis_type'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../../../visualizations/public/np_ready/public/legacy'; import { getAngularModule } from '../../get_inner_angular'; import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; -import { tableVisResponseHandler } from '../../table_vis_response_handler'; - -const { tabifyAggResponse } = search; +import { tabifiedData } from './tabified_data'; describe('Table Vis - AggTable Directive', function() { let $rootScope; let $compile; - let indexPattern; let settings; - const tabifiedData = {}; - - const init = () => { - const searchSource = { - getField: name => { - if (name === 'index') { - return indexPattern; - } - }, - }; - const vis1 = visualizationsStart.createVis('table', { - type: 'table', - data: { searchSource, aggs: [] }, - }); - tabifiedData.metricOnly = tabifyAggResponse(vis1.data.aggs, metricOnly); - - const vis2 = visualizationsStart.createVis('table', { - type: 'table', - params: { - showMetricsAtAllLevels: true, - }, - data: { - aggs: [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'bucket', params: { field: 'extension' } }, - { type: 'terms', schema: 'bucket', params: { field: 'geo.src' } }, - { type: 'terms', schema: 'bucket', params: { field: 'machine.os' } }, - ], - searchSource, - }, - }); - vis2.data.aggs.aggs.forEach(function(agg, i) { - agg.id = 'agg_' + (i + 1); - }); - tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.data.aggs, threeTermBuckets, { - metricsAtAllLevels: true, - }); - - const vis3 = visualizationsStart.createVis('table', { - type: 'table', - data: { - aggs: [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'min', schema: 'metric', params: { field: '@timestamp' } }, - { type: 'terms', schema: 'bucket', params: { field: 'extension' } }, - { - type: 'date_histogram', - schema: 'bucket', - params: { field: '@timestamp', interval: 'd' }, - }, - { - type: 'derivative', - schema: 'metric', - params: { metricAgg: 'custom', customMetric: { id: '5-orderAgg', type: 'count' } }, - }, - { - type: 'top_hits', - schema: 'metric', - params: { field: 'bytes', aggregate: { val: 'min' }, size: 1 }, - }, - ], - searchSource, - }, - }); - vis3.data.aggs.aggs.forEach(function(agg, i) { - agg.id = 'agg_' + (i + 1); - }); - - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = tabifyAggResponse( - vis3.data.aggs, - oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative - ); - }; const initLocalAngular = () => { const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); @@ -128,20 +40,13 @@ describe('Table Vis - AggTable Directive', function() { beforeEach(initLocalAngular); - ngMock.inject(function() { - visualizationsSetup.createBaseVisualization(tableVisTypeDefinition); - }); - beforeEach(ngMock.module('kibana/table_vis')); beforeEach( - ngMock.inject(function($injector, Private, config) { - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + ngMock.inject(function($injector, config) { settings = config; $rootScope = $injector.get('$rootScope'); $compile = $injector.get('$compile'); - - init(); }) ); @@ -158,7 +63,7 @@ describe('Table Vis - AggTable Directive', function() { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [], }; - $scope.table = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions).tables[0]; + $scope.table = tabifiedData.metricOnly.tables[0]; const $el = $compile('')( $scope @@ -194,10 +99,7 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, params: {} }, ], }; - $scope.table = tableVisResponseHandler( - tabifiedData.threeTermBuckets, - $scope.dimensions - ).tables[0]; + $scope.table = tabifiedData.threeTermBuckets.tables[0]; const $el = $(''); $compile($el)($scope); $scope.$digest(); @@ -261,11 +163,8 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, format: { id: 'number' } }, ], }; - const response = tableVisResponseHandler( - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, - $scope.dimensions - ); - $scope.table = response.tables[0]; + $scope.table = + tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative.tables[0]; $scope.showTotal = true; $scope.totalFunc = totalFunc; const $el = $(`')( $scope @@ -419,10 +315,7 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, params: {} }, ], }; - $scope.table = tableVisResponseHandler( - tabifiedData.threeTermBuckets, - $scope.dimensions - ).tables[0]; + $scope.table = tabifiedData.threeTermBuckets.tables[0]; const $el = $compile('')( $scope @@ -481,11 +374,8 @@ describe('Table Vis - AggTable Directive', function() { { accessor: 5, format: { id: 'number' } }, ], }; - const response = tableVisResponseHandler( - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, - $scope.dimensions - ); - $scope.table = response.tables[0]; + $scope.table = + tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative.tables[0]; $scope.percentageCol = 'Average bytes'; const $el = $(` { - const searchSource = { - getField: name => { - if (name === 'index') { - return indexPattern; - } - }, - }; - const vis1 = visualizationsStart.createVis('table', { - type: 'table', - data: { searchSource, aggs: [] }, - }); - tabifiedData.metricOnly = tabifyAggResponse(vis1.data.aggs, metricOnly); - - const vis2 = visualizationsStart.createVis('pie', { - type: 'pie', - data: { - aggs: [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'split', params: { field: 'extension' } }, - { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, - ], - searchSource, - }, - }); - vis2.data.aggs.aggs.forEach(function(agg, i) { - agg.id = 'agg_' + (i + 1); - }); - tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.data.aggs, threeTermBuckets); - }; const initLocalAngular = () => { const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); @@ -78,23 +38,9 @@ describe('Table Vis - AggTableGroup Directive', function() { beforeEach(ngMock.module('kibana/table_vis')); beforeEach( - ngMock.inject(function($injector, Private) { - // this is provided in table_vis_controller.js - // tech debt that will be resolved through further deangularization and moving tests to jest - /* - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, - }; - - visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies)); - */ - - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + ngMock.inject(function($injector) { $rootScope = $injector.get('$rootScope'); $compile = $injector.get('$compile'); - - init(); }) ); @@ -111,7 +57,7 @@ describe('Table Vis - AggTableGroup Directive', function() { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [], }; - $scope.group = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions); + $scope.group = tabifiedData.metricOnly; $scope.sort = { columnIndex: null, direction: null, @@ -156,10 +102,7 @@ describe('Table Vis - AggTableGroup Directive', function() { { accessor: 5, params: {} }, ], }; - const group = ($scope.group = tableVisResponseHandler( - tabifiedData.threeTermBuckets, - $scope.dimensions - )); + const group = ($scope.group = tabifiedData.threeTermBucketsWithSplit); const $el = $( '' ); diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/tabified_data.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/tabified_data.js new file mode 100644 index 0000000000000..857b0ea8662cd --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/tabified_data.js @@ -0,0 +1,795 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const tabifiedData = { + metricOnly: { + tables: [ + { + columns: [ + { + id: 'col-0-1', + name: 'Count', + }, + ], + rows: [ + { + 'col-0-1': 1000, + }, + ], + }, + ], + }, + threeTermBuckets: { + tables: [ + { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + ], + }, + threeTermBucketsWithSplit: { + tables: [ + { + title: 'png: extension: Descending', + name: 'extension: Descending', + key: 'png', + column: 0, + row: 0, + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + tables: [ + { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + ], + }, + { + title: 'css: extension: Descending', + name: 'extension: Descending', + key: 'css', + column: 0, + row: 4, + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + tables: [ + { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + ], + }, + { + title: 'html: extension: Descending', + name: 'extension: Descending', + key: 'html', + column: 0, + row: 8, + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'IT', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'MX', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'linux', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-1-agg_3': 'US', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + tables: [ + { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-2-agg_4', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'CN', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'win', + 'col-3-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-1-agg_3': 'FR', + 'col-2-agg_4': 'mac', + 'col-3-agg_1': 3029, + }, + ], + }, + ], + }, + ], + direction: 'row', + }, + oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative: { + tables: [ + { + columns: [ + { + id: 'col-0-agg_3', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_4', + name: '@timestamp per day', + }, + { + id: 'col-2-agg_1', + name: 'Average bytes', + }, + { + id: 'col-3-agg_2', + name: 'Min @timestamp', + }, + { + id: 'col-4-agg_5', + name: 'Derivative of Count', + }, + { + id: 'col-5-agg_6', + name: 'Last bytes', + }, + ], + rows: [ + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1411862400000, + 'col-2-agg_1': 9283, + 'col-3-agg_2': 1411862400000, + 'col-5-agg_6': 23, + }, + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1411948800000, + 'col-2-agg_1': 28349, + 'col-3-agg_2': 1411948800000, + 'col-4-agg_5': 203, + 'col-5-agg_6': 39, + }, + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1412035200000, + 'col-2-agg_1': 84330, + 'col-3-agg_2': 1412035200000, + 'col-4-agg_5': 200, + 'col-5-agg_6': 329, + }, + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1412121600000, + 'col-2-agg_1': 34992, + 'col-3-agg_2': 1412121600000, + 'col-4-agg_5': 103, + 'col-5-agg_6': 22, + }, + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1412208000000, + 'col-2-agg_1': 145432, + 'col-3-agg_2': 1412208000000, + 'col-4-agg_5': 153, + 'col-5-agg_6': 93, + }, + { + 'col-0-agg_3': 'png', + 'col-1-agg_4': 1412294400000, + 'col-2-agg_1': 220943, + 'col-3-agg_2': 1412294400000, + 'col-4-agg_5': 239, + 'col-5-agg_6': 72, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1411862400000, + 'col-2-agg_1': 9283, + 'col-3-agg_2': 1411862400000, + 'col-5-agg_6': 75, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1411948800000, + 'col-2-agg_1': 28349, + 'col-3-agg_2': 1411948800000, + 'col-4-agg_5': 10, + 'col-5-agg_6': 11, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1412035200000, + 'col-2-agg_1': 84330, + 'col-3-agg_2': 1412035200000, + 'col-4-agg_5': 24, + 'col-5-agg_6': 238, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1412121600000, + 'col-2-agg_1': 34992, + 'col-3-agg_2': 1412121600000, + 'col-4-agg_5': 49, + 'col-5-agg_6': 343, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1412208000000, + 'col-2-agg_1': 145432, + 'col-3-agg_2': 1412208000000, + 'col-4-agg_5': 100, + 'col-5-agg_6': 837, + }, + { + 'col-0-agg_3': 'css', + 'col-1-agg_4': 1412294400000, + 'col-2-agg_1': 220943, + 'col-3-agg_2': 1412294400000, + 'col-4-agg_5': 23, + 'col-5-agg_6': 302, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1411862400000, + 'col-2-agg_1': 9283, + 'col-3-agg_2': 1411862400000, + 'col-5-agg_6': 30, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1411948800000, + 'col-2-agg_1': 28349, + 'col-3-agg_2': 1411948800000, + 'col-4-agg_5': 1, + 'col-5-agg_6': 43, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1412035200000, + 'col-2-agg_1': 84330, + 'col-3-agg_2': 1412035200000, + 'col-4-agg_5': 5, + 'col-5-agg_6': 88, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1412121600000, + 'col-2-agg_1': 34992, + 'col-3-agg_2': 1412121600000, + 'col-4-agg_5': 10, + 'col-5-agg_6': 91, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1412208000000, + 'col-2-agg_1': 145432, + 'col-3-agg_2': 1412208000000, + 'col-4-agg_5': 43, + 'col-5-agg_6': 534, + }, + { + 'col-0-agg_3': 'html', + 'col-1-agg_4': 1412294400000, + 'col-2-agg_1': 220943, + 'col-3-agg_2': 1412294400000, + 'col-4-agg_5': 1, + 'col-5-agg_6': 553, + }, + ], + }, + ], + }, +}; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js index 83d7ca4084a20..b9e79f96e4fc1 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; import aggTableTemplate from './agg_table.html'; -import { getFormat } from '../legacy_imports'; +import { getFormatService } from '../services'; import { i18n } from '@kbn/i18n'; export function KbnAggTable(config, RecursionHelper) { @@ -127,7 +127,7 @@ export function KbnAggTable(config, RecursionHelper) { if (!dimension) return; - const formatter = getFormat(dimension.format); + const formatter = getFormatService().deserialize(dimension.format); const formattedColumn = { id: col.id, @@ -247,7 +247,7 @@ export function KbnAggTable(config, RecursionHelper) { function addPercentageCol(columns, title, rows, insertAtIndex) { const { id, sumTotal } = columns[insertAtIndex]; const newId = `${id}-percents`; - const formatter = getFormat({ id: 'percent' }); + const formatter = getFormatService().deserialize({ id: 'percent' }); const i18nTitle = i18n.translate('visTypeTable.params.percentageTableColumnName', { defaultMessage: '{title} percentages', values: { title }, diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy.ts b/src/legacy/core_plugins/vis_type_table/public/legacy.ts index e5b2619ef2970..3d5f8c1b3efe9 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts @@ -22,14 +22,13 @@ import { npSetup, npStart } from './legacy_imports'; import { plugin } from '.'; import { TablePluginSetupDependencies } from './plugin'; -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); export const setup = pluginInstance.setup(npSetup.core, plugins); -export const start = pluginInstance.start(npStart.core); +export const start = pluginInstance.start(npStart.core, { data: npStart.plugins.data }); diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index 287b6c172ffd9..1030e971d6450 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -18,4 +18,3 @@ */ export { npSetup, npStart } from 'ui/new_platform'; -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; diff --git a/src/legacy/core_plugins/vis_type_table/public/plugin.ts b/src/legacy/core_plugins/vis_type_table/public/plugin.ts index 519a56da23ac9..ea12a5320a14d 100644 --- a/src/legacy/core_plugins/vis_type_table/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_table/public/plugin.ts @@ -17,12 +17,14 @@ * under the License. */ import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; import { createTableVisFn } from './table_vis_fn'; import { tableVisTypeDefinition } from './table_vis_type'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { setFormatService } from './services'; /** @internal */ export interface TablePluginSetupDependencies { @@ -30,6 +32,11 @@ export interface TablePluginSetupDependencies { visualizations: VisualizationsSetup; } +/** @internal */ +export interface TablePluginStartDependencies { + data: DataPublicPluginStart; +} + /** @internal */ export class TableVisPlugin implements Plugin, void> { initializerContext: PluginInitializerContext; @@ -47,7 +54,7 @@ export class TableVisPlugin implements Plugin, void> { visualizations.createBaseVisualization(tableVisTypeDefinition); } - public start(core: CoreStart) { - // nothing to do here yet + public start(core: CoreStart, { data }: TablePluginStartDependencies) { + setFormatService(data.fieldFormats); } } diff --git a/src/legacy/core_plugins/vis_type_table/public/services.ts b/src/legacy/core_plugins/vis_type_table/public/services.ts new file mode 100644 index 0000000000000..08efed733cafe --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/services.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter } from '../../../../plugins/kibana_utils/common'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; + +export const [getFormatService, setFormatService] = createGetterSetter< + DataPublicPluginStart['fieldFormats'] +>('table data.fieldFormats'); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index ad56607e9296c..8d6f88bf8dd4a 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -27,7 +27,7 @@ import StubIndexPattern from 'test_utils/stub_index_pattern'; import { getAngularModule } from './get_inner_angular'; import { initTableVisLegacyModule } from './table_vis_legacy_module'; import { tableVisTypeDefinition } from './table_vis_type'; -import { Vis } from '../../visualizations/public'; +import { Vis } from '../../../../plugins/visualizations/public'; // eslint-disable-next-line import { stubFields } from '../../../../plugins/data/public/stubs'; // eslint-disable-next-line diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts index 426480fa5b52d..4bf33c876dfff 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_response_handler.ts @@ -19,7 +19,7 @@ import { Required } from '@kbn/utility-types'; -import { getFormat } from './legacy_imports'; +import { getFormatService } from './services'; import { Input } from './table_vis_fn'; export interface TableContext { @@ -54,7 +54,7 @@ export function tableVisResponseHandler(table: Input, dimensions: any): TableCon if (split) { converted.direction = dimensions.splitRow ? 'row' : 'column'; const splitColumnIndex = split[0].accessor; - const splitColumnFormatter = getFormat(split[0].format); + const splitColumnFormatter = getFormatService().deserialize(split[0].format); const splitColumn = table.columns[splitColumnIndex]; const splitMap = {}; let splitIndex = 0; diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts index e70b09904253f..d26e860e51272 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { AggGroupNames } from '../../../../plugins/data/public'; import { Schemas } from '../../vis_default_editor/public'; -import { Vis } from '../../visualizations/public'; +import { Vis } from '../../../../plugins/visualizations/public'; import { tableVisResponseHandler } from './table_vis_response_handler'; // @ts-ignore import tableVisTemplate from './table_vis.html'; diff --git a/src/legacy/core_plugins/vis_type_table/public/types.ts b/src/legacy/core_plugins/vis_type_table/public/types.ts index 39023d1305cb6..c6de14b9f050c 100644 --- a/src/legacy/core_plugins/vis_type_table/public/types.ts +++ b/src/legacy/core_plugins/vis_type_table/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { SchemaConfig } from '../../visualizations/public'; +import { SchemaConfig } from '../../../../plugins/visualizations/public'; export enum AggTypes { SUM = 'sum', diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index 2feaad9f4e6b6..5bb730d2f9b10 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -20,11 +20,10 @@ import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; import $ from 'jquery'; -import { VisParams } from '../../visualizations/public'; +import { VisParams, ExprVis } from '../../../../plugins/visualizations/public'; import { npStart } from './legacy_imports'; import { getAngularModule } from './get_inner_angular'; import { initTableVisLegacyModule } from './table_vis_legacy_module'; -import { ExprVis } from '../../visualizations/public/np_ready/public/expressions/vis'; const innerAngularName = 'kibana/table_vis'; diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js b/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js index 6f54744a2f508..9e611861417cd 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/__tests__/tag_cloud_visualization.js @@ -19,20 +19,23 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { start as visualizationsStart } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy'; import { ImageComparator } from 'test_utils/image_comparator'; import { createTagCloudVisualization } from '../tag_cloud_visualization'; import basicdrawPng from './basicdraw.png'; import afterresizePng from './afterresize.png'; import afterparamChange from './afterparamchange.png'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ExprVis } from '../../../../../../plugins/visualizations/public/expressions/vis'; // Replace with mock when converting to jest tests // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { seedColors } from '../../../../../../plugins/charts/public/services/colors/seed_colors'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { BaseVisType } from '../../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +import { createTagCloudVisTypeDefinition } from '../../tag_cloud_type'; const THRESHOLD = 0.65; const PIXEL_DIFF = 64; - describe('TagCloudVisualizationTest', function() { let domNode; let vis; @@ -67,10 +70,11 @@ describe('TagCloudVisualizationTest', function() { describe('TagCloudVisualization - basics', function() { beforeEach(async function() { + const visType = new BaseVisType(createTagCloudVisTypeDefinition({ colors: seedColors })); setupDOM('512px', '512px'); imageComparator = new ImageComparator(); - vis = visualizationsStart.createVis('tagcloud', { - type: 'tagcloud', + vis = new ExprVis({ + type: visType, params: { bucket: { accessor: 0, format: {} }, metric: { accessor: 0, format: {} }, diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js index 04f447bf78d50..4094f2ab59158 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js @@ -23,7 +23,7 @@ import { take } from 'rxjs/operators'; import { render, unmountComponentAtNode } from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; -import { getFormat } from '../legacy_imports'; +import { getFormatService } from '../services'; import { Label } from './label'; import { TagCloud } from './tag_cloud'; @@ -118,7 +118,7 @@ export function createTagCloudVisualization({ colors }) { const bucket = this._visParams.bucket; const metric = this._visParams.metric; - const bucketFormatter = bucket ? getFormat(bucket.format) : null; + const bucketFormatter = bucket ? getFormatService().deserialize(bucket.format) : null; const tagColumn = bucket ? data.columns[bucket.accessor].id : -1; const metricColumn = data.columns[metric.accessor].id; const tags = data.rows.map((row, rowIndex) => { diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts index 182da40a3e6ea..f70789edc66ba 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts @@ -19,18 +19,16 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { TagCloudPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, charts: npSetup.plugins.charts, }; const pluginInstance = plugin({} as PluginInitializerContext); export const setup = pluginInstance.setup(npSetup.core, plugins); -export const start = pluginInstance.start(npStart.core); +export const start = pluginInstance.start(npStart.core, { data: npStart.plugins.data }); diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts index 8244cba38edc3..1061271aa315b 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts @@ -19,11 +19,13 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { ChartsPluginSetup } from '../../../../plugins/charts/public'; import { createTagCloudFn } from './tag_cloud_fn'; import { createTagCloudVisTypeDefinition } from './tag_cloud_type'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { setFormatService } from './services'; /** @internal */ export interface TagCloudPluginSetupDependencies { @@ -37,6 +39,11 @@ export interface TagCloudVisDependencies { colors: ChartsPluginSetup['colors']; } +/** @internal */ +export interface TagCloudVisPluginStartDependencies { + data: DataPublicPluginStart; +} + /** @internal */ export class TagCloudPlugin implements Plugin { initializerContext: PluginInitializerContext; @@ -58,7 +65,7 @@ export class TagCloudPlugin implements Plugin { ); } - public start(core: CoreStart) { - // nothing to do here yet + public start(core: CoreStart, { data }: TagCloudVisPluginStartDependencies) { + setFormatService(data.fieldFormats); } } diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/services.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/services.ts new file mode 100644 index 0000000000000..fef46282eb8dd --- /dev/null +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/services.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter } from '../../../../plugins/kibana_utils/common'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; + +export const [getFormatService, setFormatService] = createGetterSetter< + DataPublicPluginStart['fieldFormats'] +>('data.fieldFormats'); + +export { npStart } from 'ui/new_platform'; diff --git a/src/legacy/core_plugins/vis_type_timelion/index.ts b/src/legacy/core_plugins/vis_type_timelion/index.ts index 6c1e3f452959e..7bca5154c84fd 100644 --- a/src/legacy/core_plugins/vis_type_timelion/index.ts +++ b/src/legacy/core_plugins/vis_type_timelion/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../../../src/legacy const timelionVisPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'timelion_vis', - require: ['kibana', 'elasticsearch', 'visualizations'], + require: ['kibana', 'elasticsearch'], publicDir: resolve(__dirname, 'public'), uiExports: { styleSheetPaths: resolve(__dirname, 'public/index.scss'), diff --git a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx index f55d1602ea342..0fad0a164bf0b 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx +++ b/src/legacy/core_plugins/vis_type_timelion/public/components/timelion_vis.tsx @@ -23,7 +23,7 @@ import { IUiSettingsClient } from 'kibana/public'; import { ChartComponent } from './chart'; import { VisParams } from '../timelion_vis_fn'; import { TimelionSuccessResponse } from '../helpers/timelion_request_handler'; -import { ExprVis } from '../../../visualizations/public/np_ready/public/expressions/vis'; +import { ExprVis } from '../../../../../plugins/visualizations/public'; export interface TimelionVisComponentProp { config: IUiSettingsClient; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts b/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts index 47bfed6340e93..61e31420f73ba 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/helpers/timelion_request_handler.ts @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { KIBANA_CONTEXT_NAME } from 'src/plugins/expressions/public'; -import { VisParams } from 'src/legacy/core_plugins/visualizations/public'; +import { VisParams } from '../../../../../plugins/visualizations/public'; import { TimeRange, Filter, esQuery, Query } from '../../../../../plugins/data/public'; import { TimelionVisDependencies } from '../plugin'; import { getTimezone } from './get_timezone'; diff --git a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts b/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts index 9935f3d92f6bd..f8de9f94dcedf 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/legacy.ts @@ -20,15 +20,13 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from './legacy_imports'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { TimelionVisSetupDependencies } from './plugin'; import { plugin } from '.'; const setupPlugins: Readonly = { expressions: npSetup.plugins.expressions, data: npSetup.plugins.data, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts b/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts index 9d69c312b48f4..b5aa64db19aa4 100644 --- a/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_timelion/public/plugin.ts @@ -29,13 +29,13 @@ import { Plugin as ExpressionsPlugin } from 'src/plugins/expressions/public'; import { DataPublicPluginSetup, TimefilterContract } from 'src/plugins/data/public'; import { PluginsStart } from './legacy_imports'; -import { VisualizationsSetup } from '../../visualizations/public/np_ready/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { getTimelionVisualizationConfig } from './timelion_vis_fn'; import { getTimelionVisDefinition } from './timelion_vis_type'; import { setIndexPatterns, setSavedObjectsClient } from './helpers/plugin_services'; -type TimelionVisCoreSetup = CoreSetup; +type TimelionVisCoreSetup = CoreSetup; /** @internal */ export interface TimelionVisDependencies extends Partial { diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts b/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts index fb22bbd4146e2..42f116701be51 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/public/legacy.ts @@ -19,14 +19,12 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { MetricsPluginSetupDependencies } from './plugin'; import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/plugin.ts b/src/legacy/core_plugins/vis_type_timeseries/public/plugin.ts index 441b1f05ea78c..0310ecf6cfd87 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/public/plugin.ts @@ -18,7 +18,7 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { createMetricsFn } from './metrics_fn'; import { metricsVisDefinition } from './metrics_type'; diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index 0db3e6cefa724..c7fbc0815b07c 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -39,15 +39,15 @@ import vegaMapImage256 from './vega_map_image_256.png'; import { VegaParser } from '../data_model/vega_parser'; import { SearchCache } from '../data_model/search_cache'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../../visualizations/public/np_ready/public/legacy'; import { createVegaTypeDefinition } from '../vega_type'; // TODO This is an integration test and thus requires a running platform. When moving to the new platform, // this test has to be migrated to the newly created integration test environment. // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { npStart } from 'ui/new_platform'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; import { setInjectedVars } from '../services'; const THRESHOLD = 0.1; @@ -59,7 +59,7 @@ describe('VegaVisualizations', () => { let vis; let imageComparator; let vegaVisualizationDependencies; - let visRegComplete = false; + let vegaVisType; setInjectedVars({ emsTileLayerId: {}, @@ -89,13 +89,7 @@ describe('VegaVisualizations', () => { }, }; - if (!visRegComplete) { - visRegComplete = true; - visualizationsSetup.createBaseVisualization( - createVegaTypeDefinition(vegaVisualizationDependencies) - ); - } - + vegaVisType = new BaseVisType(createVegaTypeDefinition(vegaVisualizationDependencies)); VegaVisualization = createVegaVisualization(vegaVisualizationDependencies); }) ); @@ -105,7 +99,9 @@ describe('VegaVisualizations', () => { setupDOM('512px', '512px'); imageComparator = new ImageComparator(); - vis = visualizationsStart.createVis('vega', { type: 'vega' }); + vis = new ExprVis({ + type: vegaVisType, + }); }); afterEach(function() { diff --git a/src/legacy/core_plugins/vis_type_vega/public/data_model/vega_parser.js b/src/legacy/core_plugins/vis_type_vega/public/data_model/vega_parser.js index 7c2638d1f5165..735ce60f76d47 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/data_model/vega_parser.js +++ b/src/legacy/core_plugins/vis_type_vega/public/data_model/vega_parser.js @@ -116,7 +116,8 @@ export class VegaParser { */ _compileVegaLite() { this.vlspec = this.spec; - const logger = vega.logger(vega.Warn); + // eslint-disable-next-line import/namespace + const logger = vega.logger(vega.Warn); // note: eslint has a false positive here logger.warn = this._onWarning.bind(this); this.spec = vegaLite.compile(this.vlspec, logger).spec; diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index 38ce706ed13ef..b2c73894d978d 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -19,15 +19,13 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; - -import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { VegaPluginSetupDependencies, VegaPluginStartDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; const setupPlugins: Readonly = { ...npSetup.plugins, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts index 3b01d9ceca5a6..38b92a40cd99a 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../.. import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; -import { VisualizationsSetup } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { setNotifications, setData, diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js index 76a2e672e0bd0..c90f059ff7c94 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_base_view.js @@ -132,7 +132,8 @@ export class VegaBaseView { createViewConfig() { const config = { - logLevel: vega.Warn, + // eslint-disable-next-line import/namespace + logLevel: vega.Warn, // note: eslint has a false positive here renderer: this._parser.renderer, }; diff --git a/src/legacy/core_plugins/vis_type_vislib/index.ts b/src/legacy/core_plugins/vis_type_vislib/index.ts index 1f75aea31ba0b..da9476285a9b2 100644 --- a/src/legacy/core_plugins/vis_type_vislib/index.ts +++ b/src/legacy/core_plugins/vis_type_vislib/index.ts @@ -25,7 +25,7 @@ import { LegacyPluginApi, LegacyPluginInitializer } from '../../types'; const visTypeVislibPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => new Plugin({ id: 'vis_type_vislib', - require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter'], + require: ['kibana', 'elasticsearch', 'interpreter'], publicDir: resolve(__dirname, 'public'), styleSheetPaths: resolve(__dirname, 'public/index.scss'), uiExports: { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx index bc12e04e29468..ec7a325ba43d1 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx @@ -22,7 +22,7 @@ import React, { useMemo, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { SeriesParam, ValueAxis } from '../../../types'; import { ChartTypes } from '../../../utils/collections'; import { SelectOption } from '../../common'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx index a53d21b121f7d..01a69a6fac70b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx @@ -22,7 +22,7 @@ import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { SeriesParam } from '../../../types'; import { NumberInputOption, SelectOption, SwitchOption } from '../../common'; import { SetChart } from './chart_options'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts index 58c75629f1fa1..0d9fa8c25a4f7 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { Axis, ValueAxis, SeriesParam, Style } from '../../../types'; import { ChartTypes, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx index 44e7a4cfb0088..22a726b53363b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx @@ -23,7 +23,7 @@ import { EuiPanel, EuiTitle, EuiSpacer, EuiAccordion } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { ValueAxis, SeriesParam } from '../../../types'; import { ChartOptions } from './chart_options'; import { SetParamByIndex, ChangeValueAxis } from './'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx index 30d80ed595fe7..912c3b904b110 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx @@ -31,7 +31,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { SeriesParam, ValueAxis } from '../../../types'; import { ValueAxisOptions } from './value_axis_options'; import { SetParamByIndex } from './'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx index 0e78bf2f31ef6..8f0327e78c7ab 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx @@ -21,7 +21,7 @@ import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiAccordion, EuiHorizontalRule } from '@elastic/eui'; -import { Vis } from 'src/legacy/core_plugins/visualizations/public'; +import { Vis } from '../../../../../../../plugins/visualizations/public'; import { ValueAxis } from '../../../types'; import { Positions } from '../../../utils/collections'; import { SelectOption, SwitchOption, TextInputOption } from '../../common'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts index 5828a0cccebd7..aa11e0ef41fba 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts @@ -25,20 +25,15 @@ import { VisTypeVislibPluginSetupDependencies, VisTypeVislibPluginStartDependencies, } from './plugin'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../visualizations/public/np_ready/public/legacy'; const setupPlugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, charts: npSetup.plugins.charts, }; const startPlugins: Readonly = { - expressions: npStart.plugins.expressions, - visualizations: visualizationsStart, + data: npStart.plugins.data, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts index 2b177bff98d56..da16a38deba9f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts @@ -17,11 +17,9 @@ * under the License. */ -import { npStart } from 'ui/new_platform'; -export const { createFiltersFromEvent } = npStart.plugins.data.actions; -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { search } from '../../../../plugins/data/public'; export const { tabifyAggResponse, tabifyGetColumns } = search; + // @ts-ignore export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts index a71892cc47b05..2731fb6f5fbe6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts @@ -25,7 +25,7 @@ import { } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public'; +import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn'; import { createPieVisFn } from './pie_fn'; import { @@ -40,6 +40,8 @@ import { } from './vis_type_vislib_vis_types'; import { ChartsPluginSetup } from '../../../../plugins/charts/public'; import { ConfigSchema as VisTypeXyConfigSchema } from '../../vis_type_xy'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { setFormatService, setDataActions } from './services'; export interface VisTypeVislibDependencies { uiSettings: IUiSettingsClient; @@ -55,14 +57,13 @@ export interface VisTypeVislibPluginSetupDependencies { /** @internal */ export interface VisTypeVislibPluginStartDependencies { - expressions: ReturnType; - visualizations: VisualizationsStart; + data: DataPublicPluginStart; } -type VisTypeVislibCoreSetup = CoreSetup; +type VisTypeVislibCoreSetup = CoreSetup; /** @internal */ -export class VisTypeVislibPlugin implements Plugin, void> { +export class VisTypeVislibPlugin implements Plugin { constructor(public initializerContext: PluginInitializerContext) {} public async setup( @@ -108,7 +109,8 @@ export class VisTypeVislibPlugin implements Plugin, void> { ); } - public start(core: CoreStart, deps: VisTypeVislibPluginStartDependencies) { - // nothing to do here + public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) { + setFormatService(data.fieldFormats); + setDataActions({ createFiltersFromEvent: data.actions.createFiltersFromEvent }); } } diff --git a/src/legacy/core_plugins/vis_type_vislib/public/services.ts b/src/legacy/core_plugins/vis_type_vislib/public/services.ts new file mode 100644 index 0000000000000..da50e227d84d2 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/services.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter } from '../../../../plugins/kibana_utils/common'; +import { DataPublicPluginStart } from '../../../../plugins/data/public'; + +export const [getDataActions, setDataActions] = createGetterSetter< + DataPublicPluginStart['actions'] +>('vislib data.actions'); + +export const [getFormatService, setFormatService] = createGetterSetter< + DataPublicPluginStart['fieldFormats'] +>('vislib data.fieldFormats'); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx index 010b61a0900b0..ec091e5d29cfd 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx @@ -26,8 +26,7 @@ import { Positions } from './utils/collections'; import { VisTypeVislibDependencies } from './plugin'; import { mountReactNode } from '../../../../core/public/utils'; import { VisLegend, CUSTOM_LEGEND_VIS_TYPES } from './vislib/components/legend'; -import { VisParams } from '../../visualizations/public'; -import { ExprVis } from '../../visualizations/public/np_ready/public/expressions/vis'; +import { VisParams, ExprVis } from '../../../../plugins/visualizations/public'; const legendClassName = { top: 'visLib--legend-top', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js index 21f4e60e4bc6e..caafb2c636271 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js @@ -22,91 +22,8 @@ import _ from 'lodash'; import $ from 'jquery'; import expect from '@kbn/expect'; -import { threeTermBuckets } from 'fixtures/fake_hierarchical_data'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -import { start as visualizationsStart } from '../../../../../visualizations/public/np_ready/public/legacy'; import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture'; -import { tabifyAggResponse } from '../../../legacy_imports'; -import { vislibSlicesResponseHandler } from '../../response_handler'; - -const rowAgg = [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'split', params: { field: 'extension', rows: true } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, - { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, -]; - -const rowAggDimensions = { - splitRow: [ - { - accessor: 0, - }, - ], - buckets: [ - { - accessor: 2, - }, - { - accessor: 4, - }, - ], - metric: { - accessor: 5, - }, -}; - -const colAgg = [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'split', params: { field: 'extension', row: false } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, - { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, -]; - -const colAggDimensions = { - splitColumn: [ - { - accessor: 0, - }, - ], - buckets: [ - { - accessor: 2, - }, - { - accessor: 4, - }, - ], - metric: { - accessor: 5, - }, -}; - -const sliceAgg = [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, - { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, -]; - -const sliceAggDimensions = { - buckets: [ - { - accessor: 0, - }, - { - accessor: 2, - }, - ], - metric: { - accessor: 3, - }, -}; - -const aggArray = [ - [rowAgg, rowAggDimensions], - [colAgg, colAggDimensions], - [sliceAgg, sliceAggDimensions], -]; +import { pieChartMockData } from './pie_chart_mock_data'; const names = ['rows', 'columns', 'slices']; @@ -121,47 +38,14 @@ describe('No global chart settings', function() { }; let chart1; let mockUiState; - let indexPattern; - let responseHandler; - let data1; - let stubVis1; beforeEach(() => { chart1 = getVis(visLibParams1); mockUiState = getMockUiState(); - indexPattern = new FixturesStubbedLogstashIndexPatternProvider(); - responseHandler = vislibSlicesResponseHandler; - - let id1 = 1; - stubVis1 = visualizationsStart.createVis('pie', { - type: 'pie', - data: { - aggs: rowAgg, - searchSource: { - getField: name => { - if (name === 'index') { - return indexPattern; - } - }, - }, - }, - }); - - stubVis1.isHierarchical = () => true; - - // We need to set the aggs to a known value. - _.each(stubVis1.data.aggs.aggs, function(agg) { - agg.id = 'agg_' + id1++; - }); }); beforeEach(async () => { - const table1 = tabifyAggResponse(stubVis1.data.aggs, threeTermBuckets, { - metricsAtAllLevels: true, - }); - data1 = await responseHandler(table1, rowAggDimensions); - - chart1.render(data1, mockUiState); + chart1.render(pieChartMockData.rowData, mockUiState); }); afterEach(function() { @@ -209,55 +93,21 @@ describe('No global chart settings', function() { }); describe('Vislib PieChart Class Test Suite', function() { - aggArray.forEach(function(aggItem, i) { - const [dataAgg, dataDimensions] = aggItem; + ['rowData', 'columnData', 'sliceData'].forEach(function(aggItem, i) { describe('Vislib PieChart Class Test Suite for ' + names[i] + ' data', function() { + const mockPieData = pieChartMockData[aggItem]; + const visLibParams = { type: 'pie', addLegend: true, addTooltip: true, }; let vis; - let mockUiState; - let indexPattern; - let data; - let stubVis; - let responseHandler; - - beforeEach(() => { - vis = getVis(visLibParams); - mockUiState = getMockUiState(); - indexPattern = new FixturesStubbedLogstashIndexPatternProvider(); - responseHandler = vislibSlicesResponseHandler; - - let id = 1; - stubVis = visualizationsStart.createVis('pie', { - type: 'pie', - data: { - aggs: dataAgg, - searchSource: { - getField: name => { - if (name === 'index') { - return indexPattern; - } - }, - }, - }, - }); - - // We need to set the aggs to a known value. - _.each(stubVis.data.aggs.aggs, function(agg) { - agg.id = 'agg_' + id++; - }); - }); beforeEach(async () => { - const table = tabifyAggResponse(stubVis.data.aggs, threeTermBuckets, { - metricsAtAllLevels: true, - }); - data = await responseHandler(table, dataDimensions); - - vis.render(data, mockUiState); + vis = getVis(visLibParams); + const mockUiState = getMockUiState(); + vis.render(mockPieData, mockUiState); }); afterEach(function() { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart_mock_data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart_mock_data.js new file mode 100644 index 0000000000000..188cd51759e51 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart_mock_data.js @@ -0,0 +1,3742 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const pieChartMockData = { + rowData: { + rows: [ + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['IT', 'win', 'mac', 'US', 'linux'], + slices: { + children: [ + { + name: 'IT', + size: 9299, + children: [ + { + name: 'win', + size: 0, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 9299, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'IT', + }, + }, + { + name: 'US', + size: 8293, + children: [ + { + name: 'linux', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'linux', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'US', + }, + }, + ], + }, + label: 'png: extension: Descending', + }, + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['MX', 'win', 'mac', 'US', 'linux'], + slices: { + children: [ + { + name: 'MX', + size: 9299, + children: [ + { + name: 'win', + size: 4992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 5892, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'MX', + }, + }, + { + name: 'US', + size: 8293, + children: [ + { + name: 'linux', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'linux', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'US', + }, + }, + ], + }, + label: 'css: extension: Descending', + }, + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['CN', 'win', 'mac', 'FR'], + slices: { + children: [ + { + name: 'CN', + size: 9299, + children: [ + { + name: 'win', + size: 4992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 5892, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'CN', + }, + }, + { + name: 'FR', + size: 8293, + children: [ + { + name: 'win', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'FR', + }, + }, + ], + }, + label: 'html: extension: Descending', + }, + ], + hits: 12, + }, + columnData: { + columns: [ + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['IT', 'win', 'mac', 'US', 'linux'], + slices: { + children: [ + { + name: 'IT', + size: 9299, + children: [ + { + name: 'win', + size: 0, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 9299, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'IT', + }, + }, + { + name: 'US', + size: 8293, + children: [ + { + name: 'linux', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'linux', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 0, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'US', + }, + }, + ], + }, + label: 'png: extension: Descending', + }, + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['MX', 'win', 'mac', 'US', 'linux'], + slices: { + children: [ + { + name: 'MX', + size: 9299, + children: [ + { + name: 'win', + size: 4992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 5892, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'MX', + }, + }, + { + name: 'US', + size: 8293, + children: [ + { + name: 'linux', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'linux', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'linux', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'US', + }, + }, + ], + }, + label: 'css: extension: Descending', + }, + { + hits: 4, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + names: ['CN', 'win', 'mac', 'FR'], + slices: { + children: [ + { + name: 'CN', + size: 9299, + children: [ + { + name: 'win', + size: 4992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 5892, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 1, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 0, + column: 2, + value: 'CN', + }, + }, + { + name: 'FR', + size: 8293, + children: [ + { + name: 'win', + size: 3992, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 4, + value: 'win', + }, + }, + { + name: 'mac', + size: 3029, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 3, + column: 4, + value: 'mac', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'extension: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'machine.os: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + { + id: 'col-4-agg_4', + name: 'geo.src: Descending', + }, + { + id: 'col-5-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 4992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + 'col-5-agg_1': 5892, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'win', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3992, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-4-agg_4': 'mac', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + 'col-5-agg_1': 3029, + }, + ], + }, + row: 2, + column: 2, + value: 'FR', + }, + }, + ], + }, + label: 'html: extension: Descending', + }, + ], + hits: 12, + }, + sliceData: { + hits: 6, + raw: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + names: ['png', 'IT', 'US', 'css', 'MX', 'html', 'CN', 'FR'], + slices: { + children: [ + { + name: 'png', + size: 412032, + children: [ + { + name: 'IT', + size: 9299, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 0, + column: 2, + value: 'IT', + }, + }, + { + name: 'US', + size: 8293, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 1, + column: 2, + value: 'US', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 0, + column: 0, + value: 'png', + }, + }, + { + name: 'css', + size: 412032, + children: [ + { + name: 'MX', + size: 9299, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 2, + column: 2, + value: 'MX', + }, + }, + { + name: 'US', + size: 8293, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 3, + column: 2, + value: 'US', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 2, + column: 0, + value: 'css', + }, + }, + { + name: 'html', + size: 412032, + children: [ + { + name: 'CN', + size: 9299, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 4, + column: 2, + value: 'CN', + }, + }, + { + name: 'FR', + size: 8293, + children: [], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 5, + column: 2, + value: 'FR', + }, + }, + ], + rawData: { + table: { + columns: [ + { + id: 'col-0-agg_2', + name: 'machine.os: Descending', + }, + { + id: 'col-1-agg_1', + name: 'Average bytes', + }, + { + id: 'col-2-agg_3', + name: 'geo.src: Descending', + }, + { + id: 'col-3-agg_1', + name: 'Average bytes', + }, + ], + rows: [ + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'IT', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'png', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'MX', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'css', + 'col-2-agg_3': 'US', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'CN', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 9299, + }, + { + 'col-0-agg_2': 'html', + 'col-2-agg_3': 'FR', + 'col-1-agg_1': 412032, + 'col-3-agg_1': 8293, + }, + ], + }, + row: 4, + column: 0, + value: 'html', + }, + }, + ], + }, + }, +}; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx index 7f06bdddb4805..c378ae7b05b37 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.test.tsx @@ -32,10 +32,13 @@ jest.mock('@elastic/eui', () => ({ })); jest.mock('../../../legacy_imports', () => ({ - createFiltersFromEvent: jest.fn().mockResolvedValue(['yes']), getTableAggs: jest.fn(), })); +jest.mock('../../../services', () => ({ + getDataActions: () => ({ createFiltersFromEvent: jest.fn().mockResolvedValue(['yes']) }), +})); + const vis = { params: { addLegend: true, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx index afd974d6d9b40..2fe16bbfeb625 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/legend/legend.tsx @@ -23,7 +23,7 @@ import { compact, uniq, map, every, isUndefined } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui'; -import { createFiltersFromEvent } from '../../../legacy_imports'; +import { getDataActions } from '../../../services'; import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; import { VisLegendItem } from './legend_item'; import { getPieNames } from './pie_utils'; @@ -101,7 +101,7 @@ export class VisLegend extends PureComponent { return false; } - const filters = await createFiltersFromEvent(item.values); + const filters = await getDataActions().createFiltersFromEvent(item.values); return Boolean(filters.length); }; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js index 2ed6d899f8602..2df157b6f121d 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js @@ -23,7 +23,7 @@ import _ from 'lodash'; import { injectZeros } from '../components/zero_injection/inject_zeros'; import { orderXValues } from '../components/zero_injection/ordered_x_keys'; import { labels } from '../components/labels/labels'; -import { getFormat } from '../../legacy_imports'; +import { getFormatService } from '../../services'; /** * Provides an API for pulling values off the data @@ -56,8 +56,8 @@ export class Data { newData[key] = data[key]; } else { newData[key] = data[key].map(seri => { - const converter = getFormat(seri.format); - const zConverter = getFormat(seri.zFormat); + const converter = getFormatService().deserialize(seri.format); + const zConverter = getFormatService().deserialize(seri.zFormat); return { id: seri.id, rawId: seri.rawId, @@ -76,9 +76,9 @@ export class Data { } }); - const xConverter = getFormat(newData.xAxisFormat); - const yConverter = getFormat(newData.yAxisFormat); - const zConverter = getFormat(newData.zAxisFormat); + const xConverter = getFormatService().deserialize(newData.xAxisFormat); + const yConverter = getFormatService().deserialize(newData.yAxisFormat); + const zConverter = getFormatService().deserialize(newData.zAxisFormat); newData.xAxisFormatter = val => xConverter.convert(val); newData.yAxisFormatter = val => yConverter.convert(val); newData.zAxisFormatter = val => zConverter.convert(val); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js index 0c584fedda217..9ba86c5181a4c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js @@ -17,7 +17,8 @@ * under the License. */ -import { buildHierarchicalData, buildPointSeriesData, getFormat } from '../legacy_imports'; +import { buildHierarchicalData, buildPointSeriesData } from '../legacy_imports'; +import { getFormatService } from '../services'; function tableResponseHandler(table, dimensions) { const converted = { tables: [] }; @@ -26,7 +27,7 @@ function tableResponseHandler(table, dimensions) { if (split) { converted.direction = dimensions.splitRow ? 'row' : 'column'; const splitColumnIndex = split[0].accessor; - const splitColumnFormatter = getFormat(split[0].format); + const splitColumnFormatter = getFormatService().deserialize(split[0].format); const splitColumn = table.columns[splitColumnIndex]; const splitMap = {}; let splitIndex = 0; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js index a36c7c4774dad..8e881c2a15726 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js @@ -22,7 +22,7 @@ import _ from 'lodash'; import { dataLabel } from '../lib/_data_label'; import { Dispatch } from '../lib/dispatch'; -import { getFormat } from '../../legacy_imports'; +import { getFormatService } from '../../services'; import { Tooltip, hierarchicalTooltipFormatter, @@ -47,7 +47,9 @@ export class Chart { const events = (this.events = new Dispatch(handler, deps.uiSettings)); - const fieldFormatter = getFormat(this.handler.data.get('tooltipFormatter')); + const fieldFormatter = getFormatService().deserialize( + this.handler.data.get('tooltipFormatter') + ); const tooltipFormatterProvider = this.handler.visConfig.get('type') === 'pie' ? hierarchicalTooltipFormatter diff --git a/src/legacy/core_plugins/vis_type_xy/public/legacy.ts b/src/legacy/core_plugins/vis_type_xy/public/legacy.ts index e1cee9c30804a..740ceeaac6a7d 100644 --- a/src/legacy/core_plugins/vis_type_xy/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_xy/public/legacy.ts @@ -22,20 +22,16 @@ import { PluginInitializerContext } from 'kibana/public'; import { plugin } from '.'; import { VisTypeXyPluginSetupDependencies, VisTypeXyPluginStartDependencies } from './plugin'; -import { - setup as visualizationsSetup, - start as visualizationsStart, -} from '../../visualizations/public/np_ready/public/legacy'; const setupPlugins: Readonly = { expressions: npSetup.plugins.expressions, - visualizations: visualizationsSetup, + visualizations: npSetup.plugins.visualizations, charts: npSetup.plugins.charts, }; const startPlugins: Readonly = { expressions: npStart.plugins.expressions, - visualizations: visualizationsStart, + visualizations: npStart.plugins.visualizations, }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_xy/public/plugin.ts b/src/legacy/core_plugins/vis_type_xy/public/plugin.ts index 35abb04fd8732..ab01b6b3153fb 100644 --- a/src/legacy/core_plugins/vis_type_xy/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_xy/public/plugin.ts @@ -26,7 +26,10 @@ import { } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; -import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public'; +import { + VisualizationsSetup, + VisualizationsStart, +} from '../../../../plugins/visualizations/public'; import { ChartsPluginSetup } from '../../../../plugins/charts/public'; export interface VisTypeXyDependencies { @@ -47,10 +50,10 @@ export interface VisTypeXyPluginStartDependencies { visualizations: VisualizationsStart; } -type VisTypeXyCoreSetup = CoreSetup; +type VisTypeXyCoreSetup = CoreSetup; /** @internal */ -export class VisTypeXyPlugin implements Plugin, void> { +export class VisTypeXyPlugin implements Plugin { constructor(public initializerContext: PluginInitializerContext) {} public async setup( diff --git a/src/legacy/core_plugins/visualizations/package.json b/src/legacy/core_plugins/visualizations/package.json deleted file mode 100644 index 5b436f0c2fef2..0000000000000 --- a/src/legacy/core_plugins/visualizations/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "visualizations", - "version": "kibana" -} diff --git a/src/legacy/core_plugins/visualizations/public/index.scss b/src/legacy/core_plugins/visualizations/public/index.scss deleted file mode 100644 index 238f58fbfa295..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'src/legacy/ui/public/styles/styling_constants'; -@import './np_ready/public/index'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json b/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json deleted file mode 100644 index f8637a71b2d35..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "visualizations", - "version": "kibana", - "server": false, - "ui": true, - "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection"] -} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts deleted file mode 100644 index 078cc4a3f4035..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Visualizations Plugin - public - * - * This is the entry point for the entire client-side public contract of the plugin. - * If something is not explicitly exported here, you can safely assume it is private - * to the plugin and not considered stable. - * - * All stateful contracts will be injected by the platform at runtime, and are defined - * in the setup/start interfaces in `plugin.ts`. The remaining items exported here are - * either types, or static code. - */ - -import { PublicContract } from '@kbn/utility-types'; -import { PluginInitializerContext } from '../../../../../../core/public'; -import { VisualizationsPlugin, VisualizationsSetup, VisualizationsStart } from './plugin'; - -/** @public */ -export { VisualizationsSetup, VisualizationsStart }; - -/** @public types */ -export { VisTypeAlias, VisType } from './vis_types'; -export { VisSavedObject } from './types'; -export { Vis, VisParams, SerializedVis, SerializedVisData, VisData } from './vis'; -import { VisualizeEmbeddableFactory, VisualizeEmbeddable } from './embeddable'; -export type VisualizeEmbeddableFactoryContract = PublicContract; -export type VisualizeEmbeddableContract = PublicContract; -export { TypesService } from './vis_types/types_service'; -export { VISUALIZE_EMBEDDABLE_TYPE, VisualizeInput } from './embeddable'; -export { SchemaConfig } from './legacy/build_pipeline'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new VisualizationsPlugin(initializerContext); -} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js deleted file mode 100644 index deb345a77cdb6..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/_vis.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { start as visualizations } from '../../legacy'; - -describe('Vis Class', function() { - let indexPattern; - let visTypes; - - let vis; - const stateFixture = { - type: 'pie', - aggs: [ - { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }, - { type: 'terms', schema: 'segment', params: { field: 'geo.src' } }, - ], - params: { isDonut: true }, - listeners: { click: _.noop }, - }; - - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject(function(Private) { - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - visTypes = visualizations; - }) - ); - - beforeEach(function() { - vis = visualizations.createVis(indexPattern, stateFixture); - }); - - const verifyVis = function(vis) { - expect(vis).to.have.property('aggs'); - expect(vis.aggs.aggs).to.have.length(3); - - expect(vis).to.have.property('type'); - expect(vis.type).to.eql(visTypes.get('pie')); - - expect(vis).to.have.property('params'); - expect(vis.params).to.have.property('isDonut', true); - expect(vis).to.have.property('indexPattern', indexPattern); - }; - - describe('initialization', function() { - it('should set the state', function() { - verifyVis(vis); - }); - }); - - describe('getState()', function() { - it('should get a state that represents the... er... state', function() { - const state = vis.getEnabledState(); - expect(state).to.have.property('type', 'pie'); - - expect(state).to.have.property('params'); - expect(state.params).to.have.property('isDonut', true); - - expect(state).to.have.property('aggs'); - expect(state.aggs).to.have.length(3); - }); - }); - - describe('setState()', function() { - it('should set the state to defaults', function() { - const vis = visualizations.createVis(indexPattern); - expect(vis).to.have.property('type'); - expect(vis.type).to.eql(visTypes.get('histogram')); - expect(vis).to.have.property('aggs'); - expect(vis.aggs.aggs).to.have.length(1); - expect(vis).to.have.property('params'); - expect(vis.params).to.have.property('addLegend', true); - expect(vis.params).to.have.property('addTooltip', true); - }); - }); - - describe('isHierarchical()', function() { - it('should return true for hierarchical vis (like pie)', function() { - expect(vis.isHierarchical()).to.be(true); - }); - it('should return false for non-hierarchical vis (like histogram)', function() { - const vis = visualizations.createVis(indexPattern); - expect(vis.isHierarchical()).to.be(false); - }); - }); -}); diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/base_vis_type.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/base_vis_type.js deleted file mode 100644 index 9c1dfd9780255..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/base_vis_type.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { BaseVisType } from '../../../vis_types/base_vis_type'; - -describe('Base Vis Type', function() { - beforeEach(ngMock.module('kibana')); - - describe('initialization', () => { - it('should throw if mandatory properties are missing', () => { - expect(() => { - new BaseVisType({}); - }).to.throwError('vis_type must define its name'); - - expect(() => { - new BaseVisType({ name: 'test' }); - }).to.throwError('vis_type must define its title'); - - expect(() => { - new BaseVisType({ name: 'test', title: 'test' }); - }).to.throwError('vis_type must define its description'); - - expect(() => { - new BaseVisType({ name: 'test', title: 'test', description: 'test' }); - }).to.throwError('vis_type must define its icon or image'); - - expect(() => { - new BaseVisType({ name: 'test', title: 'test', description: 'test', icon: 'test' }); - }).to.throwError('vis_type must define visualization controller'); - - expect(() => { - new BaseVisType({ - name: 'test', - title: 'test', - description: 'test', - icon: 'test', - visualization: {}, - }); - }).to.not.throwError(); - }); - }); -}); diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts deleted file mode 100644 index dcd11c920f17c..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { CoreSetup, PluginInitializerContext } from '../../../../../../core/public'; -import { VisualizationsSetup, VisualizationsStart } from './'; -import { VisualizationsPlugin } from './plugin'; -import { coreMock } from '../../../../../../core/public/mocks'; -import { embeddablePluginMock } from '../../../../../../plugins/embeddable/public/mocks'; -import { expressionsPluginMock } from '../../../../../../plugins/expressions/public/mocks'; -import { dataPluginMock } from '../../../../../../plugins/data/public/mocks'; -import { usageCollectionPluginMock } from '../../../../../../plugins/usage_collection/public/mocks'; -import { uiActionsPluginMock } from '../../../../../../plugins/ui_actions/public/mocks'; -import { VisualizationsStartDeps } from './plugin'; - -const createSetupContract = (): VisualizationsSetup => ({ - createBaseVisualization: jest.fn(), - createReactVisualization: jest.fn(), - registerAlias: jest.fn(), - hideTypes: jest.fn(), -}); - -const createStartContract = (): VisualizationsStart => ({ - get: jest.fn(), - all: jest.fn(), - getAliases: jest.fn(), - savedVisualizationsLoader: {} as any, - showNewVisModal: jest.fn(), - createVis: jest.fn(), - convertFromSerializedVis: jest.fn(), - convertToSerializedVis: jest.fn(), -}); - -const createInstance = async () => { - const plugin = new VisualizationsPlugin({} as PluginInitializerContext); - - const setup = plugin.setup(coreMock.createSetup() as CoreSetup, { - data: dataPluginMock.createSetupContract(), - expressions: expressionsPluginMock.createSetupContract(), - embeddable: embeddablePluginMock.createSetupContract(), - usageCollection: usageCollectionPluginMock.createSetupContract(), - }); - const doStart = () => - plugin.start(coreMock.createStart(), { - data: dataPluginMock.createStartContract(), - expressions: expressionsPluginMock.createStartContract(), - uiActions: uiActionsPluginMock.createStartContract(), - }); - - return { - plugin, - setup, - doStart, - }; -}; - -export const visualizationsPluginMock = { - createSetupContract, - createStartContract, - createInstance, -}; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts deleted file mode 100644 index c826841e2bcf3..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { - PluginInitializerContext, - CoreSetup, - CoreStart, - Plugin, -} from '../../../../../../core/public'; -import { TypesService, TypesSetup, TypesStart } from './vis_types'; -import { - setUISettings, - setTypes, - setI18n, - setCapabilities, - setHttp, - setIndexPatterns, - setSavedObjects, - setUsageCollector, - setFilterManager, - setExpressions, - setUiActions, - setSavedVisualizationsLoader, - setTimeFilter, - setAggs, - setChrome, - setOverlays, -} from './services'; -import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeEmbeddableFactory } from './embeddable'; -import { ExpressionsSetup, ExpressionsStart } from '../../../../../../plugins/expressions/public'; -import { EmbeddableSetup } from '../../../../../../plugins/embeddable/public'; -import { visualization as visualizationFunction } from './expressions/visualization_function'; -import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; -import { - DataPublicPluginSetup, - DataPublicPluginStart, -} from '../../../../../../plugins/data/public'; -import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; -import { createSavedVisLoader, SavedVisualizationsLoader } from './saved_visualizations'; -import { SerializedVis, Vis } from './vis'; -import { showNewVisModal } from './wizard'; -import { UiActionsStart } from '../../../../../../plugins/ui_actions/public'; -import { - convertFromSerializedVis, - convertToSerializedVis, -} from './saved_visualizations/_saved_vis'; - -/** - * Interface for this plugin's returned setup/start contracts. - * - * @public - */ - -export type VisualizationsSetup = TypesSetup; - -export interface VisualizationsStart extends TypesStart { - savedVisualizationsLoader: SavedVisualizationsLoader; - createVis: (visType: string, visState?: SerializedVis) => Vis; - convertToSerializedVis: typeof convertToSerializedVis; - convertFromSerializedVis: typeof convertFromSerializedVis; - showNewVisModal: typeof showNewVisModal; -} - -export interface VisualizationsSetupDeps { - expressions: ExpressionsSetup; - embeddable: EmbeddableSetup; - usageCollection: UsageCollectionSetup; - data: DataPublicPluginSetup; -} - -export interface VisualizationsStartDeps { - data: DataPublicPluginStart; - expressions: ExpressionsStart; - uiActions: UiActionsStart; -} - -/** - * Visualizations Plugin - public - * - * This plugin's stateful contracts are returned from the `setup` and `start` methods - * below. The interfaces for these contracts are provided above. - * - * @internal - */ -export class VisualizationsPlugin - implements - Plugin< - VisualizationsSetup, - VisualizationsStart, - VisualizationsSetupDeps, - VisualizationsStartDeps - > { - private readonly types: TypesService = new TypesService(); - - constructor(initializerContext: PluginInitializerContext) {} - - public setup( - core: CoreSetup, - { expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps - ): VisualizationsSetup { - setUISettings(core.uiSettings); - setUsageCollector(usageCollection); - - expressions.registerFunction(visualizationFunction); - expressions.registerRenderer(visualizationRenderer); - - const embeddableFactory = new VisualizeEmbeddableFactory( - async () => (await core.getStartServices())[1].uiActions - ); - embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); - - return { - ...this.types.setup(), - }; - } - - public start( - core: CoreStart, - { data, expressions, uiActions }: VisualizationsStartDeps - ): VisualizationsStart { - const types = this.types.start(); - setI18n(core.i18n); - setTypes(types); - setCapabilities(core.application.capabilities); - setHttp(core.http); - setSavedObjects(core.savedObjects); - setIndexPatterns(data.indexPatterns); - setFilterManager(data.query.filterManager); - setExpressions(expressions); - setUiActions(uiActions); - setTimeFilter(data.query.timefilter.timefilter); - setAggs(data.search.aggs); - setOverlays(core.overlays); - setChrome(core.chrome); - const savedVisualizationsLoader = createSavedVisLoader({ - savedObjectsClient: core.savedObjects.client, - indexPatterns: data.indexPatterns, - chrome: core.chrome, - overlays: core.overlays, - visualizationTypes: types, - }); - setSavedVisualizationsLoader(savedVisualizationsLoader); - - return { - ...types, - showNewVisModal, - /** - * creates new instance of Vis - * @param {IIndexPattern} indexPattern - index pattern to use - * @param {VisState} visState - visualization configuration - */ - createVis: (visType: string, visState?: SerializedVis) => new Vis(visType, visState), - convertToSerializedVis, - convertFromSerializedVis, - savedVisualizationsLoader, - }; - } - - public stop() { - this.types.stop(); - } -} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts deleted file mode 100644 index 8f93a179af3bc..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SavedObject } from '../../../../../../plugins/saved_objects/public'; -import { ISearchSource, AggConfigOptions } from '../../../../../../plugins/data/public'; -import { SerializedVis, Vis, VisParams } from './vis'; - -export { Vis, SerializedVis, VisParams }; - -export interface VisualizationController { - render(visData: any, visParams: any): Promise; - destroy(): void; - isLoaded?(): Promise | void; -} - -export interface SavedVisState { - type: string; - params: VisParams; - aggs: AggConfigOptions[]; -} - -export interface ISavedVis { - id: string; - title: string; - description?: string; - visState: SavedVisState; - searchSource?: ISearchSource; - uiStateJSON?: string; - savedSearchRefName?: string; - savedSearchId?: string; -} - -// @ts-ignore-next-line -export interface VisSavedObject extends SavedObject, ISavedVis {} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/base_vis_type.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/base_vis_type.js deleted file mode 100644 index 50ff74cfe9dd3..0000000000000 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/base_vis_type.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -export class BaseVisType { - constructor(opts = {}) { - if (!opts.name) { - throw 'vis_type must define its name'; - } - if (!opts.title) { - throw 'vis_type must define its title'; - } - if (!opts.description) { - throw 'vis_type must define its description'; - } - if (!opts.icon && !opts.image) { - throw 'vis_type must define its icon or image'; - } - if (!opts.visualization) { - throw 'vis_type must define visualization controller'; - } - - const _defaults = { - // name, title, description, icon, image - visualization: null, // must be a class with render/resize/destroy methods - visConfig: { - defaults: {}, // default configuration - }, - requestHandler: 'courier', // select one from registry or pass a function - responseHandler: 'none', - editor: null, // no default is provided - editorConfig: { - collections: {}, // collections used for configuration (list of positions, ...) - }, - options: { - // controls the visualize editor - showTimePicker: true, - showQueryBar: true, - showFilterBar: true, - showIndexSelection: true, - hierarchicalData: false, // we should get rid of this i guess ? - }, - stage: 'production', - feedbackMessage: '', - hidden: false, - }; - - _.defaultsDeep(this, opts, _defaults); - - this.requiresSearch = this.requestHandler !== 'none'; - } - - shouldMarkAsExperimentalInUI() { - return this.stage === 'experimental'; - } - - get schemas() { - if (this.editorConfig && this.editorConfig.schemas) { - return this.editorConfig.schemas; - } - return []; - } -} diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index 769d9ba311281..4b7618712cdd8 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -263,7 +263,7 @@ export default () => .allow(''), emsFileApiUrl: Joi.string().default('https://vector.maps.elastic.co'), emsTileApiUrl: Joi.string().default('https://tiles.maps.elastic.co'), - emsLandingPageUrl: Joi.string().default('https://maps.elastic.co/v7.6'), + emsLandingPageUrl: Joi.string().default('https://maps.elastic.co/v7.7'), emsFontLibraryUrl: Joi.string().default( 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf' ), diff --git a/src/legacy/server/http/index.js b/src/legacy/server/http/index.js index d616afb533d0a..3649987d89b9a 100644 --- a/src/legacy/server/http/index.js +++ b/src/legacy/server/http/index.js @@ -18,7 +18,6 @@ */ import { format } from 'url'; -import { resolve } from 'path'; import _ from 'lodash'; import Boom from 'boom'; @@ -32,22 +31,6 @@ export default async function(kbnServer, server, config) { await registerHapiPlugins(server); - // provide a simple way to expose static directories - server.decorate('server', 'exposeStaticDir', function(routePath, dirPath) { - this.route({ - path: routePath, - method: 'GET', - handler: { - directory: { - path: dirPath, - listing: false, - lookupCompressed: true, - }, - }, - config: { auth: false }, - }); - }); - // helper for creating view managers for servers server.decorate('server', 'setupViews', function(path, engines) { this.views({ @@ -77,7 +60,4 @@ export default async function(kbnServer, server, config) { .permanent(true); }, }); - - // Expose static assets - server.exposeStaticDir('/ui/{path*}', resolve(__dirname, '../../ui/public/assets')); } diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index d222dbb550f11..d43ddf581da90 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -39,9 +39,6 @@ import { LegacyServiceDiscoverPlugins, } from '../../core/server'; -// Disable lint errors for imports from src/core/server/saved_objects until SavedObjects migration is complete -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SavedObjectsManagement } from '../../core/server/saved_objects/management'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LegacyConfig, ILegacyService, ILegacyInternals } from '../../core/server/legacy'; import { ApmOssPlugin } from '../core_plugins/apm_oss'; @@ -78,7 +75,6 @@ declare module 'hapi' { addScopedTutorialContextFactory: ( scopedTutorialContextFactory: (...args: any[]) => any ) => void; - getSavedObjectsManagement(): SavedObjectsManagement; getInjectedUiAppVars: (pluginName: string) => { [key: string]: any }; getUiNavLinks(): Array<{ _id: string }>; addMemoizedFactoryToRequest: ( diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index 6991527a9503c..e06212d87e3e3 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -199,8 +199,7 @@ export default class KbnServer { } applyLoggingConfiguration(settings) { - const config = new Config(this.config.getSchema(), settings); - + const config = Config.withDefaultSchema(settings); const loggingOptions = loggingConfiguration(config); const subset = { ops: config.get('ops'), diff --git a/src/legacy/server/plugins/lib/plugin.js b/src/legacy/server/plugins/lib/plugin.js index e73f1bf2c4d38..2b392d13d595a 100644 --- a/src/legacy/server/plugins/lib/plugin.js +++ b/src/legacy/server/plugins/lib/plugin.js @@ -73,7 +73,10 @@ export class Plugin { }); if (this.publicDir) { - server.exposeStaticDir(`/plugins/${id}/{path*}`, this.publicDir); + server.newPlatform.__internals.http.registerStaticDir( + `/plugins/${id}/{path*}`, + this.publicDir + ); } // Many of the plugins are simply adding static assets to the server and we don't need diff --git a/src/legacy/server/sass/build.js b/src/legacy/server/sass/build.js index 3d892ce321c2e..1ec656786ccc5 100644 --- a/src/legacy/server/sass/build.js +++ b/src/legacy/server/sass/build.js @@ -34,7 +34,7 @@ const access = promisify(fs.access); const copyFile = promisify(fs.copyFile); const mkdirAsync = promisify(fs.mkdir); -const UI_ASSETS_DIR = resolve(__dirname, '../../ui/public/assets'); +const UI_ASSETS_DIR = resolve(__dirname, '../../../core/server/core_app/assets'); const DARK_THEME_IMPORTER = url => { if (url.includes('eui_colors_light')) { return { file: url.replace('eui_colors_light', 'eui_colors_dark') }; diff --git a/src/legacy/server/saved_objects/saved_objects_mixin.js b/src/legacy/server/saved_objects/saved_objects_mixin.js index cc63099c8a211..bcf766231dc9c 100644 --- a/src/legacy/server/saved_objects/saved_objects_mixin.js +++ b/src/legacy/server/saved_objects/saved_objects_mixin.js @@ -29,7 +29,6 @@ import { } from '../../../core/server/saved_objects'; import { getRootPropertiesObjects } from '../../../core/server/saved_objects/mappings'; import { convertTypesToLegacySchema } from '../../../core/server/saved_objects/utils'; -import { SavedObjectsManagement } from '../../../core/server/saved_objects/management'; export function savedObjectsMixin(kbnServer, server) { const migrator = kbnServer.newPlatform.__internals.kibanaMigrator; @@ -40,11 +39,6 @@ export function savedObjectsMixin(kbnServer, server) { const visibleTypes = allTypes.filter(type => !schema.isHiddenType(type)); server.decorate('server', 'kibanaMigrator', migrator); - server.decorate( - 'server', - 'getSavedObjectsManagement', - () => new SavedObjectsManagement(typeRegistry) - ); const warn = message => server.log(['warning', 'saved-objects'], message); // we use kibana.index which is technically defined in the kibana plugin, so if @@ -84,8 +78,13 @@ export function savedObjectsMixin(kbnServer, server) { const provider = kbnServer.newPlatform.__internals.savedObjectsClientProvider; + const importAndExportableTypes = typeRegistry + .getImportableAndExportableTypes() + .map(type => type.name); + const service = { types: visibleTypes, + importAndExportableTypes, SavedObjectsClient, SavedObjectsRepository, getSavedObjectsRepository: createRepository, diff --git a/src/legacy/server/saved_objects/saved_objects_mixin.test.js b/src/legacy/server/saved_objects/saved_objects_mixin.test.js index 3745f0b92123c..3fa9f9a936988 100644 --- a/src/legacy/server/saved_objects/saved_objects_mixin.test.js +++ b/src/legacy/server/saved_objects/saved_objects_mixin.test.js @@ -183,7 +183,7 @@ describe('Saved Objects Mixin', () => { 'kibanaMigrator', expect.any(Object) ); - expect(mockServer.decorate).toHaveBeenCalledTimes(2); + expect(mockServer.decorate).toHaveBeenCalledTimes(1); expect(mockServer.route).not.toHaveBeenCalled(); }); }); diff --git a/src/legacy/server/status/index.js b/src/legacy/server/status/index.js index a9544049182a7..df02b3c45ec2f 100644 --- a/src/legacy/server/status/index.js +++ b/src/legacy/server/status/index.js @@ -57,7 +57,7 @@ export function statusMixin(kbnServer, server, config) { // init routes registerStatusPage(kbnServer, server, config); registerStatusApi(kbnServer, server, config); - registerStatsApi(usageCollection, server, config); + registerStatsApi(usageCollection, server, config, kbnServer); // expore shared functionality server.decorate('server', 'getOSInfo', getOSInfo); diff --git a/src/legacy/server/status/routes/api/register_stats.js b/src/legacy/server/status/routes/api/register_stats.js index e218c1caf1701..2dd66cb8caff7 100644 --- a/src/legacy/server/status/routes/api/register_stats.js +++ b/src/legacy/server/status/routes/api/register_stats.js @@ -21,7 +21,7 @@ import Joi from 'joi'; import boom from 'boom'; import { i18n } from '@kbn/i18n'; import { wrapAuthConfig } from '../../wrap_auth_config'; -import { KIBANA_STATS_TYPE } from '../../constants'; +import { getKibanaInfoForStats } from '../../lib'; const STATS_NOT_READY_MESSAGE = i18n.translate('server.stats.notReadyMessage', { defaultMessage: 'Stats are not ready yet. Please try again later.', @@ -37,7 +37,7 @@ const STATS_NOT_READY_MESSAGE = i18n.translate('server.stats.notReadyMessage', { * - Any other value causes a statusCode 400 response (Bad Request) * Including ?exclude_usage in the query string excludes the usage stats from the response. Same value semantics as ?extended */ -export function registerStatsApi(usageCollection, server, config) { +export function registerStatsApi(usageCollection, server, config, kbnServer) { const wrapAuth = wrapAuthConfig(config.get('status.allowAnonymous')); const getClusterUuid = async callCluster => { @@ -50,6 +50,17 @@ export function registerStatsApi(usageCollection, server, config) { return usageCollection.toObject(usage); }; + let lastMetrics = null; + /* kibana_stats gets singled out from the collector set as it is used + * for health-checking Kibana and fetch does not rely on fetching data + * from ES */ + server.newPlatform.setup.core.metrics.getOpsMetrics$().subscribe(metrics => { + lastMetrics = { + ...metrics, + timestamp: new Date().toISOString(), + }; + }); + server.route( wrapAuth({ method: 'GET', @@ -133,15 +144,15 @@ export function registerStatsApi(usageCollection, server, config) { } } - /* kibana_stats gets singled out from the collector set as it is used - * for health-checking Kibana and fetch does not rely on fetching data - * from ES */ - const kibanaStatsCollector = usageCollection.getCollectorByType(KIBANA_STATS_TYPE); - if (!(await kibanaStatsCollector.isReady())) { + if (!lastMetrics) { return boom.serverUnavailable(STATS_NOT_READY_MESSAGE); } - let kibanaStats = await kibanaStatsCollector.fetch(); - kibanaStats = usageCollection.toApiFieldNames(kibanaStats); + const kibanaStats = usageCollection.toApiFieldNames({ + ...lastMetrics, + kibana: getKibanaInfoForStats(server, kbnServer), + last_updated: new Date().toISOString(), + collection_interval_in_millis: config.get('ops.interval'), + }); return { ...kibanaStats, diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js index f96f194108ff9..21a937bf1fb66 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js +++ b/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js @@ -18,7 +18,58 @@ */ import { buildHierarchicalData } from './build_hierarchical_data'; -import { tableVisResponseHandler } from '../../../../core_plugins/vis_type_table/public/table_vis_response_handler'; + +function tableVisResponseHandler(table, dimensions) { + const converted = { + tables: [], + }; + + const split = dimensions.splitColumn || dimensions.splitRow; + + if (split) { + converted.direction = dimensions.splitRow ? 'row' : 'column'; + const splitColumnIndex = split[0].accessor; + const splitColumn = table.columns[splitColumnIndex]; + const splitMap = {}; + let splitIndex = 0; + + table.rows.forEach((row, rowIndex) => { + const splitValue = row[splitColumn.id]; + + if (!splitMap.hasOwnProperty(splitValue)) { + splitMap[splitValue] = splitIndex++; + const tableGroup = { + $parent: converted, + title: `splitValue: ${splitColumn.name}`, + name: splitColumn.name, + key: splitValue, + column: splitColumnIndex, + row: rowIndex, + table, + tables: [], + }; + + tableGroup.tables.push({ + $parent: tableGroup, + columns: table.columns, + rows: [], + }); + + converted.tables.push(tableGroup); + } + + const tableIndex = splitMap[splitValue]; + converted.tables[tableIndex].tables[0].rows.push(row); + }); + } else { + converted.tables.push({ + columns: table.columns, + rows: table.rows, + }); + } + + return converted; +} jest.mock('ui/new_platform'); jest.mock('ui/chrome', () => ({ diff --git a/src/legacy/ui/public/new_platform/__mocks__/helpers.ts b/src/legacy/ui/public/new_platform/__mocks__/helpers.ts index 6f6b4be86f58d..f9f4494929014 100644 --- a/src/legacy/ui/public/new_platform/__mocks__/helpers.ts +++ b/src/legacy/ui/public/new_platform/__mocks__/helpers.ts @@ -30,6 +30,8 @@ import { usageCollectionPluginMock } from '../../../../../plugins/usage_collecti import { kibanaLegacyPluginMock } from '../../../../../plugins/kibana_legacy/public/mocks'; import { chartPluginMock } from '../../../../../plugins/charts/public/mocks'; import { advancedSettingsMock } from '../../../../../plugins/advanced_settings/public/mocks'; +import { savedObjectsManagementPluginMock } from '../../../../../plugins/saved_objects_management/public/mocks'; +import { visualizationsPluginMock } from '../../../../../plugins/visualizations/public/mocks'; /* eslint-enable @kbn/eslint/no-restricted-paths */ export const pluginsMock = { @@ -43,7 +45,9 @@ export const pluginsMock = { uiActions: uiActionsPluginMock.createSetupContract(), usageCollection: usageCollectionPluginMock.createSetupContract(), advancedSettings: advancedSettingsMock.createSetupContract(), + visualizations: visualizationsPluginMock.createSetupContract(), kibanaLegacy: kibanaLegacyPluginMock.createSetupContract(), + savedObjectsManagement: savedObjectsManagementPluginMock.createSetupContract(), }), createStart: () => ({ data: dataPluginMock.createStartContract(), @@ -55,7 +59,9 @@ export const pluginsMock = { uiActions: uiActionsPluginMock.createStartContract(), management: managementPluginMock.createStartContract(), advancedSettings: advancedSettingsMock.createStartContract(), + visualizations: visualizationsPluginMock.createStartContract(), kibanaLegacy: kibanaLegacyPluginMock.createStartContract(), + savedObjectsManagement: savedObjectsManagementPluginMock.createStartContract(), }), }; diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 67877c5382633..25647e4a08897 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -20,20 +20,7 @@ import sinon from 'sinon'; import { getFieldFormatsRegistry } from '../../../../test_utils/public/stub_field_formats'; import { METRIC_TYPE } from '@kbn/analytics'; -import { - setFieldFormats, - setIndexPatterns, - setInjectedMetadata, - setHttp, - setNotifications, - setOverlays, - setQueryService, - setSearchService, - setUiSettings, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../plugins/data/public/services'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { setAggs } from '../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/services'; +import { setSetupServices, setStartServices } from './set_services'; import { AggTypesRegistry, getAggTypes, @@ -57,6 +44,10 @@ const mockComponent = () => { return null; }; +let refreshInterval = undefined; +let isTimeRangeSelectorEnabled = true; +let isAutoRefreshSelectorEnabled = true; + export const mockUiSettings = { get: item => { return mockUiSettings[item]; @@ -64,6 +55,7 @@ export const mockUiSettings = { getUpdate$: () => ({ subscribe: sinon.fake(), }), + isDefault: sinon.fake(), 'query:allowLeadingWildcards': true, 'query:queryString:options': {}, 'courier:ignoreFilterIfFieldNotInIndex': true, @@ -71,20 +63,110 @@ export const mockUiSettings = { 'format:defaultTypeMap': {}, }; -const mockCore = { +const mockCoreSetup = { chrome: {}, + http: { + basePath: { + get: sinon.fake.returns(''), + }, + }, + injectedMetadata: {}, uiSettings: mockUiSettings, +}; + +const mockCoreStart = { + application: { + capabilities: {}, + }, + chrome: { + overlays: { + openModal: sinon.fake(), + }, + }, http: { basePath: { get: sinon.fake.returns(''), }, }, + i18n: {}, + overlays: {}, + savedObjects: { + client: {}, + }, + uiSettings: mockUiSettings, +}; + +const querySetup = { + state$: mockObservable(), + filterManager: { + getFetches$: sinon.fake(), + getFilters: sinon.fake(), + getAppFilters: sinon.fake(), + getGlobalFilters: sinon.fake(), + removeFilter: sinon.fake(), + addFilters: sinon.fake(), + setFilters: sinon.fake(), + removeAll: sinon.fake(), + getUpdates$: mockObservable, + }, + timefilter: { + timefilter: { + getFetch$: mockObservable, + getAutoRefreshFetch$: mockObservable, + getEnabledUpdated$: mockObservable, + getTimeUpdate$: mockObservable, + getRefreshIntervalUpdate$: mockObservable, + isTimeRangeSelectorEnabled: () => { + return isTimeRangeSelectorEnabled; + }, + isAutoRefreshSelectorEnabled: () => { + return isAutoRefreshSelectorEnabled; + }, + disableAutoRefreshSelector: () => { + isAutoRefreshSelectorEnabled = false; + }, + enableAutoRefreshSelector: () => { + isAutoRefreshSelectorEnabled = true; + }, + getRefreshInterval: () => { + return refreshInterval; + }, + setRefreshInterval: interval => { + refreshInterval = interval; + }, + enableTimeRangeSelector: () => { + isTimeRangeSelectorEnabled = true; + }, + disableTimeRangeSelector: () => { + isTimeRangeSelectorEnabled = false; + }, + getTime: sinon.fake(), + setTime: sinon.fake(), + getActiveBounds: sinon.fake(), + getBounds: sinon.fake(), + calculateBounds: sinon.fake(), + createFilter: sinon.fake(), + }, + history: sinon.fake(), + }, + savedQueries: { + saveQuery: sinon.fake(), + getAllSavedQueries: sinon.fake(), + findSavedQueries: sinon.fake(), + getSavedQuery: sinon.fake(), + deleteSavedQuery: sinon.fake(), + getSavedQueryCount: sinon.fake(), + }, }; const mockAggTypesRegistry = () => { const registry = new AggTypesRegistry(); const registrySetup = registry.setup(); - const aggTypes = getAggTypes({ uiSettings: mockCore.uiSettings }); + const aggTypes = getAggTypes({ + uiSettings: mockCoreSetup.uiSettings, + notifications: mockCoreStart.notifications, + query: querySetup, + }); aggTypes.buckets.forEach(type => registrySetup.registerBucket(type)); aggTypes.metrics.forEach(type => registrySetup.registerMetric(type)); @@ -93,12 +175,8 @@ const mockAggTypesRegistry = () => { const aggTypesRegistry = mockAggTypesRegistry(); -let refreshInterval = undefined; -let isTimeRangeSelectorEnabled = true; -let isAutoRefreshSelectorEnabled = true; - export const npSetup = { - core: mockCore, + core: mockCoreSetup, plugins: { advancedSettings: { component: { @@ -135,72 +213,7 @@ export const npSetup = { addProvider: sinon.fake(), getProvider: sinon.fake(), }, - query: { - state$: mockObservable(), - filterManager: { - getFetches$: sinon.fake(), - getFilters: sinon.fake(), - getAppFilters: sinon.fake(), - getGlobalFilters: sinon.fake(), - removeFilter: sinon.fake(), - addFilters: sinon.fake(), - setFilters: sinon.fake(), - removeAll: sinon.fake(), - getUpdates$: mockObservable, - }, - timefilter: { - timefilter: { - getTime: sinon.fake(), - getRefreshInterval: sinon.fake(), - getTimeUpdate$: mockObservable, - getRefreshIntervalUpdate$: mockObservable, - getFetch$: mockObservable, - getAutoRefreshFetch$: mockObservable, - getEnabledUpdated$: mockObservable, - getTimeUpdate$: mockObservable, - getRefreshIntervalUpdate$: mockObservable, - isTimeRangeSelectorEnabled: () => { - return isTimeRangeSelectorEnabled; - }, - isAutoRefreshSelectorEnabled: () => { - return isAutoRefreshSelectorEnabled; - }, - disableAutoRefreshSelector: () => { - isAutoRefreshSelectorEnabled = false; - }, - enableAutoRefreshSelector: () => { - isAutoRefreshSelectorEnabled = true; - }, - getRefreshInterval: () => { - return refreshInterval; - }, - setRefreshInterval: interval => { - refreshInterval = interval; - }, - enableTimeRangeSelector: () => { - isTimeRangeSelectorEnabled = true; - }, - disableTimeRangeSelector: () => { - isTimeRangeSelectorEnabled = false; - }, - getTime: sinon.fake(), - setTime: sinon.fake(), - getActiveBounds: sinon.fake(), - getBounds: sinon.fake(), - calculateBounds: sinon.fake(), - createFilter: sinon.fake(), - }, - history: sinon.fake(), - }, - savedQueries: { - saveQuery: sinon.fake(), - getAllSavedQueries: sinon.fake(), - findSavedQueries: sinon.fake(), - getSavedQuery: sinon.fake(), - deleteSavedQuery: sinon.fake(), - getSavedQueryCount: sinon.fake(), - }, - }, + query: querySetup, search: { aggs: { calculateAutoTimeExpression: sinon.fake(), @@ -213,7 +226,7 @@ export const npSetup = { }, }, }, - fieldFormats: getFieldFormatsRegistry(mockCore), + fieldFormats: getFieldFormatsRegistry(mockCoreSetup), }, share: { register: () => {}, @@ -280,17 +293,17 @@ export const npSetup = { visTypeVega: { config: sinon.fake(), }, + visualizations: { + createBaseVisualization: sinon.fake(), + createReactVisualization: sinon.fake(), + registerAlias: sinon.fake(), + hideTypes: sinon.fake(), + }, }, }; export const npStart = { - core: { - chrome: { - overlays: { - openModal: sinon.fake(), - }, - }, - }, + core: mockCoreStart, plugins: { management: { legacy: { @@ -410,7 +423,6 @@ export const npStart = { search: { aggs: { calculateAutoTimeExpression: sinon.fake(), - createAggConfigs: sinon.fake(), createAggConfigs: (indexPattern, configStates = []) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: aggTypesRegistry.start(), @@ -435,7 +447,7 @@ export const npStart = { }, }, }, - fieldFormats: getFieldFormatsRegistry(mockCore), + fieldFormats: getFieldFormatsRegistry(mockCoreStart), }, share: { toggleShareContextMenu: () => {}, @@ -457,6 +469,16 @@ export const npStart = { getTriggerActions: sinon.fake(), getTriggerCompatibleActions: sinon.fake(), }, + visualizations: { + get: sinon.fake(), + all: sinon.fake(), + getAliases: sinon.fake(), + savedVisualizationsLoader: {}, + showNewVisModal: sinon.fake(), + createVis: sinon.fake(), + convertFromSerializedVis: sinon.fake(), + convertToSerializedVis: sinon.fake(), + }, navigation: { ui: { TopNavMenu: mockComponent, @@ -483,23 +505,15 @@ export function __setup__(coreSetup) { // bootstrap an LP plugin outside of tests) npSetup.core.application.register = () => {}; - // Services that need to be set in the legacy platform since the legacy data plugin - // which previously provided them has been removed. - setInjectedMetadata(npSetup.core.injectedMetadata); + // Services that need to be set in the legacy platform since the legacy data + // & vis plugins which previously provided them have been removed. + setSetupServices(npSetup); } export function __start__(coreStart) { npStart.core = coreStart; - // Services that need to be set in the legacy platform since the legacy data plugin - // which previously provided them has been removed. - setHttp(npStart.core.http); - setNotifications(npStart.core.notifications); - setOverlays(npStart.core.overlays); - setUiSettings(npStart.core.uiSettings); - setFieldFormats(npStart.plugins.data.fieldFormats); - setIndexPatterns(npStart.plugins.data.indexPatterns); - setQueryService(npStart.plugins.data.query); - setSearchService(npStart.plugins.data.search); - setAggs(npStart.plugins.data.search.aggs); + // Services that need to be set in the legacy platform since the legacy data + // & vis plugins which previously provided them have been removed. + setStartServices(npStart); } diff --git a/src/legacy/ui/public/new_platform/new_platform.test.ts b/src/legacy/ui/public/new_platform/new_platform.test.ts index dd41093f3a1f0..1629aac588a61 100644 --- a/src/legacy/ui/public/new_platform/new_platform.test.ts +++ b/src/legacy/ui/public/new_platform/new_platform.test.ts @@ -20,19 +20,8 @@ jest.mock('history'); import { setRootControllerMock, historyMock } from './new_platform.test.mocks'; -import { - legacyAppRegister, - __reset__, - __setup__, - __start__, - PluginsSetup, - PluginsStart, -} from './new_platform'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import * as dataServices from '../../../../plugins/data/public/services'; -import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public'; +import { legacyAppRegister, __reset__, __setup__, __start__ } from './new_platform'; import { coreMock } from '../../../../core/public/mocks'; -import { npSetup, npStart } from './__mocks__'; describe('ui/new_platform', () => { describe('legacyAppRegister', () => { @@ -119,25 +108,4 @@ describe('ui/new_platform', () => { expect(unmountMock).toHaveBeenCalled(); }); }); - - describe('service getters', () => { - const services: Record = dataServices; - const getters = Object.keys(services).filter(k => k.substring(0, 3) === 'get'); - - getters.forEach(g => { - it(`sets a value for ${g}`, () => { - __reset__(); - __setup__( - (coreMock.createSetup() as unknown) as LegacyCoreSetup, - (npSetup.plugins as unknown) as PluginsSetup - ); - __start__( - (coreMock.createStart() as unknown) as LegacyCoreStart, - (npStart.plugins as unknown) as PluginsStart - ); - - expect(services[g]()).toBeDefined(); - }); - }); - }); }); diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index b315abec1a64b..b4b5099081759 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -23,6 +23,7 @@ import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public'; import { EmbeddableStart, EmbeddableSetup } from 'src/plugins/embeddable/public'; import { createBrowserHistory } from 'history'; import { DashboardStart } from '../../../../plugins/dashboard/public'; +import { setSetupServices, setStartServices } from './set_services'; import { LegacyCoreSetup, LegacyCoreStart, @@ -31,18 +32,6 @@ import { ScopedHistory, } from '../../../../core/public'; import { Plugin as DataPlugin } from '../../../../plugins/data/public'; -import { - setFieldFormats, - setIndexPatterns, - setInjectedMetadata, - setHttp, - setNotifications, - setOverlays, - setQueryService, - setSearchService, - setUiSettings, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../plugins/data/public/services'; import { Plugin as ExpressionsPlugin } from '../../../../plugins/expressions/public'; import { Setup as InspectorSetup, @@ -67,6 +56,14 @@ import { } from '../../../../plugins/navigation/public'; import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public'; import { DiscoverSetup, DiscoverStart } from '../../../../plugins/discover/public'; +import { + SavedObjectsManagementPluginSetup, + SavedObjectsManagementPluginStart, +} from '../../../../plugins/saved_objects_management/public'; +import { + VisualizationsSetup, + VisualizationsStart, +} from '../../../../plugins/visualizations/public'; export interface PluginsSetup { bfetch: BfetchPublicSetup; @@ -86,7 +83,9 @@ export interface PluginsSetup { management: ManagementSetup; visTypeVega: VisTypeVegaSetup; discover: DiscoverSetup; + visualizations: VisualizationsSetup; telemetry?: TelemetryPluginSetup; + savedObjectsManagement: SavedObjectsManagementPluginSetup; } export interface PluginsStart { @@ -104,8 +103,10 @@ export interface PluginsStart { management: ManagementStart; advancedSettings: AdvancedSettingsStart; discover: DiscoverStart; + visualizations: VisualizationsStart; telemetry?: TelemetryPluginStart; dashboard: DashboardStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; } export const npSetup = { @@ -137,25 +138,18 @@ export function __setup__(coreSetup: LegacyCoreSetup, plugins: PluginsSetup) { // Setup compatibility layer for AppService in legacy platform npSetup.core.application.register = legacyAppRegister; - // Services that need to be set in the legacy platform since the legacy data plugin - // which previously provided them has been removed. - setInjectedMetadata(npSetup.core.injectedMetadata); + // Services that need to be set in the legacy platform since the legacy data + // & vis plugins which previously provided them have been removed. + setSetupServices(npSetup); } export function __start__(coreStart: LegacyCoreStart, plugins: PluginsStart) { npStart.core = coreStart; npStart.plugins = plugins; - // Services that need to be set in the legacy platform since the legacy data plugin - // which previously provided them has been removed. - setHttp(npStart.core.http); - setNotifications(npStart.core.notifications); - setOverlays(npStart.core.overlays); - setUiSettings(npStart.core.uiSettings); - setFieldFormats(npStart.plugins.data.fieldFormats); - setIndexPatterns(npStart.plugins.data.indexPatterns); - setQueryService(npStart.plugins.data.query); - setSearchService(npStart.plugins.data.search); + // Services that need to be set in the legacy platform since the legacy data + // & vis plugins which previously provided them have been removed. + setStartServices(npStart); } /** Flag used to ensure `legacyAppRegister` is only called once. */ diff --git a/src/legacy/ui/public/new_platform/set_services.test.ts b/src/legacy/ui/public/new_platform/set_services.test.ts new file mode 100644 index 0000000000000..25a4524925169 --- /dev/null +++ b/src/legacy/ui/public/new_platform/set_services.test.ts @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { __reset__, __setup__, __start__, PluginsSetup, PluginsStart } from './new_platform'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import * as dataServices from '../../../../plugins/data/public/services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import * as visualizationsServices from '../../../../plugins/visualizations/public/services'; +import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public'; +import { coreMock } from '../../../../core/public/mocks'; +import { npSetup, npStart } from './__mocks__'; + +describe('ui/new_platform', () => { + describe('set service getters', () => { + const testServiceGetters = (name: string, services: Record) => { + const getters = Object.keys(services).filter(k => k.substring(0, 3) === 'get'); + getters.forEach(g => { + it(`ui/new_platform sets a value for ${name} getter ${g}`, () => { + __reset__(); + __setup__( + (coreMock.createSetup() as unknown) as LegacyCoreSetup, + (npSetup.plugins as unknown) as PluginsSetup + ); + __start__( + (coreMock.createStart() as unknown) as LegacyCoreStart, + (npStart.plugins as unknown) as PluginsStart + ); + + expect(services[g]()).toBeDefined(); + }); + }); + }; + + testServiceGetters('data', dataServices); + testServiceGetters('visualizations', visualizationsServices); + }); +}); diff --git a/src/legacy/ui/public/new_platform/set_services.ts b/src/legacy/ui/public/new_platform/set_services.ts new file mode 100644 index 0000000000000..8cf015d5dff5c --- /dev/null +++ b/src/legacy/ui/public/new_platform/set_services.ts @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { pick } from 'lodash'; + +import { PluginsSetup, PluginsStart } from './new_platform'; +import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import * as dataServices from '../../../../plugins/data/public/services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import * as visualizationsServices from '../../../../plugins/visualizations/public/services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { createSavedVisLoader } from '../../../../plugins/visualizations/public/saved_visualizations/saved_visualizations'; + +interface NpSetup { + core: LegacyCoreSetup; + plugins: PluginsSetup; +} + +interface NpStart { + core: LegacyCoreStart; + plugins: PluginsStart; +} + +export function setSetupServices(npSetup: NpSetup) { + // Services that need to be set in the legacy platform since the legacy data plugin + // which previously provided them has been removed. + dataServices.setInjectedMetadata(npSetup.core.injectedMetadata); + visualizationsServices.setUISettings(npSetup.core.uiSettings); + visualizationsServices.setUsageCollector(npSetup.plugins.usageCollection); +} + +export function setStartServices(npStart: NpStart) { + // Services that need to be set in the legacy platform since the legacy data plugin + // which previously provided them has been removed. + dataServices.setHttp(npStart.core.http); + dataServices.setNotifications(npStart.core.notifications); + dataServices.setOverlays(npStart.core.overlays); + dataServices.setUiSettings(npStart.core.uiSettings); + dataServices.setFieldFormats(npStart.plugins.data.fieldFormats); + dataServices.setIndexPatterns(npStart.plugins.data.indexPatterns); + dataServices.setQueryService(npStart.plugins.data.query); + dataServices.setSearchService(npStart.plugins.data.search); + visualizationsServices.setI18n(npStart.core.i18n); + visualizationsServices.setTypes( + pick(npStart.plugins.visualizations, ['get', 'all', 'getAliases']) + ); + visualizationsServices.setCapabilities(npStart.core.application.capabilities); + visualizationsServices.setHttp(npStart.core.http); + visualizationsServices.setSavedObjects(npStart.core.savedObjects); + visualizationsServices.setIndexPatterns(npStart.plugins.data.indexPatterns); + visualizationsServices.setFilterManager(npStart.plugins.data.query.filterManager); + visualizationsServices.setExpressions(npStart.plugins.expressions); + visualizationsServices.setUiActions(npStart.plugins.uiActions); + visualizationsServices.setTimeFilter(npStart.plugins.data.query.timefilter.timefilter); + visualizationsServices.setAggs(npStart.plugins.data.search.aggs); + visualizationsServices.setOverlays(npStart.core.overlays); + visualizationsServices.setChrome(npStart.core.chrome); + const savedVisualizationsLoader = createSavedVisLoader({ + savedObjectsClient: npStart.core.savedObjects.client, + indexPatterns: npStart.plugins.data.indexPatterns, + chrome: npStart.core.chrome, + overlays: npStart.core.overlays, + visualizationTypes: visualizationsServices.getTypes(), + }); + visualizationsServices.setSavedVisualizationsLoader(savedVisualizationsLoader); +} diff --git a/src/legacy/ui/public/visualize/_index.scss b/src/legacy/ui/public/visualize/_index.scss index c528c1e37b412..d9761f741353b 100644 --- a/src/legacy/ui/public/visualize/_index.scss +++ b/src/legacy/ui/public/visualize/_index.scss @@ -1 +1 @@ -@import '../../../core_plugins/visualizations/public/np_ready/public/components/index'; +@import '../../../../plugins/visualizations/public/components/index'; diff --git a/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts b/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts index f19940726ef2d..fe7f239fbea3b 100644 --- a/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts +++ b/src/legacy/ui/public/visualize/loader/pipeline_helpers/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { buildPipeline } from '../../../../../core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline'; +export { buildPipeline } from '../../../../../../plugins/visualizations/public/legacy/build_pipeline'; diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index 0a1b95c23450b..99560b0bf653f 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -23,8 +23,6 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; import * as UiSharedDeps from '@kbn/ui-shared-deps'; import { AppBootstrap } from './bootstrap'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { fromRoot } from '../../../core/server/utils'; import { getApmConfig } from '../apm'; import { DllCompiler } from '../../../optimize/dynamic_dll_plugin'; @@ -43,11 +41,6 @@ export function uiRenderMixin(kbnServer, server, config) { // render all views from ./views server.setupViews(resolve(__dirname, 'views')); - server.exposeStaticDir( - '/node_modules/@kbn/ui-framework/dist/{path*}', - fromRoot('node_modules/@kbn/ui-framework/dist') - ); - const translationsCache = { translations: null, hash: null }; server.route({ path: '/translations/{locale}.json', diff --git a/src/plugins/apm_oss/server/index.ts b/src/plugins/apm_oss/server/index.ts index 95a4ae4519bc9..bd0d23d62500d 100644 --- a/src/plugins/apm_oss/server/index.ts +++ b/src/plugins/apm_oss/server/index.ts @@ -22,6 +22,7 @@ import { APMOSSPlugin } from './plugin'; export const config = { schema: schema.object({ + enabled: schema.boolean({ defaultValue: true }), transactionIndices: schema.string({ defaultValue: 'apm-*' }), spanIndices: schema.string({ defaultValue: 'apm-*' }), errorIndices: schema.string({ defaultValue: 'apm-*' }), diff --git a/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts index e1640927c4ead..7a0d324995890 100644 --- a/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts +++ b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts @@ -20,11 +20,16 @@ import { TimedItemBuffer } from '../timed_item_buffer'; import { runItemBufferTests } from './run_item_buffer_tests'; -// FLAKY: https://github.com/elastic/kibana/issues/58662 -describe.skip('TimedItemBuffer', () => { +jest.useFakeTimers(); + +beforeEach(() => { + jest.clearAllTimers(); +}); + +describe('TimedItemBuffer', () => { runItemBufferTests(TimedItemBuffer); - test('does not do unnecessary flushes', async () => { + test('does not do unnecessary flushes', () => { const onFlush = jest.fn(); const buf = new TimedItemBuffer({ onFlush, @@ -38,7 +43,7 @@ describe.skip('TimedItemBuffer', () => { expect(onFlush).toHaveBeenCalledTimes(1); }); - test('does not do extra flush after timeout if buffer was flushed during timeout wait', async () => { + test('does not do extra flush after timeout if buffer was flushed during timeout wait', () => { const onFlush = jest.fn(); const buf = new TimedItemBuffer({ onFlush, @@ -46,14 +51,14 @@ describe.skip('TimedItemBuffer', () => { }); buf.write(0); - await new Promise(r => setTimeout(r, 3)); + jest.advanceTimersByTime(3); buf.flush(); - await new Promise(r => setTimeout(r, 11)); + jest.advanceTimersByTime(11); expect(onFlush).toHaveBeenCalledTimes(1); }); - test('flushes buffer automatically after timeout reached', async () => { + test('flushes buffer automatically after timeout reached', () => { const onFlush = jest.fn(); const buf = new TimedItemBuffer({ onFlush, @@ -64,12 +69,12 @@ describe.skip('TimedItemBuffer', () => { buf.write(2); expect(onFlush).toHaveBeenCalledTimes(0); - await new Promise(r => setTimeout(r, 3)); + jest.advanceTimersByTime(3); expect(onFlush).toHaveBeenCalledTimes(1); expect(onFlush).toHaveBeenCalledWith([1, 2]); }); - test('does not call flush after timeout if flush was triggered because buffer size reached', async () => { + test('does not call flush after timeout if flush was triggered because buffer size reached', () => { const onFlush = jest.fn(); const buf = new TimedItemBuffer({ onFlush, @@ -81,11 +86,11 @@ describe.skip('TimedItemBuffer', () => { buf.write(2); expect(onFlush).toHaveBeenCalledTimes(1); - await new Promise(r => setTimeout(r, 3)); + jest.advanceTimersByTime(3); expect(onFlush).toHaveBeenCalledTimes(1); }); - test('does not automatically flush if `.clear()` was called', async () => { + test('does not automatically flush if `.clear()` was called', () => { const onFlush = jest.fn(); const buf = new TimedItemBuffer({ onFlush, @@ -95,11 +100,11 @@ describe.skip('TimedItemBuffer', () => { buf.write(1); buf.write(2); - await new Promise(r => setImmediate(r)); + jest.advanceTimersByTime(1); buf.clear(); expect(onFlush).toHaveBeenCalledTimes(0); - await new Promise(r => setTimeout(r, 6)); + jest.advanceTimersByTime(6); expect(onFlush).toHaveBeenCalledTimes(0); }); }); diff --git a/src/plugins/console/server/lib/spec_definitions/json/.eslintrc b/src/plugins/console/server/lib/spec_definitions/json/.eslintrc deleted file mode 100644 index 10f7444ecaf1b..0000000000000 --- a/src/plugins/console/server/lib/spec_definitions/json/.eslintrc +++ /dev/null @@ -1,27 +0,0 @@ ---- - -root: true -extends: '../../../../../../../.eslintrc.js' - -rules: - block-scoped-var: off - camelcase: off - dot-location: off - dot-notation: off - eqeqeq: off - guard-for-in: off - new-cap: off - no-caller: off - no-empty: off - no-extend-native: off - no-loop-func: off - no-multi-str: off - no-nested-ternary: off - no-proto: off - no-sequences: off - no-undef: off - no-use-before-define: off - one-var: off - strict: off - no-var: off - prefer-const: off diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json index 2135bd67e57d8..40b0e56782641 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json @@ -6,7 +6,14 @@ "h": [], "help": "__flag__", "s": [], - "v": "__flag__" + "v": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] }, "methods": [ "GET" diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json index e6ca1fb575396..410350df13721 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json @@ -36,7 +36,14 @@ "nanos" ], "v": "__flag__", - "include_unloaded_segments": "__flag__" + "include_unloaded_segments": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] }, "methods": [ "GET" diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.delete_component_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.delete_component_template.json new file mode 100644 index 0000000000000..e935b8999e6d3 --- /dev/null +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.delete_component_template.json @@ -0,0 +1,15 @@ +{ + "cluster.delete_component_template": { + "url_params": { + "timeout": "", + "master_timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_component_template/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-component-templates.html" + } +} diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json index 64ede603c0e0d..1758ea44d92c0 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json @@ -4,6 +4,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json index ba9c8d427e7bd..fb4a02c603174 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json @@ -11,6 +11,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/count.json b/src/plugins/console/server/lib/spec_definitions/json/generated/count.json index bd69fd0c77ec8..67386eb7c6f1b 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/count.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/count.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json index 2d1636d5f2c02..e01ea8b2dec6d 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json @@ -1,6 +1,7 @@ { "delete_by_query": { "url_params": { + "analyzer": "", "analyze_wildcard": "__flag__", "default_operator": [ "AND", @@ -17,6 +18,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json b/src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json index 5e632018bef25..4bf63d7566788 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json index f5cf05c9a3f7f..fc84d07df88a4 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json @@ -9,6 +9,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json index 676f20632e63b..1b58a27829bc7 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json @@ -8,6 +8,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json index 8227e38d3c6d9..1970f88b30958 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json @@ -1,6 +1,7 @@ { "indices.create": { "url_params": { + "include_type_name": "__flag__", "wait_for_active_shards": "", "timeout": "", "master_timeout": "" diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json index b006d5ea7a3cb..084828108123b 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json @@ -8,6 +8,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json index 33c845210ea87..09f6c7fd780f8 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json index d302bbe6b93de..4b93184ed52f1 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json index 70d35e6c453c9..0b11356155b50 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json index 0ad1a250229b2..63c86d10a9864 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json @@ -8,6 +8,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json index 0e705e2e721ee..b642d5f04a044 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json index 7ca9e88274aa5..6df796ed6c4cf 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json @@ -1,12 +1,14 @@ { "indices.get": { "url_params": { + "include_type_name": "__flag__", "local": "__flag__", "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json index d687cab56630f..95bc74edc5865 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json index ea952435566ed..c95e2efc73fab 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json @@ -1,12 +1,14 @@ { "indices.get_field_mapping": { "url_params": { + "include_type_name": "__flag__", "include_defaults": "__flag__", "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json index 73f4e42262bf2..555137d0e2ee0 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json @@ -1,11 +1,13 @@ { "indices.get_mapping": { "url_params": { + "include_type_name": "__flag__", "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json index 1c84258d0fce9..a6777f7a820aa 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json index f5902929c25cc..d5f52ec76b374 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json @@ -1,6 +1,7 @@ { "indices.get_template": { "url_params": { + "include_type_name": "__flag__", "flat_settings": "__flag__", "master_timeout": "", "local": "__flag__" diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json index d781172c54d63..99ac958523084 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json index b5c4c5501d05d..6369238739203 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json @@ -8,6 +8,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json index 07a62a64b64e1..e36783c815e3f 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json @@ -1,6 +1,7 @@ { "indices.put_mapping": { "url_params": { + "include_type_name": "__flag__", "timeout": "", "master_timeout": "", "ignore_unavailable": "__flag__", @@ -8,6 +9,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json index fe7b938d2f3fc..a2508cd0fc817 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json @@ -9,6 +9,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json index 54a7625a2713c..8fb31277da44e 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json @@ -1,9 +1,9 @@ { "indices.put_template": { "url_params": { + "include_type_name": "__flag__", "order": "", "create": "__flag__", - "timeout": "", "master_timeout": "", "flat_settings": "__flag__" }, diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json index 54cd2a869902a..2906349d3fdae 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json index 19e0f1f909ab8..7fa76a687eb77 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json @@ -1,6 +1,7 @@ { "indices.rollover": { "url_params": { + "include_type_name": "__flag__", "timeout": "", "dry_run": "__flag__", "master_timeout": "", diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json index 9e2eb6efce27e..b3c07150699af 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json index f8e026eb89984..c50f4cf501698 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json index c3fc0f8f7055f..1fa32265c91ee 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json @@ -16,6 +16,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json index 68ee06dd1b0bd..484115bb9b260 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json @@ -5,6 +5,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json index 33720576ef8a3..315aa13d4b4e8 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json index c2f741066bbdb..0b0ca087b1819 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json @@ -9,7 +9,8 @@ ], "typed_keys": "__flag__", "max_concurrent_searches": "", - "rest_total_hits_as_int": "__flag__" + "rest_total_hits_as_int": "__flag__", + "ccs_minimize_roundtrips": "__flag__" }, "methods": [ "GET", diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json b/src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json index c2bed081124a8..4d73e58bd4c06 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json @@ -6,6 +6,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/search.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search.json index eb21b43644d77..78b969d3ed8f2 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/search.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/search.json @@ -19,6 +19,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json index cbeb0a429352d..b0819f8e066c8 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json @@ -9,6 +9,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ] diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json index cf5a5c5f32db3..748326522e5c2 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json @@ -7,6 +7,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], @@ -22,7 +23,8 @@ "explain": "__flag__", "profile": "__flag__", "typed_keys": "__flag__", - "rest_total_hits_as_int": "__flag__" + "rest_total_hits_as_int": "__flag__", + "ccs_minimize_roundtrips": "__flag__" }, "methods": [ "GET", diff --git a/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json index 393197949e86c..596f8f8b83963 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json +++ b/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json @@ -18,6 +18,7 @@ "expand_wildcards": [ "open", "closed", + "hidden", "none", "all" ], diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json index 7e1655e680b8f..949b897b29ff4 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json @@ -1,11 +1,38 @@ { "cluster.health": { "url_params": { - "master_timeout": "30s", - "timeout": "30s", - "wait_for_relocating_shards": 0, - "wait_for_active_shards": 0, - "wait_for_nodes": 0 + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ], + "level": [ + "cluster", + "indices", + "shards" + ], + "local": "__flag__", + "master_timeout": "", + "timeout": "", + "wait_for_active_shards": "", + "wait_for_nodes": "", + "wait_for_events": [ + "immediate", + "urgent", + "high", + "normal", + "low", + "languid" + ], + "wait_for_no_relocating_shards": "__flag__", + "wait_for_no_initializing_shards": "__flag__", + "wait_for_status": [ + "green", + "yellow", + "red" + ] } } } diff --git a/src/plugins/dashboard/public/actions/replace_panel_action.tsx b/src/plugins/dashboard/public/actions/replace_panel_action.tsx index 4e20aa3c35088..21ec961917d17 100644 --- a/src/plugins/dashboard/public/actions/replace_panel_action.tsx +++ b/src/plugins/dashboard/public/actions/replace_panel_action.tsx @@ -37,7 +37,7 @@ export interface ReplacePanelActionContext { export class ReplacePanelAction implements ActionByType { public readonly type = ACTION_REPLACE_PANEL; public readonly id = ACTION_REPLACE_PANEL; - public order = 3; + public order = 11; constructor( private core: CoreStart, diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 3d67435e6d8f7..df3c312c7ae1b 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -87,7 +87,7 @@ export class DashboardEmbeddableContainerPublicPlugin ): Setup { const expandPanelAction = new ExpandPanelAction(); uiActions.registerAction(expandPanelAction); - uiActions.attachAction(CONTEXT_MENU_TRIGGER, expandPanelAction.id); + uiActions.attachAction(CONTEXT_MENU_TRIGGER, expandPanelAction); const startServices = core.getStartServices(); if (share) { @@ -146,7 +146,7 @@ export class DashboardEmbeddableContainerPublicPlugin plugins.embeddable.getEmbeddableFactories ); uiActions.registerAction(changeViewAction); - uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, changeViewAction); + uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction); const savedDashboardLoader = createSavedDashboardLoader({ savedObjectsClient: core.savedObjects.client, indexPatterns, diff --git a/src/plugins/dashboard/public/tests/dashboard_container.test.tsx b/src/plugins/dashboard/public/tests/dashboard_container.test.tsx index 4aede3f3442fb..a81d80b440e04 100644 --- a/src/plugins/dashboard/public/tests/dashboard_container.test.tsx +++ b/src/plugins/dashboard/public/tests/dashboard_container.test.tsx @@ -49,7 +49,7 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => { const editModeAction = createEditModeAction(); uiActionsSetup.registerAction(editModeAction); - uiActionsSetup.addTriggerAction(CONTEXT_MENU_TRIGGER, editModeAction); + uiActionsSetup.attachAction(CONTEXT_MENU_TRIGGER, editModeAction); setup.registerEmbeddableFactory( CONTACT_CARD_EMBEDDABLE, new ContactCardEmbeddableFactory({} as any, (() => null) as any, {} as any) diff --git a/src/plugins/data/common/query/filter_manager/compare_filters.test.ts b/src/plugins/data/common/query/filter_manager/compare_filters.test.ts index b0bb2f754d6cf..0c3947ade8221 100644 --- a/src/plugins/data/common/query/filter_manager/compare_filters.test.ts +++ b/src/plugins/data/common/query/filter_manager/compare_filters.test.ts @@ -197,6 +197,22 @@ describe('filter manager utilities', () => { expect(compareFilters([f1], [f2], COMPARE_ALL_OPTIONS)).toBeTruthy(); }); + test('should compare alias with alias true', () => { + const f1 = { + $state: { store: FilterStateStore.GLOBAL_STATE }, + ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''), + }; + const f2 = { + $state: { store: FilterStateStore.GLOBAL_STATE }, + ...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''), + }; + + f2.meta.alias = 'wassup'; + f2.meta.alias = 'dog'; + + expect(compareFilters([f1], [f2], { alias: true })).toBeFalsy(); + }); + test('should compare alias with COMPARE_ALL_OPTIONS', () => { const f1 = { $state: { store: FilterStateStore.GLOBAL_STATE }, diff --git a/src/plugins/data/common/query/filter_manager/compare_filters.ts b/src/plugins/data/common/query/filter_manager/compare_filters.ts index e047d5e0665d5..3be52a9a60977 100644 --- a/src/plugins/data/common/query/filter_manager/compare_filters.ts +++ b/src/plugins/data/common/query/filter_manager/compare_filters.ts @@ -46,7 +46,7 @@ const mapFilter = ( if (comparators.negate) cleaned.negate = filter.meta && Boolean(filter.meta.negate); if (comparators.disabled) cleaned.disabled = filter.meta && Boolean(filter.meta.disabled); - if (comparators.disabled) cleaned.alias = filter.meta?.alias; + if (comparators.alias) cleaned.alias = filter.meta?.alias; return cleaned; }; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index ea2e85947aa12..26587470adfd9 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -109,19 +109,22 @@ export class DataPublicPlugin implements Plugin Record<"buckets" | "metrics", string>; + aggGroupNamesMap: () => Record<"metrics" | "buckets", string>; aggTypeFilters: import("./search/aggs/filter/agg_type_filters").AggTypeFilters; CidrMask: typeof CidrMask; convertDateRangeToString: typeof convertDateRangeToString; diff --git a/src/plugins/data/public/search/aggs/agg_types.ts b/src/plugins/data/public/search/aggs/agg_types.ts index 73c6a5046fd23..556f6b0c93c41 100644 --- a/src/plugins/data/public/search/aggs/agg_types.ts +++ b/src/plugins/data/public/search/aggs/agg_types.ts @@ -17,7 +17,8 @@ * under the License. */ -import { IUiSettingsClient } from 'src/core/public'; +import { IUiSettingsClient, NotificationsSetup } from 'src/core/public'; +import { QuerySetup } from '../../query/query_service'; import { countMetricAgg } from './metrics/count'; import { avgMetricAgg } from './metrics/avg'; @@ -36,10 +37,10 @@ import { derivativeMetricAgg } from './metrics/derivative'; import { cumulativeSumMetricAgg } from './metrics/cumulative_sum'; import { movingAvgMetricAgg } from './metrics/moving_avg'; import { serialDiffMetricAgg } from './metrics/serial_diff'; -import { dateHistogramBucketAgg } from './buckets/date_histogram'; -import { histogramBucketAgg } from './buckets/histogram'; +import { getDateHistogramBucketAgg } from './buckets/date_histogram'; +import { getHistogramBucketAgg } from './buckets/histogram'; import { rangeBucketAgg } from './buckets/range'; -import { dateRangeBucketAgg } from './buckets/date_range'; +import { getDateRangeBucketAgg } from './buckets/date_range'; import { ipRangeBucketAgg } from './buckets/ip_range'; import { termsBucketAgg } from './buckets/terms'; import { filterBucketAgg } from './buckets/filter'; @@ -52,44 +53,47 @@ import { bucketAvgMetricAgg } from './metrics/bucket_avg'; import { bucketMinMetricAgg } from './metrics/bucket_min'; import { bucketMaxMetricAgg } from './metrics/bucket_max'; -export function getAggTypes(deps: { uiSettings: IUiSettingsClient }) { - const { uiSettings } = deps; - return { - metrics: [ - countMetricAgg, - avgMetricAgg, - sumMetricAgg, - medianMetricAgg, - minMetricAgg, - maxMetricAgg, - stdDeviationMetricAgg, - cardinalityMetricAgg, - percentilesMetricAgg, - percentileRanksMetricAgg, - topHitMetricAgg, - derivativeMetricAgg, - cumulativeSumMetricAgg, - movingAvgMetricAgg, - serialDiffMetricAgg, - bucketAvgMetricAgg, - bucketSumMetricAgg, - bucketMinMetricAgg, - bucketMaxMetricAgg, - geoBoundsMetricAgg, - geoCentroidMetricAgg, - ], - buckets: [ - dateHistogramBucketAgg, - histogramBucketAgg, - rangeBucketAgg, - dateRangeBucketAgg, - ipRangeBucketAgg, - termsBucketAgg, - filterBucketAgg, - getFiltersBucketAgg({ uiSettings }), - significantTermsBucketAgg, - geoHashBucketAgg, - geoTileBucketAgg, - ], - }; +export interface AggTypesDependencies { + notifications: NotificationsSetup; + uiSettings: IUiSettingsClient; + query: QuerySetup; } + +export const getAggTypes = ({ notifications, uiSettings, query }: AggTypesDependencies) => ({ + metrics: [ + countMetricAgg, + avgMetricAgg, + sumMetricAgg, + medianMetricAgg, + minMetricAgg, + maxMetricAgg, + stdDeviationMetricAgg, + cardinalityMetricAgg, + percentilesMetricAgg, + percentileRanksMetricAgg, + topHitMetricAgg, + derivativeMetricAgg, + cumulativeSumMetricAgg, + movingAvgMetricAgg, + serialDiffMetricAgg, + bucketAvgMetricAgg, + bucketSumMetricAgg, + bucketMinMetricAgg, + bucketMaxMetricAgg, + geoBoundsMetricAgg, + geoCentroidMetricAgg, + ], + buckets: [ + getDateHistogramBucketAgg({ uiSettings, query }), + getHistogramBucketAgg({ uiSettings, notifications }), + rangeBucketAgg, + getDateRangeBucketAgg({ uiSettings }), + ipRangeBucketAgg, + termsBucketAgg, + filterBucketAgg, + getFiltersBucketAgg({ uiSettings }), + significantTermsBucketAgg, + geoHashBucketAgg, + geoTileBucketAgg, + ], +}); diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 12817a9ba1159..def354c4557cb 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -22,23 +22,35 @@ import { createFilterDateHistogram } from './date_histogram'; import { intervalOptions } from '../_interval_options'; import { AggConfigs } from '../../agg_configs'; import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; -import { dateHistogramBucketAgg, IBucketDateHistogramAggConfig } from '../date_histogram'; +import { + getDateHistogramBucketAgg, + DateHistogramBucketAggDependencies, + IBucketDateHistogramAggConfig, +} from '../date_histogram'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { RangeFilter } from '../../../../../common'; +import { coreMock } from '../../../../../../../core/public/mocks'; +import { queryServiceMock } from '../../../../query/mocks'; describe('AggConfig Filters', () => { describe('date_histogram', () => { - beforeEach(() => { - mockDataServices(); - }); - - const typesRegistry = mockAggTypesRegistry([dateHistogramBucketAgg]); - + let aggTypesDependencies: DateHistogramBucketAggDependencies; let agg: IBucketDateHistogramAggConfig; let filter: RangeFilter; let bucketStart: any; let field: any; + beforeEach(() => { + const { uiSettings } = coreMock.createSetup(); + + aggTypesDependencies = { + uiSettings, + query: queryServiceMock.createSetupContract(), + }; + + mockDataServices(); + }); + const init = (interval: string = 'auto', duration: any = moment.duration(15, 'minutes')) => { field = { name: 'date', @@ -61,7 +73,7 @@ describe('AggConfig Filters', () => { params: { field: field.name, interval, customInterval: '5d' }, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]) } ); const bucketKey = 1422579600000; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index d18a30fb6c6f8..6a03176959a83 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -18,7 +18,7 @@ */ import moment from 'moment'; -import { dateRangeBucketAgg } from '../date_range'; +import { getDateRangeBucketAgg, DateRangeBucketAggDependencies } from '../date_range'; import { createFilterDateRange } from './date_range'; import { FieldFormatsGetConfigFn } from '../../../../../common'; import { DateFormat } from '../../../../field_formats'; @@ -26,10 +26,20 @@ import { AggConfigs } from '../../agg_configs'; import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../_bucket_agg_type'; +import { coreMock } from '../../../../../../../core/public/mocks'; describe('AggConfig Filters', () => { describe('Date range', () => { - const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); + let aggTypesDependencies: DateRangeBucketAggDependencies; + + beforeEach(() => { + const { uiSettings } = coreMock.createSetup(); + + aggTypesDependencies = { + uiSettings, + }; + }); + const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -57,7 +67,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index 33ab1ce8186a1..32ada8d57c768 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -17,25 +17,24 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { getFiltersBucketAgg } from '../filters'; +import { getFiltersBucketAgg, FiltersBucketAggDependencies } from '../filters'; import { createFilterFilters } from './filters'; import { AggConfigs } from '../../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; +import { mockAggTypesRegistry } from '../../test_helpers'; import { IBucketAggConfig } from '../_bucket_agg_type'; +import { coreMock } from '../../../../../../../core/public/mocks'; describe('AggConfig Filters', () => { describe('filters', () => { + let aggTypesDependencies: FiltersBucketAggDependencies; + beforeEach(() => { - mockDataServices(); - }); + const { uiSettings } = coreMock.createSetup(); - const typesRegistry = mockAggTypesRegistry([ - getFiltersBucketAgg({ - uiSettings: coreMock.createSetup().uiSettings, - }), - ]); + aggTypesDependencies = { + uiSettings, + }; + }); const getAggConfigs = () => { const field = { @@ -65,7 +64,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]) } ); }; it('should return a filters filter', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts index d600b16f56764..7701f1bbcb4d0 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -17,9 +17,10 @@ * under the License. */ -import _ from 'lodash'; +import { get, noop, find, every } from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; +import { IUiSettingsClient } from 'src/core/public'; import { TimeBuckets } from './lib/time_buckets'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; @@ -32,7 +33,8 @@ import { isMetricAggType } from '../metrics/metric_agg_type'; import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common'; import { TimefilterContract } from '../../../query'; -import { getFieldFormats, getQueryService, getUiSettings } from '../../../../public/services'; +import { getFieldFormats } from '../../../../public/services'; +import { QuerySetup } from '../../../query/query_service'; const detectedTimezone = moment.tz.guess(); const tzOffset = moment().format('Z'); @@ -56,6 +58,11 @@ interface ITimeBuckets { getInterval: Function; } +export interface DateHistogramBucketAggDependencies { + uiSettings: IUiSettingsClient; + query: QuerySetup; +} + export interface IBucketDateHistogramAggConfig extends IBucketAggConfig { buckets: ITimeBuckets; } @@ -64,212 +71,214 @@ export function isDateHistogramBucketAggConfig(agg: any): agg is IBucketDateHist return Boolean(agg.buckets); } -export const dateHistogramBucketAgg = new BucketAggType({ - name: BUCKET_TYPES.DATE_HISTOGRAM, - title: i18n.translate('data.search.aggs.buckets.dateHistogramTitle', { - defaultMessage: 'Date Histogram', - }), - ordered: { - date: true, - }, - makeLabel(agg) { - let output: Record = {}; +export const getDateHistogramBucketAgg = ({ + uiSettings, + query, +}: DateHistogramBucketAggDependencies) => + new BucketAggType({ + name: BUCKET_TYPES.DATE_HISTOGRAM, + title: i18n.translate('data.search.aggs.buckets.dateHistogramTitle', { + defaultMessage: 'Date Histogram', + }), + ordered: { + date: true, + }, + makeLabel(agg) { + let output: Record = {}; - if (this.params) { - output = writeParams(this.params, agg); - } + if (this.params) { + output = writeParams(this.params, agg); + } - const field = agg.getFieldDisplayName(); - return i18n.translate('data.search.aggs.buckets.dateHistogramLabel', { - defaultMessage: '{fieldName} per {intervalDescription}', - values: { - fieldName: field, - intervalDescription: output.metricScaleText || output.bucketInterval.description, - }, - }); - }, - createFilter: createFilterDateHistogram, - decorateAggConfig() { - const uiSettings = getUiSettings(); - let buckets: any; + const field = agg.getFieldDisplayName(); + return i18n.translate('data.search.aggs.buckets.dateHistogramLabel', { + defaultMessage: '{fieldName} per {intervalDescription}', + values: { + fieldName: field, + intervalDescription: output.metricScaleText || output.bucketInterval.description, + }, + }); + }, + createFilter: createFilterDateHistogram, + decorateAggConfig() { + let buckets: any; - return { - buckets: { - configurable: true, - get() { - if (buckets) return buckets; + return { + buckets: { + configurable: true, + get() { + if (buckets) return buckets; - const { timefilter } = getQueryService().timefilter; - buckets = new TimeBuckets({ uiSettings }); - updateTimeBuckets(this, timefilter, buckets); + const { timefilter } = query.timefilter; + buckets = new TimeBuckets({ uiSettings }); + updateTimeBuckets(this, timefilter, buckets); - return buckets; - }, - } as any, - }; - }, - getFormat(agg) { - const DateFieldFormat = getFieldFormats().getType(FIELD_FORMAT_IDS.DATE); + return buckets; + }, + } as any, + }; + }, + getFormat(agg) { + const DateFieldFormat = getFieldFormats().getType(FIELD_FORMAT_IDS.DATE); - if (!DateFieldFormat) { - throw new Error('Unable to retrieve Date Field Format'); - } + if (!DateFieldFormat) { + throw new Error('Unable to retrieve Date Field Format'); + } - return new DateFieldFormat( + return new DateFieldFormat( + { + pattern: agg.buckets.getScaledDateFormat(), + }, + (key: string) => uiSettings.get(key) + ); + }, + params: [ { - pattern: agg.buckets.getScaledDateFormat(), + name: 'field', + type: 'field', + filterFieldTypes: KBN_FIELD_TYPES.DATE, + default(agg: IBucketDateHistogramAggConfig) { + return agg.getIndexPattern().timeFieldName; + }, + onChange(agg: IBucketDateHistogramAggConfig) { + if (get(agg, 'params.interval') === 'auto' && !agg.fieldIsTimeField()) { + delete agg.params.interval; + } + }, }, - (key: string) => getUiSettings().get(key) - ); - }, - params: [ - { - name: 'field', - type: 'field', - filterFieldTypes: KBN_FIELD_TYPES.DATE, - default(agg: IBucketDateHistogramAggConfig) { - return agg.getIndexPattern().timeFieldName; + { + name: 'timeRange', + default: null, + write: noop, }, - onChange(agg: IBucketDateHistogramAggConfig) { - if (_.get(agg, 'params.interval') === 'auto' && !agg.fieldIsTimeField()) { - delete agg.params.interval; - } + { + name: 'useNormalizedEsInterval', + default: true, + write: noop, }, - }, - { - name: 'timeRange', - default: null, - write: _.noop, - }, - { - name: 'useNormalizedEsInterval', - default: true, - write: _.noop, - }, - { - name: 'scaleMetricValues', - default: false, - write: _.noop, - advanced: true, - }, - { - name: 'interval', - deserialize(state: any, agg) { - // For upgrading from 7.0.x to 7.1.x - intervals are now stored as key of options or custom value - if (state === 'custom') { - return _.get(agg, 'params.customInterval'); - } + { + name: 'scaleMetricValues', + default: false, + write: noop, + advanced: true, + }, + { + name: 'interval', + deserialize(state: any, agg) { + // For upgrading from 7.0.x to 7.1.x - intervals are now stored as key of options or custom value + if (state === 'custom') { + return get(agg, 'params.customInterval'); + } - const interval = _.find(intervalOptions, { val: state }); + const interval = find(intervalOptions, { val: state }); - // For upgrading from 4.0.x to 4.1.x - intervals are now stored as 'y' instead of 'year', - // but this maps the old values to the new values - if (!interval && state === 'year') { - return 'y'; - } - return state; - }, - default: 'auto', - options: intervalOptions, - write(agg, output, aggs) { - const { timefilter } = getQueryService().timefilter; - updateTimeBuckets(agg, timefilter); + // For upgrading from 4.0.x to 4.1.x - intervals are now stored as 'y' instead of 'year', + // but this maps the old values to the new values + if (!interval && state === 'year') { + return 'y'; + } + return state; + }, + default: 'auto', + options: intervalOptions, + write(agg, output, aggs) { + const { timefilter } = query.timefilter; + updateTimeBuckets(agg, timefilter); - const { useNormalizedEsInterval, scaleMetricValues } = agg.params; - const interval = agg.buckets.getInterval(useNormalizedEsInterval); - output.bucketInterval = interval; - if (interval.expression === '0ms') { - // We are hitting this code a couple of times while configuring in editor - // with an interval of 0ms because the overall time range has not yet been - // set. Since 0ms is not a valid ES interval, we cannot pass it through dateHistogramInterval - // below, since it would throw an exception. So in the cases we still have an interval of 0ms - // here we simply skip the rest of the method and never write an interval into the DSL, since - // this DSL will anyway not be used before we're passing this code with an actual interval. - return; - } - output.params = { - ...output.params, - ...dateHistogramInterval(interval.expression), - }; + const { useNormalizedEsInterval, scaleMetricValues } = agg.params; + const interval = agg.buckets.getInterval(useNormalizedEsInterval); + output.bucketInterval = interval; + if (interval.expression === '0ms') { + // We are hitting this code a couple of times while configuring in editor + // with an interval of 0ms because the overall time range has not yet been + // set. Since 0ms is not a valid ES interval, we cannot pass it through dateHistogramInterval + // below, since it would throw an exception. So in the cases we still have an interval of 0ms + // here we simply skip the rest of the method and never write an interval into the DSL, since + // this DSL will anyway not be used before we're passing this code with an actual interval. + return; + } + output.params = { + ...output.params, + ...dateHistogramInterval(interval.expression), + }; - const scaleMetrics = scaleMetricValues && interval.scaled && interval.scale < 1; - if (scaleMetrics && aggs) { - const metrics = aggs.aggs.filter(a => isMetricAggType(a.type)); - const all = _.every(metrics, (a: IBucketAggConfig) => { - const { type } = a; + const scaleMetrics = scaleMetricValues && interval.scaled && interval.scale < 1; + if (scaleMetrics && aggs) { + const metrics = aggs.aggs.filter(a => isMetricAggType(a.type)); + const all = every(metrics, (a: IBucketAggConfig) => { + const { type } = a; - if (isMetricAggType(type)) { - return type.isScalable(); + if (isMetricAggType(type)) { + return type.isScalable(); + } + }); + if (all) { + output.metricScale = interval.scale; + output.metricScaleText = interval.preScaled.description; } - }); - if (all) { - output.metricScale = interval.scale; - output.metricScaleText = interval.preScaled.description; } - } + }, }, - }, - { - name: 'time_zone', - default: undefined, - // We don't ever want this parameter to be serialized out (when saving or to URLs) - // since we do all the logic handling it "on the fly" in the `write` method, to prevent - // time_zones being persisted into saved_objects - serialize: _.noop, - write(agg, output) { - // If a time_zone has been set explicitly always prefer this. - let tz = agg.params.time_zone; - if (!tz && agg.params.field) { - // If a field has been configured check the index pattern's typeMeta if a date_histogram on that - // field requires a specific time_zone - tz = _.get(agg.getIndexPattern(), [ - 'typeMeta', - 'aggs', - 'date_histogram', - agg.params.field.name, - 'time_zone', - ]); - } - if (!tz) { - const config = getUiSettings(); - // If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz - const isDefaultTimezone = config.isDefault('dateFormat:tz'); - tz = isDefaultTimezone ? detectedTimezone || tzOffset : config.get('dateFormat:tz'); - } - output.params.time_zone = tz; + { + name: 'time_zone', + default: undefined, + // We don't ever want this parameter to be serialized out (when saving or to URLs) + // since we do all the logic handling it "on the fly" in the `write` method, to prevent + // time_zones being persisted into saved_objects + serialize: noop, + write(agg, output) { + // If a time_zone has been set explicitly always prefer this. + let tz = agg.params.time_zone; + if (!tz && agg.params.field) { + // If a field has been configured check the index pattern's typeMeta if a date_histogram on that + // field requires a specific time_zone + tz = get(agg.getIndexPattern(), [ + 'typeMeta', + 'aggs', + 'date_histogram', + agg.params.field.name, + 'time_zone', + ]); + } + if (!tz) { + // If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz + const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz'); + tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz'); + } + output.params.time_zone = tz; + }, }, - }, - { - name: 'drop_partials', - default: false, - write: _.noop, - shouldShow: agg => { - const field = agg.params.field; - return field && field.name && field.name === agg.getIndexPattern().timeFieldName; + { + name: 'drop_partials', + default: false, + write: noop, + shouldShow: agg => { + const field = agg.params.field; + return field && field.name && field.name === agg.getIndexPattern().timeFieldName; + }, }, - }, - { - name: 'format', - }, - { - name: 'min_doc_count', - default: 1, - }, - { - name: 'extended_bounds', - default: {}, - write(agg, output) { - const val = agg.params.extended_bounds; + { + name: 'format', + }, + { + name: 'min_doc_count', + default: 1, + }, + { + name: 'extended_bounds', + default: {}, + write(agg, output) { + const val = agg.params.extended_bounds; - if (val.min != null || val.max != null) { - output.params.extended_bounds = { - min: moment(val.min).valueOf(), - max: moment(val.max).valueOf(), - }; + if (val.min != null || val.max != null) { + output.params.extended_bounds = { + min: moment(val.min).valueOf(), + max: moment(val.max).valueOf(), + }; - return; - } + return; + } + }, }, - }, - ], -}); + ], + }); diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts index 03a453836e113..4ea550492fa09 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts @@ -17,20 +17,22 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths import { coreMock } from '../../../../../../../src/core/public/mocks'; -import { setUiSettings } from '../../../../public/services'; -import { dateRangeBucketAgg } from './date_range'; +import { getDateRangeBucketAgg, DateRangeBucketAggDependencies } from './date_range'; import { AggConfigs } from '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; +import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; describe('date_range params', () => { + let aggTypesDependencies: DateRangeBucketAggDependencies; + beforeEach(() => { - mockDataServices(); - }); + const { uiSettings } = coreMock.createSetup(); - const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]); + aggTypesDependencies = { + uiSettings, + }; + }); const getAggConfigs = (params: Record = {}, hasIncludeTypeMeta: boolean = true) => { const field = { @@ -67,12 +69,12 @@ describe('date_range params', () => { params, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) } ); }; describe('getKey', () => { - it('should return object', () => { + test('should return object', () => { const aggConfigs = getAggConfigs(); const dateRange = aggConfigs.aggs[0]; const bucket = { from: 'from-date', to: 'to-date', key: 'from-dateto-date' }; @@ -82,7 +84,7 @@ describe('date_range params', () => { }); describe('time_zone', () => { - it('should use the specified time_zone', () => { + test('should use the specified time_zone', () => { const aggConfigs = getAggConfigs({ time_zone: 'Europe/Minsk', field: 'bytes', @@ -93,7 +95,7 @@ describe('date_range params', () => { expect(params.time_zone).toBe('Europe/Minsk'); }); - it('should use the fixed time_zone from the index pattern typeMeta', () => { + test('should use the fixed time_zone from the index pattern typeMeta', () => { const aggConfigs = getAggConfigs({ field: 'bytes', }); @@ -103,12 +105,14 @@ describe('date_range params', () => { expect(params.time_zone).toBe('defaultTimeZone'); }); - it('should use the Kibana time_zone if no parameter specified', () => { - const core = coreMock.createStart(); - setUiSettings({ - ...core.uiSettings, - get: () => 'kibanaTimeZone' as any, - }); + test('should use the Kibana time_zone if no parameter specified', () => { + aggTypesDependencies = { + ...aggTypesDependencies, + uiSettings: { + ...aggTypesDependencies.uiSettings, + get: () => 'kibanaTimeZone' as any, + }, + }; const aggConfigs = getAggConfigs( { @@ -119,8 +123,6 @@ describe('date_range params', () => { const dateRange = aggConfigs.aggs[0]; const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE]; - setUiSettings(core.uiSettings); // clean up - expect(params.time_zone).toBe('kibanaTimeZone'); }); }); diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.ts b/src/plugins/data/public/search/aggs/buckets/date_range.ts index 59e78af2d7b95..8133a47ec7248 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.ts @@ -20,86 +20,92 @@ import { get } from 'lodash'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; +import { IUiSettingsClient } from 'src/core/public'; + import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common'; -import { getFieldFormats, getUiSettings } from '../../../../public/services'; +import { getFieldFormats } from '../../../../public/services'; const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', { defaultMessage: 'Date Range', }); -export const dateRangeBucketAgg = new BucketAggType({ - name: BUCKET_TYPES.DATE_RANGE, - title: dateRangeTitle, - createFilter: createFilterDateRange, - getKey({ from, to }): DateRangeKey { - return { from, to }; - }, - getFormat(agg) { - const fieldFormatsService = getFieldFormats(); +export interface DateRangeBucketAggDependencies { + uiSettings: IUiSettingsClient; +} - const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE) - ); - const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { - return convertDateRangeToString(range, formatter); - }); - return new DateRangeFormat(); - }, - makeLabel(aggConfig) { - return aggConfig.getFieldDisplayName() + ' date ranges'; - }, - params: [ - { - name: 'field', - type: 'field', - filterFieldTypes: KBN_FIELD_TYPES.DATE, - default(agg: IBucketAggConfig) { - return agg.getIndexPattern().timeFieldName; - }, +export const getDateRangeBucketAgg = ({ uiSettings }: DateRangeBucketAggDependencies) => + new BucketAggType({ + name: BUCKET_TYPES.DATE_RANGE, + title: dateRangeTitle, + createFilter: createFilterDateRange, + getKey({ from, to }): DateRangeKey { + return { from, to }; }, - { - name: 'ranges', - default: [ - { - from: 'now-1w/w', - to: 'now', - }, - ], + getFormat(agg) { + const fieldFormatsService = getFieldFormats(); + + const formatter = agg.fieldOwnFormatter( + TEXT_CONTEXT_TYPE, + fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.DATE) + ); + const DateRangeFormat = FieldFormat.from(function(range: DateRangeKey) { + return convertDateRangeToString(range, formatter); + }); + return new DateRangeFormat(); + }, + makeLabel(aggConfig) { + return aggConfig.getFieldDisplayName() + ' date ranges'; }, - { - name: 'time_zone', - default: undefined, - // Implimentation method is the same as that of date_histogram - serialize: () => undefined, - write: (agg, output) => { - const field = agg.getParam('field'); - let tz = agg.getParam('time_zone'); + params: [ + { + name: 'field', + type: 'field', + filterFieldTypes: KBN_FIELD_TYPES.DATE, + default(agg: IBucketAggConfig) { + return agg.getIndexPattern().timeFieldName; + }, + }, + { + name: 'ranges', + default: [ + { + from: 'now-1w/w', + to: 'now', + }, + ], + }, + { + name: 'time_zone', + default: undefined, + // Implimentation method is the same as that of date_histogram + serialize: () => undefined, + write: (agg, output) => { + const field = agg.getParam('field'); + let tz = agg.getParam('time_zone'); - if (!tz && field) { - tz = get(agg.getIndexPattern(), [ - 'typeMeta', - 'aggs', - 'date_range', - field.name, - 'time_zone', - ]); - } - if (!tz) { - const config = getUiSettings(); - const detectedTimezone = moment.tz.guess(); - const tzOffset = moment().format('Z'); - const isDefaultTimezone = config.isDefault('dateFormat:tz'); + if (!tz && field) { + tz = get(agg.getIndexPattern(), [ + 'typeMeta', + 'aggs', + 'date_range', + field.name, + 'time_zone', + ]); + } + if (!tz) { + const detectedTimezone = moment.tz.guess(); + const tzOffset = moment().format('Z'); + const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz'); - tz = isDefaultTimezone ? detectedTimezone || tzOffset : config.get('dateFormat:tz'); - } - output.params.time_zone = tz; + tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz'); + } + output.params.time_zone = tz; + }, }, - }, - ], -}); + ], + }); diff --git a/src/plugins/data/public/search/aggs/buckets/filters.ts b/src/plugins/data/public/search/aggs/buckets/filters.ts index 0ad28b8be2132..8b9aca87f8735 100644 --- a/src/plugins/data/public/search/aggs/buckets/filters.ts +++ b/src/plugins/data/public/search/aggs/buckets/filters.ts @@ -17,9 +17,8 @@ * under the License. */ -import _ from 'lodash'; import { i18n } from '@kbn/i18n'; - +import { size, transform, cloneDeep } from 'lodash'; import { IUiSettingsClient } from 'src/core/public'; import { createFilterFilters } from './create_filter/filters'; @@ -27,7 +26,6 @@ import { toAngularJSON } from '../utils'; import { BucketAggType } from './_bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { Storage } from '../../../../../../plugins/kibana_utils/public'; - import { getEsQueryConfig, buildEsQuery, Query } from '../../../../common'; import { getQueryLog } from '../../../query'; @@ -43,9 +41,12 @@ interface FilterValue { id: string; } -export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) { - const { uiSettings } = deps; - return new BucketAggType({ +export interface FiltersBucketAggDependencies { + uiSettings: IUiSettingsClient; +} + +export const getFiltersBucketAgg = ({ uiSettings }: FiltersBucketAggDependencies) => + new BucketAggType({ name: BUCKET_TYPES.FILTERS, title: filtersTitle, createFilter: createFilterFilters, @@ -58,7 +59,7 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) { ], write(aggConfig, output) { const inFilters: FilterValue[] = aggConfig.params.filters; - if (!_.size(inFilters)) return; + if (!size(inFilters)) return; inFilters.forEach(filter => { const persistedLog = getQueryLog( @@ -70,10 +71,10 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) { persistedLog.add(filter.input.query); }); - const outFilters = _.transform( + const outFilters = transform( inFilters, function(filters, filter) { - const input = _.cloneDeep(filter.input); + const input = cloneDeep(filter.input); if (!input) { console.log('malformed filter agg params, missing "input" query'); // eslint-disable-line no-console @@ -100,7 +101,7 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) { {} ); - if (!_.size(outFilters)) return; + if (!size(outFilters)) return; const params = output.params || (output.params = {}); params.filters = outFilters; @@ -108,4 +109,3 @@ export function getFiltersBucketAgg(deps: { uiSettings: IUiSettingsClient }) { }, ], }); -} diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts index 09dd03c759155..408cdf22bcbc2 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -24,8 +24,6 @@ import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './_bucket_agg_type'; describe('Geohash Agg', () => { - // const typesRegistry = mockAggTypesRegistry([geoHashBucketAgg]); - const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params?: Record) => { const indexPattern = { id: '1234', @@ -63,7 +61,7 @@ describe('Geohash Agg', () => { }, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry() } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts index 07cf022dca83c..c61b4ff37935a 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -17,21 +17,29 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths import { coreMock } from '../../../../../../../src/core/public/mocks'; -import { setUiSettings } from '../../../../public/services'; import { AggConfigs } from '../agg_configs'; -import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; +import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; -import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram'; +import { + IBucketHistogramAggConfig, + getHistogramBucketAgg, + AutoBounds, + HistogramBucketAggDependencies, +} from './histogram'; import { BucketAggType } from './_bucket_agg_type'; describe('Histogram Agg', () => { + let aggTypesDependencies: HistogramBucketAggDependencies; + beforeEach(() => { - mockDataServices(); - }); + const { uiSettings, notifications } = coreMock.createSetup(); - const typesRegistry = mockAggTypesRegistry([histogramBucketAgg]); + aggTypesDependencies = { + uiSettings, + notifications, + }; + }); const getAggConfigs = (params: Record) => { const indexPattern = { @@ -58,7 +66,7 @@ describe('Histogram Agg', () => { params, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]) } ); }; @@ -76,7 +84,7 @@ describe('Histogram Agg', () => { let histogramType: BucketAggType; beforeEach(() => { - histogramType = histogramBucketAgg; + histogramType = getHistogramBucketAgg(aggTypesDependencies); }); it('is ordered', () => { @@ -150,6 +158,14 @@ describe('Histogram Agg', () => { params?: Record, autoBounds?: AutoBounds ) => { + aggTypesDependencies = { + ...aggTypesDependencies, + uiSettings: { + ...aggTypesDependencies.uiSettings, + get: () => maxBars as any, + }, + }; + const aggConfigs = getAggConfigs({ ...params, field: { @@ -162,15 +178,7 @@ describe('Histogram Agg', () => { aggConfig.setAutoBounds(autoBounds); } - const core = coreMock.createStart(); - setUiSettings({ - ...core.uiSettings, - get: () => maxBars as any, - }); - - const interval = aggConfig.write(aggConfigs).params; - setUiSettings(core.uiSettings); // clean up - return interval; + return aggConfig.write(aggConfigs).params; }; it('will respect the histogram:maxBars setting', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.ts b/src/plugins/data/public/search/aggs/buckets/histogram.ts index 7ccd5ae4bf98c..bbffc0912bf0d 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.ts @@ -17,182 +17,190 @@ * under the License. */ -import _ from 'lodash'; +import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { IUiSettingsClient, NotificationsSetup } from 'src/core/public'; import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type'; import { createFilterHistogram } from './create_filter/histogram'; import { BUCKET_TYPES } from './bucket_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; -import { getNotifications, getUiSettings } from '../../../../public/services'; export interface AutoBounds { min: number; max: number; } +export interface HistogramBucketAggDependencies { + uiSettings: IUiSettingsClient; + notifications: NotificationsSetup; +} + export interface IBucketHistogramAggConfig extends IBucketAggConfig { setAutoBounds: (bounds: AutoBounds) => void; getAutoBounds: () => AutoBounds; } -export const histogramBucketAgg = new BucketAggType({ - name: BUCKET_TYPES.HISTOGRAM, - title: i18n.translate('data.search.aggs.buckets.histogramTitle', { - defaultMessage: 'Histogram', - }), - ordered: {}, - makeLabel(aggConfig) { - return aggConfig.getFieldDisplayName(); - }, - createFilter: createFilterHistogram, - decorateAggConfig() { - let autoBounds: AutoBounds; - - return { - setAutoBounds: { - configurable: true, - value(newValue: AutoBounds) { - autoBounds = newValue; +export const getHistogramBucketAgg = ({ + uiSettings, + notifications, +}: HistogramBucketAggDependencies) => + new BucketAggType({ + name: BUCKET_TYPES.HISTOGRAM, + title: i18n.translate('data.search.aggs.buckets.histogramTitle', { + defaultMessage: 'Histogram', + }), + ordered: {}, + makeLabel(aggConfig) { + return aggConfig.getFieldDisplayName(); + }, + createFilter: createFilterHistogram, + decorateAggConfig() { + let autoBounds: AutoBounds; + + return { + setAutoBounds: { + configurable: true, + value(newValue: AutoBounds) { + autoBounds = newValue; + }, }, - }, - getAutoBounds: { - configurable: true, - value() { - return autoBounds; + getAutoBounds: { + configurable: true, + value() { + return autoBounds; + }, }, - }, - }; - }, - params: [ - { - name: 'field', - type: 'field', - filterFieldTypes: KBN_FIELD_TYPES.NUMBER, + }; }, - { - /* - * This parameter can be set if you want the auto scaled interval to always - * be a multiple of a specific base. - */ - name: 'intervalBase', - default: null, - write: () => {}, - }, - { - name: 'interval', - modifyAggConfigOnSearchRequestStart( - aggConfig: IBucketHistogramAggConfig, - searchSource: any, - options: any - ) { - const field = aggConfig.getField(); - const aggBody = field.scripted - ? { script: { source: field.script, lang: field.lang } } - : { field: field.name }; - - const childSearchSource = searchSource - .createChild() - .setField('size', 0) - .setField('aggs', { - maxAgg: { - max: aggBody, - }, - minAgg: { - min: aggBody, - }, - }); - - return childSearchSource - .fetch(options) - .then((resp: any) => { - aggConfig.setAutoBounds({ - min: _.get(resp, 'aggregations.minAgg.value'), - max: _.get(resp, 'aggregations.maxAgg.value'), - }); - }) - .catch((e: Error) => { - if (e.name === 'AbortError') return; - getNotifications().toasts.addWarning( - i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', { - defaultMessage: - 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.', - }) - ); - }); + params: [ + { + name: 'field', + type: 'field', + filterFieldTypes: KBN_FIELD_TYPES.NUMBER, }, - write(aggConfig, output) { - let interval = parseFloat(aggConfig.params.interval); - if (interval <= 0) { - interval = 1; - } - const autoBounds = aggConfig.getAutoBounds(); - - // ensure interval does not create too many buckets and crash browser - if (autoBounds) { - const range = autoBounds.max - autoBounds.min; - const bars = range / interval; - - const config = getUiSettings(); - if (bars > config.get('histogram:maxBars')) { - const minInterval = range / config.get('histogram:maxBars'); - - // Round interval by order of magnitude to provide clean intervals - // Always round interval up so there will always be less buckets than histogram:maxBars - const orderOfMagnitude = Math.pow(10, Math.floor(Math.log10(minInterval))); - let roundInterval = orderOfMagnitude; - - while (roundInterval < minInterval) { - roundInterval += orderOfMagnitude; + { + /* + * This parameter can be set if you want the auto scaled interval to always + * be a multiple of a specific base. + */ + name: 'intervalBase', + default: null, + write: () => {}, + }, + { + name: 'interval', + modifyAggConfigOnSearchRequestStart( + aggConfig: IBucketHistogramAggConfig, + searchSource: any, + options: any + ) { + const field = aggConfig.getField(); + const aggBody = field.scripted + ? { script: { source: field.script, lang: field.lang } } + : { field: field.name }; + + const childSearchSource = searchSource + .createChild() + .setField('size', 0) + .setField('aggs', { + maxAgg: { + max: aggBody, + }, + minAgg: { + min: aggBody, + }, + }); + + return childSearchSource + .fetch(options) + .then((resp: any) => { + aggConfig.setAutoBounds({ + min: get(resp, 'aggregations.minAgg.value'), + max: get(resp, 'aggregations.maxAgg.value'), + }); + }) + .catch((e: Error) => { + if (e.name === 'AbortError') return; + notifications.toasts.addWarning( + i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', { + defaultMessage: + 'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.', + }) + ); + }); + }, + write(aggConfig, output) { + let interval = parseFloat(aggConfig.params.interval); + if (interval <= 0) { + interval = 1; + } + const autoBounds = aggConfig.getAutoBounds(); + + // ensure interval does not create too many buckets and crash browser + if (autoBounds) { + const range = autoBounds.max - autoBounds.min; + const bars = range / interval; + + if (bars > uiSettings.get('histogram:maxBars')) { + const minInterval = range / uiSettings.get('histogram:maxBars'); + + // Round interval by order of magnitude to provide clean intervals + // Always round interval up so there will always be less buckets than histogram:maxBars + const orderOfMagnitude = Math.pow(10, Math.floor(Math.log10(minInterval))); + let roundInterval = orderOfMagnitude; + + while (roundInterval < minInterval) { + roundInterval += orderOfMagnitude; + } + interval = roundInterval; } - interval = roundInterval; } - } - const base = aggConfig.params.intervalBase; - - if (base) { - if (interval < base) { - // In case the specified interval is below the base, just increase it to it's base - interval = base; - } else if (interval % base !== 0) { - // In case the interval is not a multiple of the base round it to the next base - interval = Math.round(interval / base) * base; + const base = aggConfig.params.intervalBase; + + if (base) { + if (interval < base) { + // In case the specified interval is below the base, just increase it to it's base + interval = base; + } else if (interval % base !== 0) { + // In case the interval is not a multiple of the base round it to the next base + interval = Math.round(interval / base) * base; + } } - } - output.params.interval = interval; + output.params.interval = interval; + }, }, - }, - { - name: 'min_doc_count', - default: false, - write(aggConfig, output) { - if (aggConfig.params.min_doc_count) { - output.params.min_doc_count = 0; - } else { - output.params.min_doc_count = 1; - } + { + name: 'min_doc_count', + default: false, + write(aggConfig, output) { + if (aggConfig.params.min_doc_count) { + output.params.min_doc_count = 0; + } else { + output.params.min_doc_count = 1; + } + }, }, - }, - { - name: 'has_extended_bounds', - default: false, - write: () => {}, - }, - { - name: 'extended_bounds', - default: { - min: '', - max: '', + { + name: 'has_extended_bounds', + default: false, + write: () => {}, }, - write(aggConfig, output) { - const { min, max } = aggConfig.params.extended_bounds; + { + name: 'extended_bounds', + default: { + min: '', + max: '', + }, + write(aggConfig, output) { + const { min, max } = aggConfig.params.extended_bounds; - if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) { - output.params.extended_bounds = { min, max }; - } + if (aggConfig.params.has_extended_bounds && (min || min === 0) && (max || max === 0)) { + output.params.extended_bounds = { min, max }; + } + }, + shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds, }, - shouldShow: (aggConfig: IBucketAggConfig) => aggConfig.params.has_extended_bounds, - }, - ], -}); + ], + }); diff --git a/src/plugins/data/public/search/aggs/buckets/range.test.ts b/src/plugins/data/public/search/aggs/buckets/range.test.ts index d9e1af149524c..bf3711543ae88 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.test.ts @@ -48,8 +48,6 @@ describe('Range Agg', () => { mockDataServices(); }); - const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]); - const getConfig = (() => {}) as FieldFormatsGetConfigFn; const getAggConfigs = () => { const field = { @@ -86,7 +84,7 @@ describe('Range Agg', () => { }, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([rangeBucketAgg]) } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts index cee3ed506c29c..1c221126c35e0 100644 --- a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -26,7 +26,6 @@ import { IBucketAggConfig } from './_bucket_agg_type'; describe('Significant Terms Agg', () => { describe('order agg editor UI', () => { describe('convert include/exclude from old format', () => { - const typesRegistry = mockAggTypesRegistry([significantTermsBucketAgg]); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -52,12 +51,12 @@ describe('Significant Terms Agg', () => { params, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry([significantTermsBucketAgg]) } ); }; const testSerializeAndWrite = (aggs: IAggConfigs) => { - const agg = aggs.aggs[0]; + const [agg] = aggs.aggs; const { [BUCKET_TYPES.SIGNIFICANT_TERMS]: params } = agg.toDsl(); expect(params.field).toBe('field'); diff --git a/src/plugins/data/public/search/aggs/buckets/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/terms.test.ts index 9a4f28afd3edf..280d78f6620bd 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.test.ts @@ -23,7 +23,6 @@ import { BUCKET_TYPES } from './bucket_agg_types'; describe('Terms Agg', () => { describe('order agg editor UI', () => { - const typesRegistry = mockAggTypesRegistry(); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -48,7 +47,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - { typesRegistry } + { typesRegistry: mockAggTypesRegistry() } ); }; diff --git a/src/plugins/data/public/search/aggs/index.test.ts b/src/plugins/data/public/search/aggs/index.test.ts index b5dedc9d45e84..8c0e47763c295 100644 --- a/src/plugins/data/public/search/aggs/index.test.ts +++ b/src/plugins/data/public/search/aggs/index.test.ts @@ -22,24 +22,29 @@ import { getAggTypes } from './index'; import { isBucketAggType } from './buckets/_bucket_agg_type'; import { isMetricAggType } from './metrics/metric_agg_type'; +import { QueryStart } from '../../query'; -const aggTypes = getAggTypes({ uiSettings: coreMock.createStart().uiSettings }); +describe('AggTypesComponent', () => { + const core = coreMock.createSetup(); + const aggTypes = getAggTypes({ + uiSettings: core.uiSettings, + notifications: core.notifications, + query: {} as QueryStart, + }); -const bucketAggs = aggTypes.buckets; -const metricAggs = aggTypes.metrics; + const { buckets, metrics } = aggTypes; -describe('AggTypesComponent', () => { describe('bucket aggs', () => { - it('all extend BucketAggType', () => { - bucketAggs.forEach(bucketAgg => { + test('all extend BucketAggType', () => { + buckets.forEach(bucketAgg => { expect(isBucketAggType(bucketAgg)).toBeTruthy(); }); }); }); describe('metric aggs', () => { - it('all extend MetricAggType', () => { - metricAggs.forEach(metricAgg => { + test('all extend MetricAggType', () => { + metrics.forEach(metricAgg => { expect(isMetricAggType(metricAgg)).toBeTruthy(); }); }); diff --git a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts index 1ebd0ea29c9ff..57d27b7da6313 100644 --- a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts +++ b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts @@ -23,6 +23,7 @@ import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry'; import { getAggTypes } from '../agg_types'; import { BucketAggType } from '../buckets/_bucket_agg_type'; import { MetricAggType } from '../metrics/metric_agg_type'; +import { queryServiceMock } from '../../../query/mocks'; /** * Testing utility which creates a new instance of AggTypesRegistry, @@ -51,7 +52,13 @@ export function mockAggTypesRegistry | MetricAggTyp } }); } else { - const aggTypes = getAggTypes({ uiSettings: coreMock.createSetup().uiSettings }); + const core = coreMock.createSetup(); + const aggTypes = getAggTypes({ + uiSettings: core.uiSettings, + notifications: core.notifications, + query: queryServiceMock.createSetupContract(), + }); + aggTypes.buckets.forEach(type => registrySetup.registerBucket(type)); aggTypes.metrics.forEach(type => registrySetup.registerMetric(type)); } diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index d83ddab807bc5..2815b41eaba5c 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -140,7 +140,7 @@ export class SearchInterceptor { }), }, { - toastLifeTimeMs: Infinity, + toastLifeTimeMs: 1000000, } ); }; diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 4bf027b07b833..19308dd387d3a 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -34,7 +34,7 @@ describe('Search service', () => { describe('setup()', () => { it('exposes proper contract', async () => { const setup = searchService.setup(mockCoreSetup, { - version: '8', + packageInfo: { version: '8' }, } as any); expect(setup).toHaveProperty('registerSearchStrategyProvider'); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 311a8a2fc6f60..dc1c99f76d59a 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -25,6 +25,7 @@ import { TStrategyTypes } from './strategy_types'; import { getEsClient, LegacyApiCaller } from './es_client'; import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search'; import { esSearchStrategyProvider } from './es_search/es_search_strategy'; +import { QuerySetup } from '../query/query_service'; import { SearchInterceptor } from './search_interceptor'; import { getAggTypes, @@ -40,6 +41,11 @@ import { siblingPipelineAggHelper, } from './aggs'; +interface SearchServiceSetupDependencies { + packageInfo: PackageInfo; + query: QuerySetup; +} + /** * The search plugin exposes two registration methods for other plugins: * - registerSearchStrategyProvider for plugins to add their own custom @@ -73,13 +79,21 @@ export class SearchService implements Plugin { return strategyProvider; }; - public setup(core: CoreSetup, packageInfo: PackageInfo): ISearchSetup { + public setup( + core: CoreSetup, + { packageInfo, query }: SearchServiceSetupDependencies + ): ISearchSetup { this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo); this.registerSearchStrategyProvider(SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider); this.registerSearchStrategyProvider(ES_SEARCH_STRATEGY, esSearchStrategyProvider); const aggTypesSetup = this.aggTypesRegistry.setup(); - const aggTypes = getAggTypes({ uiSettings: core.uiSettings }); + const aggTypes = getAggTypes({ + query, + uiSettings: core.uiSettings, + notifications: core.notifications, + }); + aggTypes.buckets.forEach(b => aggTypesSetup.registerBucket(b)); aggTypes.metrics.forEach(m => aggTypesSetup.registerMetric(m)); diff --git a/src/plugins/data/public/search/tabify/response_writer.test.ts b/src/plugins/data/public/search/tabify/response_writer.test.ts index ca84f08de8c8a..52338ae79ccbb 100644 --- a/src/plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/plugins/data/public/search/tabify/response_writer.test.ts @@ -106,13 +106,13 @@ describe('TabbedAggResponseWriter class', () => { }); test('adds the row to the array', () => { - responseWriter.bucketBuffer = [{ id: 'col-0', value: 'US' }]; - responseWriter.metricBuffer = [{ id: 'col-1', value: 5 }]; + responseWriter.bucketBuffer = [{ id: 'col-0-1', value: 'US' }]; + responseWriter.metricBuffer = [{ id: 'col-1-2', value: 5 }]; responseWriter.row(); expect(responseWriter.rows.length).toEqual(1); - expect(responseWriter.rows[0]).toEqual({ 'col-0': 'US', 'col-1': 5 }); + expect(responseWriter.rows[0]).toEqual({ 'col-0-1': 'US', 'col-1-2': 5 }); }); test("doesn't add an empty row", () => { @@ -120,6 +120,21 @@ describe('TabbedAggResponseWriter class', () => { expect(responseWriter.rows.length).toEqual(0); }); + + test('doesnt add a partial row', () => { + responseWriter.bucketBuffer = [{ id: 'col-0-1', value: 'US' }]; + responseWriter.row(); + + expect(responseWriter.rows.length).toEqual(0); + }); + + test('adds partial row if partialRows is set to true', () => { + responseWriter = createResponseWritter(splitAggConfig, { partialRows: true }); + responseWriter.bucketBuffer = [{ id: 'col-0-1', value: 'US' }]; + responseWriter.row(); + + expect(responseWriter.rows.length).toEqual(1); + }); }); describe('response()', () => { diff --git a/src/plugins/data/public/search/tabify/response_writer.ts b/src/plugins/data/public/search/tabify/response_writer.ts index cacecbec3be0b..02e18d75ae6e5 100644 --- a/src/plugins/data/public/search/tabify/response_writer.ts +++ b/src/plugins/data/public/search/tabify/response_writer.ts @@ -69,10 +69,9 @@ export class TabbedAggResponseWriter { rowBuffer[metric.id] = metric.value; }); - const isPartialRow = - this.partialRows && !this.columns.every(column => rowBuffer.hasOwnProperty(column.id)); - - if (!isEmpty(rowBuffer) && !isPartialRow) { + const isPartialRow = !this.columns.every(column => rowBuffer.hasOwnProperty(column.id)); + const removePartial = isPartialRow && !this.partialRows; + if (!isEmpty(rowBuffer) && !removePartial) { this.rows.push(rowBuffer); } } diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index 2af87d84b780e..199ba17b3b81b 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -17,8 +17,7 @@ * under the License. */ -import { NotificationsStart } from 'src/core/public'; -import { CoreSetup, CoreStart } from 'kibana/public'; +import { NotificationsStart, CoreSetup, CoreStart } from 'src/core/public'; import { FieldFormatsStart } from './field_formats'; import { createGetterSetter } from '../../kibana_utils/public'; import { IndexPatternsContract } from './index_patterns'; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 5038b4226fad8..47bef4255347c 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -173,6 +173,7 @@ export { ISearchContext, TSearchStrategyProvider, getDefaultSearchParams, + getTotalLoaded, } from './search'; // Search namespace diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index b4ee02eefaf84..47cad7aa6b4d7 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -21,7 +21,7 @@ import { APICaller } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { ES_SEARCH_STRATEGY } from '../../../common/search'; import { ISearchStrategy, TSearchStrategyProvider } from '../i_search_strategy'; -import { getDefaultSearchParams, ISearchContext } from '..'; +import { getDefaultSearchParams, getTotalLoaded, ISearchContext } from '..'; export const esSearchStrategyProvider: TSearchStrategyProvider = ( context: ISearchContext, @@ -46,9 +46,7 @@ export const esSearchStrategyProvider: TSearchStrategyProvider { + it('returns the total/loaded, not including skipped', () => { + const result = getTotalLoaded({ + successful: 10, + failed: 5, + skipped: 5, + total: 100, + }); + + expect(result).toEqual({ + total: 100, + loaded: 15, + }); + }); +}); diff --git a/src/legacy/core_plugins/visualizations/public/index.ts b/src/plugins/data/server/search/es_search/get_total_loaded.ts similarity index 68% rename from src/legacy/core_plugins/visualizations/public/index.ts rename to src/plugins/data/server/search/es_search/get_total_loaded.ts index f5590c745b3f9..b5af600e84eff 100644 --- a/src/legacy/core_plugins/visualizations/public/index.ts +++ b/src/plugins/data/server/search/es_search/get_total_loaded.ts @@ -17,10 +17,14 @@ * under the License. */ +import { ShardsResponse } from 'elasticsearch'; + /** - * Static np-ready code, re-exported here so consumers can import from - * `src/legacy/core_plugins/visualizations/public` - * - * @public + * Get the `total`/`loaded` for this response (see `IKibanaSearchResponse`). Note that `skipped` is + * not included as it is already included in `successful`. + * @internal */ -export * from './np_ready/public'; +export function getTotalLoaded({ total, failed, successful }: ShardsResponse) { + const loaded = failed + successful; + return { total, loaded }; +} diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 5a8b3bc94c679..20006b70730d8 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -20,3 +20,4 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; export { getDefaultSearchParams } from './get_default_search_params'; +export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 15738a3befb27..e08eba1cad831 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -33,4 +33,4 @@ export { TStrategyTypes } from './strategy_types'; export { TSearchStrategyProvider } from './i_search_strategy'; -export { getDefaultSearchParams } from './es_search'; +export { getDefaultSearchParams, getTotalLoaded } from './es_search'; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 1abc74fe07ccc..c41023eab6d20 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -125,6 +125,7 @@ import { SearchResponse } from 'elasticsearch'; import { SearchShardsParams } from 'elasticsearch'; import { SearchTemplateParams } from 'elasticsearch'; import { ShallowPromise } from '@kbn/utility-types'; +import { ShardsResponse } from 'elasticsearch'; import { SnapshotCreateParams } from 'elasticsearch'; import { SnapshotCreateRepositoryParams } from 'elasticsearch'; import { SnapshotDeleteParams } from 'elasticsearch'; @@ -330,6 +331,12 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// @internal +export function getTotalLoaded({ total, failed, successful }: ShardsResponse): { + total: number; + loaded: number; +}; + // Warning: (ae-missing-release-tag) "IFieldFormatsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -730,12 +737,12 @@ export type TSearchStrategyProvider = (context: ISearc // src/plugins/data/server/index.ts:102:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:130:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:130:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:181:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:182:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:183:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:188:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:182:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:183:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:189:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:64:14 - (ae-forgotten-export) The symbol "ISearchSetup" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts index d37cba6f897c8..9125dc0813f98 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts @@ -33,7 +33,7 @@ interface ActionContext { export class EditPanelAction implements Action { public readonly type = ACTION_EDIT_PANEL; public readonly id = ACTION_EDIT_PANEL; - public order = 50; + public order = 15; constructor(private readonly getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']) {} diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index 35973cc16cf9b..eb10c16806640 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -16,35 +16,23 @@ * specific language governing permissions and limitations * under the License. */ -import { cloneDeep, isEqual } from 'lodash'; +import { isEqual, cloneDeep } from 'lodash'; import * as Rx from 'rxjs'; -import { Adapters, ViewMode } from '../types'; +import { Adapters } from '../types'; import { IContainer } from '../containers'; -import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; +import { IEmbeddable, EmbeddableInput, EmbeddableOutput } from './i_embeddable'; +import { ViewMode } from '../types'; import { TriggerContextMapping } from '../ui_actions'; import { EmbeddableActionStorage } from './embeddable_action_storage'; -import { - UiActionsDynamicActionManager, - UiActionsStart, -} from '../../../../../plugins/ui_actions/public'; -import { EmbeddableContext } from '../triggers'; function getPanelTitle(input: EmbeddableInput, output: EmbeddableOutput) { return input.hidePanelTitles ? '' : input.title === undefined ? output.defaultTitle : input.title; } -export interface EmbeddableParams { - uiActions?: UiActionsStart; -} - export abstract class Embeddable< TEmbeddableInput extends EmbeddableInput = EmbeddableInput, TEmbeddableOutput extends EmbeddableOutput = EmbeddableOutput > implements IEmbeddable { - static runtimeId: number = 0; - - public readonly runtimeId = Embeddable.runtimeId++; - public readonly parent?: IContainer; public readonly isContainer: boolean = false; public abstract readonly type: string; @@ -60,34 +48,15 @@ export abstract class Embeddable< // to update input when the parent changes. private parentSubscription?: Rx.Subscription; - private storageSubscription?: Rx.Subscription; - // TODO: Rename to destroyed. private destoyed: boolean = false; - private storage = new EmbeddableActionStorage((this as unknown) as Embeddable); - - private cachedDynamicActions?: UiActionsDynamicActionManager; - public get dynamicActions(): UiActionsDynamicActionManager | undefined { - if (!this.params.uiActions) return undefined; - if (!this.cachedDynamicActions) { - this.cachedDynamicActions = new UiActionsDynamicActionManager({ - isCompatible: async (context: unknown) => - (context as EmbeddableContext).embeddable.runtimeId === this.runtimeId, - storage: this.storage, - uiActions: this.params.uiActions, - }); - } - - return this.cachedDynamicActions; + private __actionStorage?: EmbeddableActionStorage; + public get actionStorage(): EmbeddableActionStorage { + return this.__actionStorage || (this.__actionStorage = new EmbeddableActionStorage(this)); } - constructor( - input: TEmbeddableInput, - output: TEmbeddableOutput, - parent?: IContainer, - public readonly params: EmbeddableParams = {} - ) { + constructor(input: TEmbeddableInput, output: TEmbeddableOutput, parent?: IContainer) { this.id = input.id; this.output = { title: getPanelTitle(input, output), @@ -111,18 +80,6 @@ export abstract class Embeddable< this.onResetInput(newInput); }); } - - if (this.dynamicActions) { - this.dynamicActions.start().catch(error => { - /* eslint-disable */ - console.log('Failed to start embeddable dynamic actions', this); - console.error(error); - /* eslint-enable */ - }); - this.storageSubscription = this.input$.subscribe(() => { - this.storage.reload$.next(); - }); - } } public getIsContainer(): this is IContainer { @@ -201,20 +158,6 @@ export abstract class Embeddable< */ public destroy(): void { this.destoyed = true; - - if (this.dynamicActions) { - this.dynamicActions.stop().catch(error => { - /* eslint-disable */ - console.log('Failed to stop embeddable dynamic actions', this); - console.error(error); - /* eslint-enable */ - }); - } - - if (this.storageSubscription) { - this.storageSubscription.unsubscribe(); - } - if (this.parentSubscription) { this.parentSubscription.unsubscribe(); } diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.test.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.test.ts index 83fd3f184e098..56facc37fc666 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.test.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.test.ts @@ -20,8 +20,7 @@ import { Embeddable } from './embeddable'; import { EmbeddableInput } from './i_embeddable'; import { ViewMode } from '../types'; -import { EmbeddableActionStorage } from './embeddable_action_storage'; -import { UiActionsSerializedEvent } from '../../../../ui_actions/public'; +import { EmbeddableActionStorage, SerializedEvent } from './embeddable_action_storage'; import { of } from '../../../../kibana_utils/common'; class TestEmbeddable extends Embeddable { @@ -43,9 +42,9 @@ describe('EmbeddableActionStorage', () => { test('can add event to embeddable', async () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -58,40 +57,23 @@ describe('EmbeddableActionStorage', () => { expect(events2).toEqual([event]); }); - test('does not merge .getInput() into .updateInput()', async () => { - const embeddable = new TestEmbeddable(); - const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { - eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], - action: {} as any, - }; - - const spy = jest.spyOn(embeddable, 'updateInput'); - - await storage.create(event); - - expect(spy.mock.calls[0][0].id).toBe(undefined); - expect(spy.mock.calls[0][0].viewMode).toBe(undefined); - }); - test('can create multiple events', async () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; - const event3: UiActionsSerializedEvent = { + const event3: SerializedEvent = { eventId: 'EVENT_ID3', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -113,9 +95,9 @@ describe('EmbeddableActionStorage', () => { test('throws when creating an event with the same ID', async () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -140,16 +122,16 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'foo', } as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'bar', } as any, @@ -166,30 +148,30 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'foo', } as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'bar', } as any, }; - const event22: UiActionsSerializedEvent = { + const event22: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'baz', } as any, }; - const event3: UiActionsSerializedEvent = { + const event3: SerializedEvent = { eventId: 'EVENT_ID3', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'qux', } as any, @@ -217,9 +199,9 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -235,14 +217,14 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -267,9 +249,9 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -284,23 +266,23 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'foo', } as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'bar', } as any, }; - const event3: UiActionsSerializedEvent = { + const event3: SerializedEvent = { eventId: 'EVENT_ID3', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: { name: 'qux', } as any, @@ -345,9 +327,9 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -373,9 +355,9 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -401,9 +383,9 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event: UiActionsSerializedEvent = { + const event: SerializedEvent = { eventId: 'EVENT_ID', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID', action: {} as any, }; @@ -420,19 +402,19 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID1', action: {} as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID2', action: {} as any, }; - const event3: UiActionsSerializedEvent = { + const event3: SerializedEvent = { eventId: 'EVENT_ID3', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID3', action: {} as any, }; @@ -476,7 +458,7 @@ describe('EmbeddableActionStorage', () => { await storage.create({ eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID1', action: {} as any, }); @@ -484,7 +466,7 @@ describe('EmbeddableActionStorage', () => { await storage.create({ eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID1', action: {} as any, }); @@ -520,15 +502,15 @@ describe('EmbeddableActionStorage', () => { const embeddable = new TestEmbeddable(); const storage = new EmbeddableActionStorage(embeddable); - const event1: UiActionsSerializedEvent = { + const event1: SerializedEvent = { eventId: 'EVENT_ID1', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID1', action: {} as any, }; - const event2: UiActionsSerializedEvent = { + const event2: SerializedEvent = { eventId: 'EVENT_ID2', - triggers: ['TRIGGER-ID'], + triggerId: 'TRIGGER-ID1', action: {} as any, }; diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.ts index fad5b4d535d6c..520f92840c5f9 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_action_storage.ts @@ -17,20 +17,32 @@ * under the License. */ -import { - UiActionsAbstractActionStorage, - UiActionsSerializedEvent, -} from '../../../../ui_actions/public'; import { Embeddable } from '..'; -export class EmbeddableActionStorage extends UiActionsAbstractActionStorage { - constructor(private readonly embbeddable: Embeddable) { - super(); - } +/** + * Below two interfaces are here temporarily, they will move to `ui_actions` + * plugin once #58216 is merged. + */ +export interface SerializedEvent { + eventId: string; + triggerId: string; + action: unknown; +} +export interface ActionStorage { + create(event: SerializedEvent): Promise; + update(event: SerializedEvent): Promise; + remove(eventId: string): Promise; + read(eventId: string): Promise; + count(): Promise; + list(): Promise; +} - async create(event: UiActionsSerializedEvent) { +export class EmbeddableActionStorage implements ActionStorage { + constructor(private readonly embbeddable: Embeddable) {} + + async create(event: SerializedEvent) { const input = this.embbeddable.getInput(); - const events = (input.events || []) as UiActionsSerializedEvent[]; + const events = (input.events || []) as SerializedEvent[]; const exists = !!events.find(({ eventId }) => eventId === event.eventId); if (exists) { @@ -41,13 +53,14 @@ export class EmbeddableActionStorage extends UiActionsAbstractActionStorage { } this.embbeddable.updateInput({ + ...input, events: [...events, event], }); } - async update(event: UiActionsSerializedEvent) { + async update(event: SerializedEvent) { const input = this.embbeddable.getInput(); - const events = (input.events || []) as UiActionsSerializedEvent[]; + const events = (input.events || []) as SerializedEvent[]; const index = events.findIndex(({ eventId }) => eventId === event.eventId); if (index === -1) { @@ -59,13 +72,14 @@ export class EmbeddableActionStorage extends UiActionsAbstractActionStorage { } this.embbeddable.updateInput({ + ...input, events: [...events.slice(0, index), event, ...events.slice(index + 1)], }); } async remove(eventId: string) { const input = this.embbeddable.getInput(); - const events = (input.events || []) as UiActionsSerializedEvent[]; + const events = (input.events || []) as SerializedEvent[]; const index = events.findIndex(event => eventId === event.eventId); if (index === -1) { @@ -77,13 +91,14 @@ export class EmbeddableActionStorage extends UiActionsAbstractActionStorage { } this.embbeddable.updateInput({ + ...input, events: [...events.slice(0, index), ...events.slice(index + 1)], }); } - async read(eventId: string): Promise { + async read(eventId: string): Promise { const input = this.embbeddable.getInput(); - const events = (input.events || []) as UiActionsSerializedEvent[]; + const events = (input.events || []) as SerializedEvent[]; const event = events.find(ev => eventId === ev.eventId); if (!event) { @@ -98,10 +113,14 @@ export class EmbeddableActionStorage extends UiActionsAbstractActionStorage { private __list() { const input = this.embbeddable.getInput(); - return (input.events || []) as UiActionsSerializedEvent[]; + return (input.events || []) as SerializedEvent[]; + } + + async count(): Promise { + return this.__list().length; } - async list(): Promise { + async list(): Promise { return this.__list(); } } diff --git a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts index 9a4452aceba00..6345c34b0dda2 100644 --- a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts +++ b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts @@ -18,7 +18,6 @@ */ import { Observable } from 'rxjs'; -import { UiActionsDynamicActionManager } from '../../../../../plugins/ui_actions/public'; import { Adapters } from '../types'; import { IContainer } from '../containers/i_container'; import { ViewMode } from '../types'; @@ -34,7 +33,7 @@ export interface EmbeddableInput { /** * Reserved key for `ui_actions` events. */ - events?: Array<{ eventId: string }>; + events?: unknown; /** * List of action IDs that this embeddable should not render. @@ -83,19 +82,6 @@ export interface IEmbeddable< **/ readonly id: string; - /** - * Unique ID an embeddable is assigned each time it is initialized. This ID - * is different for different instances of the same embeddable. For example, - * if the same dashboard is rendered twice on the screen, all embeddable - * instances will have a unique `runtimeId`. - */ - readonly runtimeId?: number; - - /** - * Default implementation of dynamic action API for embeddables. - */ - dynamicActions?: UiActionsDynamicActionManager; - /** * A functional representation of the isContainer variable, but helpful for typescript to * know the shape if this returns true diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx index 83d3d5e10761b..757d4e6bfddef 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx @@ -44,7 +44,7 @@ import { import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks'; import { EuiBadge } from '@elastic/eui'; -const actionRegistry = new Map(); +const actionRegistry = new Map>(); const triggerRegistry = new Map(); const embeddableFactories = new Map(); const getEmbeddableFactory = (id: string) => embeddableFactories.get(id); @@ -213,17 +213,13 @@ const renderInEditModeAndOpenContextMenu = async ( }; test('HelloWorldContainer in edit mode hides disabledActions', async () => { - const action = { + const action: Action = { id: 'FOO', type: 'FOO' as ActionType, getIconType: () => undefined, getDisplayName: () => 'foo', isCompatible: async () => true, execute: async () => {}, - order: 10, - getHref: () => { - return undefined; - }, }; const getActions = () => Promise.resolve([action]); @@ -249,17 +245,13 @@ test('HelloWorldContainer in edit mode hides disabledActions', async () => { }); test('HelloWorldContainer hides disabled badges', async () => { - const action = { + const action: Action = { id: 'BAR', type: 'BAR' as ActionType, getIconType: () => undefined, getDisplayName: () => 'bar', isCompatible: async () => true, execute: async () => {}, - order: 10, - getHref: () => { - return undefined; - }, }; const getActions = () => Promise.resolve([action]); diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx index c6537f2d94994..b95060a73252f 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx @@ -38,14 +38,6 @@ import { EditPanelAction } from '../actions'; import { CustomizePanelModal } from './panel_header/panel_actions/customize_title/customize_panel_modal'; import { EmbeddableStart } from '../../plugin'; -const sortByOrderField = ( - { order: orderA }: { order?: number }, - { order: orderB }: { order?: number } -) => (orderB || 0) - (orderA || 0); - -const removeById = (disabledActions: string[]) => ({ id }: { id: string }) => - disabledActions.indexOf(id) === -1; - interface Props { embeddable: IEmbeddable; getActions: UiActionsService['getTriggerCompatibleActions']; @@ -65,14 +57,12 @@ interface State { hidePanelTitles: boolean; closeContextMenu: boolean; badges: Array>; - eventCount?: number; } export class EmbeddablePanel extends React.Component { private embeddableRoot: React.RefObject; private parentSubscription?: Subscription; private subscription?: Subscription; - private eventCountSubscription?: Subscription; private mounted: boolean = false; private generateId = htmlIdGenerator(); @@ -146,9 +136,6 @@ export class EmbeddablePanel extends React.Component { if (this.subscription) { this.subscription.unsubscribe(); } - if (this.eventCountSubscription) { - this.eventCountSubscription.unsubscribe(); - } if (this.parentSubscription) { this.parentSubscription.unsubscribe(); } @@ -190,7 +177,6 @@ export class EmbeddablePanel extends React.Component { badges={this.state.badges} embeddable={this.props.embeddable} headerId={headerId} - eventCount={this.state.eventCount} /> )}
@@ -202,15 +188,6 @@ export class EmbeddablePanel extends React.Component { if (this.embeddableRoot.current) { this.props.embeddable.render(this.embeddableRoot.current); } - - const dynamicActions = this.props.embeddable.dynamicActions; - if (dynamicActions) { - this.setState({ eventCount: dynamicActions.state.get().events.length }); - this.eventCountSubscription = dynamicActions.state.state$.subscribe(({ events }) => { - if (!this.mounted) return; - this.setState({ eventCount: events.length }); - }); - } } closeMyContextMenuPanel = () => { @@ -224,14 +201,13 @@ export class EmbeddablePanel extends React.Component { }; private getActionContextMenuPanel = async () => { - let regularActions = await this.props.getActions(CONTEXT_MENU_TRIGGER, { + let actions = await this.props.getActions(CONTEXT_MENU_TRIGGER, { embeddable: this.props.embeddable, }); const { disabledActions } = this.props.embeddable.getInput(); if (disabledActions) { - const removeDisabledActions = removeById(disabledActions); - regularActions = regularActions.filter(removeDisabledActions); + actions = actions.filter(action => disabledActions.indexOf(action.id) === -1); } const createGetUserData = (overlays: OverlayStart) => @@ -270,10 +246,16 @@ export class EmbeddablePanel extends React.Component { new EditPanelAction(this.props.getEmbeddableFactory), ]; - const sortedActions = [...regularActions, ...extraActions].sort(sortByOrderField); + const sorted = actions + .concat(extraActions) + .sort((a: Action, b: Action) => { + const bOrder = b.order || 0; + const aOrder = a.order || 0; + return bOrder - aOrder; + }); return await buildContextMenuForActions({ - actions: sortedActions, + actions: sorted, actionContext: { embeddable: this.props.embeddable }, closeMenu: this.closeMyContextMenuPanel, }); diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts index 36957c3b79491..c0e43c0538833 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts @@ -33,13 +33,15 @@ interface ActionContext { export class CustomizePanelTitleAction implements Action { public readonly type = ACTION_CUSTOMIZE_PANEL; public id = ACTION_CUSTOMIZE_PANEL; - public order = 40; + public order = 10; - constructor(private readonly getDataFromUser: GetUserData) {} + constructor(private readonly getDataFromUser: GetUserData) { + this.order = 10; + } public getDisplayName() { return i18n.translate('embeddableApi.customizePanel.action.displayName', { - defaultMessage: 'Edit panel title', + defaultMessage: 'Customize panel', }); } diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.ts b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.ts index ae9645767b267..d04f35715537c 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.ts +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.ts @@ -31,7 +31,7 @@ interface ActionContext { export class InspectPanelAction implements Action { public readonly type = ACTION_INSPECT_PANEL; public readonly id = ACTION_INSPECT_PANEL; - public order = 20; + public order = 10; constructor(private readonly inspector: InspectorStartContract) {} diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.ts b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.ts index a6d4128f3f106..ee7948f3d6a4a 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.ts +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/remove_panel_action.ts @@ -41,7 +41,7 @@ function hasExpandedPanelInput( export class RemovePanelAction implements Action { public readonly type = REMOVE_PANEL_ACTION; public readonly id = REMOVE_PANEL_ACTION; - public order = 1; + public order = 5; constructor() {} diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx index 2a856af7ae916..99516a1d21d6f 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx @@ -23,7 +23,6 @@ import { EuiIcon, EuiToolTip, EuiScreenReaderOnly, - EuiNotificationBadge, } from '@elastic/eui'; import classNames from 'classnames'; import React from 'react'; @@ -41,7 +40,6 @@ export interface PanelHeaderProps { badges: Array>; embeddable: IEmbeddable; headerId?: string; - eventCount?: number; } function renderBadges(badges: Array>, embeddable: IEmbeddable) { @@ -92,7 +90,6 @@ export function PanelHeader({ badges, embeddable, headerId, - eventCount, }: PanelHeaderProps) { const viewDescription = getViewDescription(embeddable); const showTitle = !isViewMode || (title && !hidePanelTitles) || viewDescription !== ''; @@ -150,11 +147,7 @@ export function PanelHeader({ )} {renderBadges(badges, embeddable)} - {!isViewMode && !!eventCount && ( - - {eventCount} - - )} + { + if (error.name === 'AbortError') { + handlers.done(); + return; + } + getNotifications().toasts.addError(error, { title: i18n.translate('expressions.defaultErrorRenderer.errorTitle', { defaultMessage: 'Error in visualisation', diff --git a/src/plugins/home/public/plugin.ts b/src/plugins/home/public/plugin.ts index 2353df600aa69..fab7808b5072e 100644 --- a/src/plugins/home/public/plugin.ts +++ b/src/plugins/home/public/plugin.ts @@ -50,7 +50,9 @@ export interface HomePluginSetupDependencies { kibanaLegacy: KibanaLegacySetup; } -export class HomePublicPlugin implements Plugin { +export class HomePublicPlugin + implements + Plugin { private readonly featuresCatalogueRegistry = new FeatureCatalogueRegistry(); private readonly environmentService = new EnvironmentService(); private readonly tutorialService = new TutorialService(); diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index 303dbd9a9d856..a694802663171 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -50,7 +50,7 @@ supports the "asa" fileset for Cisco ASA firewall logs received over syslog or r learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', }, }), - // euiIconType: 'logoCisco', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/cisco.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index ac2db66dff6b6..53803a9358a14 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -50,7 +50,7 @@ It supports both standalone deployment and Envoy proxy deployment in Kubernetes. learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', }, }), - // euiIconType: 'logoCisco', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/envoyproxy.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts index ff9996c1b0187..82ce098018e0b 100644 --- a/src/plugins/home/server/tutorials/iis_logs/index.ts +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -49,7 +49,7 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iis.html', }, }), - // euiIconType: 'logoIIS', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/iis.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index e3f2124347b6b..b29ab20cb6653 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -52,7 +52,7 @@ number and the action performed on the traffic (allow/deny).. \ learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', }, }), - // euiIconType: 'logoUbiquiti', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/ubiquiti.svg', artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts index cea46c3220d5a..a1c994d670a3d 100644 --- a/src/plugins/home/server/tutorials/mssql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -48,7 +48,7 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mssql.html', }, }), - // euiIconType: 'logoMSSQL', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/mssql.svg', isBeta: false, artifacts: { dashboards: [ diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts index e438d3015c77c..90e4ac6026dad 100644 --- a/src/plugins/home/server/tutorials/munin_metrics/index.ts +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -36,6 +36,7 @@ export function muninMetricsSpecProvider(context: TutorialContext): TutorialSche name: i18n.translate('home.tutorials.muninMetrics.nameTitle', { defaultMessage: 'Munin metrics', }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/munin.svg', isBeta: true, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.muninMetrics.shortDescription', { diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index ac19cf0987b84..a3812fda147f5 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -50,7 +50,7 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', }, }), - // euiIconType: 'logoSuricata', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/suricata.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts index fc2fa4f49fd5f..ab8184c1b3249 100644 --- a/src/plugins/home/server/tutorials/system_logs/index.ts +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -50,6 +50,7 @@ Unix/Linux based distributions. This module is not available on Windows. \ learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-system.html', }, }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/system.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts index b0355e1118a96..456804c51f838 100644 --- a/src/plugins/home/server/tutorials/system_metrics/index.ts +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -49,6 +49,7 @@ It collects system wide statistics and statistics per process and filesystem. \ learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-system.html', }, }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/system.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 423023a3902e5..56f1d56ea0123 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -49,7 +49,7 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', }, }), - // euiIconType: 'logoTraefik', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/traefik.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts index fc36cfe869867..a1dfbc64ec244 100644 --- a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -48,7 +48,7 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', }, }), - // euiIconType: 'logouWSGI', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/uwsgi.svg', isBeta: false, artifacts: { dashboards: [ diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts index 3ea57cdbc0e44..908b6440f88c6 100644 --- a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -48,7 +48,7 @@ export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', }, }), - // euiIconType: 'logoVSphere', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/vsphere.svg', isBeta: true, artifacts: { application: { diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index c015545046c99..251825147ded1 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -50,7 +50,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', }, }), - // TODO: euiIconType: 'logoZeek', + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/zeek.svg', artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts index dcecbb6d4a812..581b4a14a2f38 100644 --- a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -36,6 +36,7 @@ export function zookeeperMetricsSpecProvider(context: TutorialContext): Tutorial name: i18n.translate('home.tutorials.zookeeperMetrics.nameTitle', { defaultMessage: 'Zookeeper metrics', }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/zookeeper.svg', isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.zookeeperMetrics.shortDescription', { diff --git a/src/plugins/kibana_utils/common/state_containers/create_state_container_react_helpers.ts b/src/plugins/kibana_utils/common/state_containers/create_state_container_react_helpers.ts index 90823359359a1..36903f2d7c90f 100644 --- a/src/plugins/kibana_utils/common/state_containers/create_state_container_react_helpers.ts +++ b/src/plugins/kibana_utils/common/state_containers/create_state_container_react_helpers.ts @@ -24,58 +24,15 @@ import { Comparator, Connect, StateContainer, UnboxState } from './types'; const { useContext, useLayoutEffect, useRef, createElement: h } = React; -/** - * Returns the latest state of a state container. - * - * @param container State container which state to track. - */ -export const useContainerState = >( - container: Container -): UnboxState => useObservable(container.state$, container.get()); - -/** - * Apply selector to state container to extract only needed information. Will - * re-render your component only when the section changes. - * - * @param container State container which state to track. - * @param selector Function used to pick parts of state. - * @param comparator Comparator function used to memoize previous result, to not - * re-render React component if state did not change. By default uses - * `fast-deep-equal` package. - */ -export const useContainerSelector = , Result>( - container: Container, - selector: (state: UnboxState) => Result, - comparator: Comparator = defaultComparator -): Result => { - const { state$, get } = container; - const lastValueRef = useRef(get()); - const [value, setValue] = React.useState(() => { - const newValue = selector(get()); - lastValueRef.current = newValue; - return newValue; - }); - useLayoutEffect(() => { - const subscription = state$.subscribe((currentState: UnboxState) => { - const newValue = selector(currentState); - if (!comparator(lastValueRef.current, newValue)) { - lastValueRef.current = newValue; - setValue(newValue); - } - }); - return () => subscription.unsubscribe(); - }, [state$, comparator]); - return value; -}; - export const createStateContainerReactHelpers = >() => { const context = React.createContext(null as any); const useContainer = (): Container => useContext(context); const useState = (): UnboxState => { - const container = useContainer(); - return useContainerState(container); + const { state$, get } = useContainer(); + const value = useObservable(state$, get()); + return value; }; const useTransitions: () => Container['transitions'] = () => useContainer().transitions; @@ -84,8 +41,24 @@ export const createStateContainerReactHelpers = ) => Result, comparator: Comparator = defaultComparator ): Result => { - const container = useContainer(); - return useContainerSelector(container, selector, comparator); + const { state$, get } = useContainer(); + const lastValueRef = useRef(get()); + const [value, setValue] = React.useState(() => { + const newValue = selector(get()); + lastValueRef.current = newValue; + return newValue; + }); + useLayoutEffect(() => { + const subscription = state$.subscribe((currentState: UnboxState) => { + const newValue = selector(currentState); + if (!comparator(lastValueRef.current, newValue)) { + lastValueRef.current = newValue; + setValue(newValue); + } + }); + return () => subscription.unsubscribe(); + }, [state$, comparator]); + return value; }; const connect: Connect> = mapStateToProp => component => props => diff --git a/src/plugins/kibana_utils/common/state_containers/types.ts b/src/plugins/kibana_utils/common/state_containers/types.ts index 29ffa4cd486b5..26a29bc470e8a 100644 --- a/src/plugins/kibana_utils/common/state_containers/types.ts +++ b/src/plugins/kibana_utils/common/state_containers/types.ts @@ -43,7 +43,7 @@ export interface BaseStateContainer { export interface StateContainer< State extends BaseState, - PureTransitions extends object = object, + PureTransitions extends object, PureSelectors extends object = {} > extends BaseStateContainer { transitions: Readonly>; diff --git a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx index cbdeef6fbe96c..8a4cc88999bfe 100644 --- a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx +++ b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx @@ -37,6 +37,7 @@ export function redirectWhenMissing({ history, mapping, toastNotifications, + onBeforeRedirect, }: { history: History; /** @@ -48,6 +49,10 @@ export function redirectWhenMissing({ * Toast notifications service to show toasts in error cases. */ toastNotifications: ToastsSetup; + /** + * Optional callback invoked directly before a redirect is triggered + */ + onBeforeRedirect?: (error: SavedObjectNotFound) => void; }) { let localMappingObject: Mapping; @@ -75,6 +80,9 @@ export function redirectWhenMissing({ text: toMountPoint({error.message}), }); + if (onBeforeRedirect) { + onBeforeRedirect(error); + } history.replace(url); }; } diff --git a/src/plugins/saved_objects/kibana.json b/src/plugins/saved_objects/kibana.json index 4081c9a4b21b9..0792955b7c5f1 100644 --- a/src/plugins/saved_objects/kibana.json +++ b/src/plugins/saved_objects/kibana.json @@ -3,5 +3,5 @@ "version": "kibana", "server": false, "ui": true, - "requiredPlugins": [] + "requiredPlugins": ["data"] } diff --git a/src/plugins/saved_objects/public/plugin.ts b/src/plugins/saved_objects/public/plugin.ts index 5092f7a0b7b33..0f5773c00283e 100644 --- a/src/plugins/saved_objects/public/plugin.ts +++ b/src/plugins/saved_objects/public/plugin.ts @@ -17,11 +17,31 @@ * under the License. */ -import { Plugin } from 'src/core/public'; +import { CoreStart, Plugin } from 'src/core/public'; import './index.scss'; +import { createSavedObjectClass } from './saved_object'; +import { DataPublicPluginStart } from '../../data/public'; -export class SavedObjectsPublicPlugin implements Plugin { +export interface SavedObjectsStart { + SavedObjectClass: any; +} + +export interface SavedObjectsStartDeps { + data: DataPublicPluginStart; +} + +export class SavedObjectsPublicPlugin + implements Plugin { public setup() {} - public start() {} + public start(core: CoreStart, { data }: SavedObjectsStartDeps) { + return { + SavedObjectClass: createSavedObjectClass({ + indexPatterns: data.indexPatterns, + savedObjectsClient: core.savedObjects.client, + chrome: core.chrome, + overlays: core.overlays, + }), + }; + } } diff --git a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts index 178edadaff6c4..e83f5c0b6bafb 100644 --- a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts +++ b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts @@ -56,7 +56,7 @@ export class SavedObjectLoader { * @param id * @returns {Promise} */ - async get(id: string) { + async get(id?: string) { // @ts-ignore const obj = new this.Class(id); return obj.init(); diff --git a/src/plugins/saved_objects_management/kibana.json b/src/plugins/saved_objects_management/kibana.json new file mode 100644 index 0000000000000..e1f14b0e3c59d --- /dev/null +++ b/src/plugins/saved_objects_management/kibana.json @@ -0,0 +1,7 @@ +{ + "id": "savedObjectsManagement", + "version": "kibana", + "server": true, + "ui": true, + "requiredPlugins": ["home"] +} diff --git a/src/plugins/saved_objects_management/public/index.ts b/src/plugins/saved_objects_management/public/index.ts new file mode 100644 index 0000000000000..7fb2f137d7d84 --- /dev/null +++ b/src/plugins/saved_objects_management/public/index.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from 'kibana/public'; +import { SavedObjectsManagementPlugin } from './plugin'; + +export { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './plugin'; +export { + ISavedObjectsManagementActionRegistry, + SavedObjectsManagementAction, + SavedObjectsManagementRecord, +} from './services'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new SavedObjectsManagementPlugin(); +} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/initialize.js b/src/plugins/saved_objects_management/public/mocks.ts similarity index 54% rename from test/plugin_functional/plugins/kbn_tp_top_nav/public/initialize.js rename to src/plugins/saved_objects_management/public/mocks.ts index d46e47f6d248a..8cf23afe87907 100644 --- a/test/plugin_functional/plugins/kbn_tp_top_nav/public/initialize.js +++ b/src/plugins/saved_objects_management/public/mocks.ts @@ -17,25 +17,23 @@ * under the License. */ -import { npSetup } from 'ui/new_platform'; +import { actionRegistryMock } from './services/action_registry.mock'; +import { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './plugin'; -const customExtension = { - id: 'registered-prop', - label: 'Registered Button', - description: 'Registered Demo', - run() {}, - testId: 'demoRegisteredNewButton', +const createSetupContractMock = (): jest.Mocked => { + const mock = { + actionRegistry: actionRegistryMock.create(), + }; + return mock; }; -npSetup.plugins.navigation.registerMenuItem(customExtension); - -const customDiscoverExtension = { - id: 'registered-discover-prop', - label: 'Registered Discover Button', - description: 'Registered Discover Demo', - run() {}, - testId: 'demoDiscoverRegisteredNewButton', - appName: 'discover', +const createStartContractMock = (): jest.Mocked => { + const mock = {}; + return mock; }; -npSetup.plugins.navigation.registerMenuItem(customDiscoverExtension); +export const savedObjectsManagementPluginMock = { + createActionRegistry: actionRegistryMock.create, + createSetupContract: createSetupContractMock, + createStartContract: createStartContractMock, +}; diff --git a/src/plugins/saved_objects_management/public/plugin.test.ts b/src/plugins/saved_objects_management/public/plugin.test.ts new file mode 100644 index 0000000000000..1cafbb235ad5b --- /dev/null +++ b/src/plugins/saved_objects_management/public/plugin.test.ts @@ -0,0 +1,47 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { coreMock } from '../../../core/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { homePluginMock } from '../../home/public/mocks'; +import { SavedObjectsManagementPlugin } from './plugin'; + +describe('SavedObjectsManagementPlugin', () => { + let plugin: SavedObjectsManagementPlugin; + + beforeEach(() => { + plugin = new SavedObjectsManagementPlugin(); + }); + + describe('#setup', () => { + it('registers the saved_objects feature to the home plugin', async () => { + const coreSetup = coreMock.createSetup(); + const homeSetup = homePluginMock.createSetupContract(); + + await plugin.setup(coreSetup, { home: homeSetup }); + + expect(homeSetup.featureCatalogue.register).toHaveBeenCalledTimes(1); + expect(homeSetup.featureCatalogue.register).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'saved_objects', + }) + ); + }); + }); +}); diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts b/src/plugins/saved_objects_management/public/plugin.ts similarity index 52% rename from src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts rename to src/plugins/saved_objects_management/public/plugin.ts index be102b2a4dce7..3f2e9c166058e 100644 --- a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_service.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -18,24 +18,44 @@ */ import { i18n } from '@kbn/i18n'; +import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { HomePublicPluginSetup, FeatureCatalogueCategory } from '../../home/public'; import { - FeatureCatalogueCategory, - HomePublicPluginSetup, -} from '../../../../../../../plugins/home/public'; -import { SavedObjectsManagementActionRegistry } from './saved_objects_management_action_registry'; + SavedObjectsManagementActionRegistry, + ISavedObjectsManagementActionRegistry, +} from './services'; -interface SetupDependencies { +export interface SavedObjectsManagementPluginSetup { + actionRegistry: ISavedObjectsManagementActionRegistry; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SavedObjectsManagementPluginStart {} + +export interface SetupDependencies { home: HomePublicPluginSetup; } -export class SavedObjectsManagementService { - public setup({ home }: SetupDependencies) { +export class SavedObjectsManagementPlugin + implements + Plugin< + SavedObjectsManagementPluginSetup, + SavedObjectsManagementPluginStart, + SetupDependencies, + {} + > { + private actionRegistry = new SavedObjectsManagementActionRegistry(); + + public setup( + core: CoreSetup<{}>, + { home }: SetupDependencies + ): SavedObjectsManagementPluginSetup { home.featureCatalogue.register({ id: 'saved_objects', - title: i18n.translate('management.objects.savedObjectsTitle', { + title: i18n.translate('savedObjectsManagement.objects.savedObjectsTitle', { defaultMessage: 'Saved Objects', }), - description: i18n.translate('management.objects.savedObjectsDescription', { + description: i18n.translate('savedObjectsManagement.objects.savedObjectsDescription', { defaultMessage: 'Import, export, and manage your saved searches, visualizations, and dashboards.', }), @@ -46,12 +66,11 @@ export class SavedObjectsManagementService { }); return { - registry: SavedObjectsManagementActionRegistry, + actionRegistry: this.actionRegistry, }; } - public stop() {} + public start(core: CoreStart) { + return {}; + } } - -/** @internal */ -export type SavedObjectsManagementServiceSetup = ReturnType; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts b/src/plugins/saved_objects_management/public/services/action_registry.mock.ts similarity index 66% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts rename to src/plugins/saved_objects_management/public/services/action_registry.mock.ts index 216e523b07141..a9093ad42d0ac 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts +++ b/src/plugins/saved_objects_management/public/services/action_registry.mock.ts @@ -17,12 +17,21 @@ * under the License. */ -// eslint-disable-next-line -import { npSetup, npStart } from 'ui/new_platform'; -import { PluginInitializerContext } from '../../../../../../core/public'; -import { plugin } from '.'; +import { ISavedObjectsManagementActionRegistry } from './action_registry'; -const pluginInstance = plugin({} as PluginInitializerContext); +const createRegistryMock = (): jest.Mocked => { + const mock = { + register: jest.fn(), + has: jest.fn(), + getAll: jest.fn(), + }; -export const setup = pluginInstance.setup(npSetup.core, npSetup.plugins); -export const start = pluginInstance.start(npStart.core, npStart.plugins); + mock.has.mockReturnValue(true); + mock.getAll.mockReturnValue([]); + + return mock; +}; + +export const actionRegistryMock = { + create: createRegistryMock, +}; diff --git a/src/plugins/saved_objects_management/public/services/action_registry.test.ts b/src/plugins/saved_objects_management/public/services/action_registry.test.ts new file mode 100644 index 0000000000000..eb3bda00f4196 --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/action_registry.test.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectsManagementActionRegistry } from './action_registry'; +import { SavedObjectsManagementAction } from './action_types'; + +class DummyAction extends SavedObjectsManagementAction { + constructor(public id: string) { + super(); + } + + public euiAction = { + name: 'name', + description: 'description', + icon: 'icon', + type: 'type', + }; + + public render = () => ''; +} + +describe('SavedObjectsManagementActionRegistry', () => { + let registry: SavedObjectsManagementActionRegistry; + + const createAction = (id: string): SavedObjectsManagementAction => { + return new DummyAction(id); + }; + + beforeEach(() => { + registry = new SavedObjectsManagementActionRegistry(); + }); + + describe('#register', () => { + it('allows actions to be registered and retrieved', () => { + const action = createAction('foo'); + registry.register(action); + expect(registry.getAll()).toContain(action); + }); + + it('does not allow actions with duplicate ids to be registered', () => { + const action = createAction('my-action'); + registry.register(action); + expect(() => registry.register(action)).toThrowErrorMatchingInlineSnapshot( + `"Saved Objects Management Action with id 'my-action' already exists"` + ); + }); + }); + + describe('#has', () => { + it('returns true when an action with a matching ID exists', () => { + const action = createAction('existing-action'); + registry.register(action); + expect(registry.has('existing-action')).toEqual(true); + }); + + it(`returns false when an action doesn't exist`, () => { + expect(registry.has('missing-action')).toEqual(false); + }); + }); +}); diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.ts b/src/plugins/saved_objects_management/public/services/action_registry.ts similarity index 52% rename from src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.ts rename to src/plugins/saved_objects_management/public/services/action_registry.ts index f4085a674f496..8bf77231dd73f 100644 --- a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action_registry.ts +++ b/src/plugins/saved_objects_management/public/services/action_registry.ts @@ -16,22 +16,37 @@ * specific language governing permissions and limitations * under the License. */ -import { SavedObjectsManagementAction } from './saved_objects_management_action'; -const actions: Map = new Map(); +import { SavedObjectsManagementAction } from './action_types'; -export const SavedObjectsManagementActionRegistry = { - register: (action: SavedObjectsManagementAction) => { - if (!action.id) { - throw new TypeError('Saved Objects Management Actions must have an id'); - } - if (actions.has(action.id)) { +export type ISavedObjectsManagementActionRegistry = PublicMethodsOf< + SavedObjectsManagementActionRegistry +>; + +export class SavedObjectsManagementActionRegistry { + private readonly actions = new Map(); + + /** + * register given action in the registry. + */ + register(action: SavedObjectsManagementAction) { + if (this.actions.has(action.id)) { throw new Error(`Saved Objects Management Action with id '${action.id}' already exists`); } - actions.set(action.id, action); - }, + this.actions.set(action.id, action); + } - has: (actionId: string) => actions.has(actionId), + /** + * return true if the registry contains given action, false otherwise. + */ + has(actionId: string) { + return this.actions.has(actionId); + } - get: () => Array.from(actions.values()), -}; + /** + * return all {@link SavedObjectsManagementAction | actions} currently registered. + */ + getAll() { + return [...this.actions.values()]; + } +} diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts b/src/plugins/saved_objects_management/public/services/action_types.ts similarity index 92% rename from src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts rename to src/plugins/saved_objects_management/public/services/action_types.ts index d83afb195a492..92b0ea638b9bb 100644 --- a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/saved_objects_management_action.ts +++ b/src/plugins/saved_objects_management/public/services/action_types.ts @@ -18,12 +18,8 @@ */ import { ReactNode } from 'react'; +import { SavedObjectReference } from 'src/core/public'; -export interface SavedObjectsManagementRecordReference { - type: string; - id: string; - name: string; -} export interface SavedObjectsManagementRecord { type: string; id: string; @@ -31,7 +27,7 @@ export interface SavedObjectsManagementRecord { icon: string; title: string; }; - references: SavedObjectsManagementRecordReference[]; + references: SavedObjectReference[]; } export abstract class SavedObjectsManagementAction { diff --git a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts b/src/plugins/saved_objects_management/public/services/index.ts similarity index 79% rename from src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts rename to src/plugins/saved_objects_management/public/services/index.ts index bad3b3ac36ef7..d6353576b8e11 100644 --- a/src/legacy/core_plugins/management/public/np_ready/services/saved_objects_management/index.ts +++ b/src/plugins/saved_objects_management/public/services/index.ts @@ -17,6 +17,8 @@ * under the License. */ -export * from './saved_objects_management_action_registry'; -export * from './saved_objects_management_action'; -export * from './saved_objects_management_service'; +export { + SavedObjectsManagementActionRegistry, + ISavedObjectsManagementActionRegistry, +} from './action_registry'; +export { SavedObjectsManagementAction, SavedObjectsManagementRecord } from './action_types'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/is_same_query.js b/src/plugins/saved_objects_management/server/index.ts similarity index 68% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/is_same_query.js rename to src/plugins/saved_objects_management/server/index.ts index ce5de5ce45003..820118ebf3ec4 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/is_same_query.js +++ b/src/plugins/saved_objects_management/server/index.ts @@ -17,16 +17,15 @@ * under the License. */ -import { parseQuery } from '.'; +import { PluginInitializerContext } from 'src/core/server'; +import { SavedObjectsManagementPlugin } from './plugin'; -export const isSameQuery = (query1, query2) => { - const parsedQuery1 = parseQuery(query1); - const parsedQuery2 = parseQuery(query2); +export const plugin = (context: PluginInitializerContext) => + new SavedObjectsManagementPlugin(context); - if (parsedQuery1.queryText === parsedQuery2.queryText) { - if (parsedQuery1.visibleTypes === parsedQuery2.visibleTypes) { - return true; - } - } - return false; -}; +export { + SavedObjectsManagementPluginSetup, + SavedObjectsManagementPluginStart, + SavedObjectMetadata, + SavedObjectWithMetadata, +} from './types'; diff --git a/src/plugins/saved_objects_management/server/lib/find_all.test.ts b/src/plugins/saved_objects_management/server/lib/find_all.test.ts new file mode 100644 index 0000000000000..98e669c093178 --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/find_all.test.ts @@ -0,0 +1,95 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { times } from 'lodash'; +import { SavedObjectsFindOptions, SavedObject } from 'src/core/server'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; +import { findAll } from './find_all'; + +describe('findAll', () => { + let savedObjectsClient: ReturnType; + + const createObj = (id: number): SavedObject => ({ + type: 'type', + id: `id-${id}`, + attributes: {}, + references: [], + }); + + beforeEach(() => { + savedObjectsClient = savedObjectsClientMock.create(); + }); + + it('calls the saved object client with the correct parameters', async () => { + const query: SavedObjectsFindOptions = { + type: ['some-type', 'another-type'], + }; + + savedObjectsClient.find.mockResolvedValue({ + saved_objects: [createObj(1), createObj(2)], + total: 1, + per_page: 20, + page: 1, + }); + + const results = await findAll(savedObjectsClient, query); + + expect(savedObjectsClient.find).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.find).toHaveBeenCalledWith({ + ...query, + page: 1, + }); + + expect(results).toEqual([createObj(1), createObj(2)]); + }); + + it('recursively call find until all objects are fetched', async () => { + const query: SavedObjectsFindOptions = { + type: ['some-type', 'another-type'], + }; + const objPerPage = 2; + + savedObjectsClient.find.mockImplementation(({ page }) => { + const firstInPage = (page! - 1) * objPerPage + 1; + return Promise.resolve({ + saved_objects: [createObj(firstInPage), createObj(firstInPage + 1)], + total: objPerPage * 3, + per_page: objPerPage, + page: page!, + }); + }); + + const results = await findAll(savedObjectsClient, query); + expect(savedObjectsClient.find).toHaveBeenCalledTimes(3); + expect(savedObjectsClient.find).toHaveBeenCalledWith({ + ...query, + page: 1, + }); + expect(savedObjectsClient.find).toHaveBeenCalledWith({ + ...query, + page: 2, + }); + expect(savedObjectsClient.find).toHaveBeenCalledWith({ + ...query, + page: 3, + }); + + expect(results).toEqual(times(6, num => createObj(num + 1))); + }); +}); diff --git a/src/plugins/saved_objects_management/server/lib/find_all.ts b/src/plugins/saved_objects_management/server/lib/find_all.ts new file mode 100644 index 0000000000000..6bc3e46d026bf --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/find_all.ts @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectsClientContract, SavedObject, SavedObjectsFindOptions } from 'src/core/server'; + +export const findAll = async ( + client: SavedObjectsClientContract, + findOptions: SavedObjectsFindOptions +): Promise => { + return recursiveFind(client, findOptions, 1, []); +}; + +const recursiveFind = async ( + client: SavedObjectsClientContract, + findOptions: SavedObjectsFindOptions, + page: number, + allObjects: SavedObject[] +): Promise => { + const objects = await client.find({ + ...findOptions, + page, + }); + + allObjects.push(...objects.saved_objects); + if (allObjects.length < objects.total) { + return recursiveFind(client, findOptions, page + 1, allObjects); + } + + return allObjects; +}; diff --git a/src/plugins/saved_objects_management/server/lib/find_relationships.test.ts b/src/plugins/saved_objects_management/server/lib/find_relationships.test.ts new file mode 100644 index 0000000000000..18846eeebdfb7 --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/find_relationships.test.ts @@ -0,0 +1,213 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { findRelationships } from './find_relationships'; +import { managementMock } from '../services/management.mock'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; + +describe('findRelationships', () => { + let savedObjectsClient: ReturnType; + let managementService: ReturnType; + + beforeEach(() => { + savedObjectsClient = savedObjectsClientMock.create(); + managementService = managementMock.create(); + }); + + it('returns the child and parent references of the object', async () => { + const type = 'dashboard'; + const id = 'some-id'; + const references = [ + { + type: 'some-type', + id: 'ref-1', + name: 'ref 1', + }, + { + type: 'another-type', + id: 'ref-2', + name: 'ref 2', + }, + ]; + const referenceTypes = ['some-type', 'another-type']; + + savedObjectsClient.get.mockResolvedValue({ + id, + type, + attributes: {}, + references, + }); + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + type: 'some-type', + id: 'ref-1', + attributes: {}, + references: [], + }, + { + type: 'another-type', + id: 'ref-2', + attributes: {}, + references: [], + }, + ], + }); + + savedObjectsClient.find.mockResolvedValue({ + saved_objects: [ + { + type: 'parent-type', + id: 'parent-id', + attributes: {}, + references: [], + }, + ], + total: 1, + per_page: 20, + page: 1, + }); + + const relationships = await findRelationships({ + type, + id, + size: 20, + client: savedObjectsClient, + referenceTypes, + savedObjectsManagement: managementService, + }); + + expect(savedObjectsClient.get).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.get).toHaveBeenCalledWith(type, id); + + expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith( + references.map(ref => ({ + id: ref.id, + type: ref.type, + })) + ); + + expect(savedObjectsClient.find).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.find).toHaveBeenCalledWith({ + hasReference: { type, id }, + perPage: 20, + type: referenceTypes, + }); + + expect(relationships).toEqual([ + { + id: 'ref-1', + relationship: 'child', + type: 'some-type', + meta: expect.any(Object), + }, + { + id: 'ref-2', + relationship: 'child', + type: 'another-type', + meta: expect.any(Object), + }, + { + id: 'parent-id', + relationship: 'parent', + type: 'parent-type', + meta: expect.any(Object), + }, + ]); + }); + + it('uses the management service to consolidate the relationship objects', async () => { + const type = 'dashboard'; + const id = 'some-id'; + const references = [ + { + type: 'some-type', + id: 'ref-1', + name: 'ref 1', + }, + ]; + const referenceTypes = ['some-type', 'another-type']; + + managementService.getIcon.mockReturnValue('icon'); + managementService.getTitle.mockReturnValue('title'); + managementService.getEditUrl.mockReturnValue('editUrl'); + managementService.getInAppUrl.mockReturnValue({ + path: 'path', + uiCapabilitiesPath: 'uiCapabilitiesPath', + }); + + savedObjectsClient.get.mockResolvedValue({ + id, + type, + attributes: {}, + references, + }); + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + type: 'some-type', + id: 'ref-1', + attributes: {}, + references: [], + }, + ], + }); + + savedObjectsClient.find.mockResolvedValue({ + saved_objects: [], + total: 0, + per_page: 20, + page: 1, + }); + + const relationships = await findRelationships({ + type, + id, + size: 20, + client: savedObjectsClient, + referenceTypes, + savedObjectsManagement: managementService, + }); + + expect(managementService.getIcon).toHaveBeenCalledTimes(1); + expect(managementService.getTitle).toHaveBeenCalledTimes(1); + expect(managementService.getEditUrl).toHaveBeenCalledTimes(1); + expect(managementService.getInAppUrl).toHaveBeenCalledTimes(1); + + expect(relationships).toEqual([ + { + id: 'ref-1', + relationship: 'child', + type: 'some-type', + meta: { + title: 'title', + icon: 'icon', + editUrl: 'editUrl', + inAppUrl: { + path: 'path', + uiCapabilitiesPath: 'uiCapabilitiesPath', + }, + }, + }, + ]); + }); +}); diff --git a/src/plugins/saved_objects_management/server/lib/find_relationships.ts b/src/plugins/saved_objects_management/server/lib/find_relationships.ts new file mode 100644 index 0000000000000..cca8831afd16c --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/find_relationships.ts @@ -0,0 +1,88 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectsClientContract } from 'src/core/server'; +import { injectMetaAttributes } from './inject_meta_attributes'; +import { ISavedObjectsManagement } from '../services'; +import { SavedObjectRelation, SavedObjectWithMetadata } from '../types'; + +export async function findRelationships({ + type, + id, + size, + client, + referenceTypes, + savedObjectsManagement, +}: { + type: string; + id: string; + size: number; + client: SavedObjectsClientContract; + referenceTypes: string[]; + savedObjectsManagement: ISavedObjectsManagement; +}): Promise { + const { references = [] } = await client.get(type, id); + + // Use a map to avoid duplicates, it does happen but have a different "name" in the reference + const referencedToBulkGetOpts = new Map( + references.map(ref => [`${ref.type}:${ref.id}`, { id: ref.id, type: ref.type }]) + ); + + const [childReferencesResponse, parentReferencesResponse] = await Promise.all([ + referencedToBulkGetOpts.size > 0 + ? client.bulkGet([...referencedToBulkGetOpts.values()]) + : Promise.resolve({ saved_objects: [] }), + client.find({ + hasReference: { type, id }, + perPage: size, + type: referenceTypes, + }), + ]); + + return childReferencesResponse.saved_objects + .map(obj => injectMetaAttributes(obj, savedObjectsManagement)) + .map(extractCommonProperties) + .map( + obj => + ({ + ...obj, + relationship: 'child', + } as SavedObjectRelation) + ) + .concat( + parentReferencesResponse.saved_objects + .map(obj => injectMetaAttributes(obj, savedObjectsManagement)) + .map(extractCommonProperties) + .map( + obj => + ({ + ...obj, + relationship: 'parent', + } as SavedObjectRelation) + ) + ); +} + +function extractCommonProperties(savedObject: SavedObjectWithMetadata) { + return { + id: savedObject.id, + type: savedObject.type, + meta: savedObject.meta, + }; +} diff --git a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/public/app.js b/src/plugins/saved_objects_management/server/lib/index.ts similarity index 83% rename from test/plugin_functional/plugins/kbn_tp_sample_app_plugin/public/app.js rename to src/plugins/saved_objects_management/server/lib/index.ts index a7a516bb0cdbd..dea6813d690ec 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/public/app.js +++ b/src/plugins/saved_objects_management/server/lib/index.ts @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import 'ui/autoload/all'; -import chrome from 'ui/chrome'; - -chrome.setRootTemplate('
Super simple app plugin
'); +export { injectMetaAttributes } from './inject_meta_attributes'; +export { findAll } from './find_all'; +export { findRelationships } from './find_relationships'; diff --git a/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.test.ts b/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.test.ts new file mode 100644 index 0000000000000..0c0f9d8feb506 --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.test.ts @@ -0,0 +1,82 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObject } from 'src/core/server'; +import { injectMetaAttributes } from './inject_meta_attributes'; +import { managementMock } from '../services/management.mock'; + +describe('injectMetaAttributes', () => { + let managementService: ReturnType; + + beforeEach(() => { + managementService = managementMock.create(); + + managementService.getIcon.mockReturnValue('icon'); + managementService.getTitle.mockReturnValue('title'); + managementService.getEditUrl.mockReturnValue('editUrl'); + managementService.getInAppUrl.mockReturnValue({ + path: 'path', + uiCapabilitiesPath: 'uiCapabilitiesPath', + }); + }); + + it('inject the metadata to the obj', () => { + const obj: SavedObject = { + id: 'id', + type: 'config', + attributes: { some: 'value' }, + references: [], + }; + + const objWithMeta = injectMetaAttributes(obj, managementService); + expect(objWithMeta).toStrictEqual({ + id: 'id', + type: 'config', + attributes: { some: 'value' }, + references: [], + meta: { + icon: 'icon', + title: 'title', + editUrl: 'editUrl', + inAppUrl: { + path: 'path', + uiCapabilitiesPath: 'uiCapabilitiesPath', + }, + }, + }); + }); + + it('does not alter the original object', () => { + const obj: SavedObject = { + id: 'id', + type: 'config', + attributes: { some: 'value' }, + references: [], + }; + + injectMetaAttributes(obj, managementService); + + expect(obj).toStrictEqual({ + id: 'id', + type: 'config', + attributes: { some: 'value' }, + references: [], + }); + }); +}); diff --git a/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.ts b/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.ts new file mode 100644 index 0000000000000..615caffd3b60b --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/inject_meta_attributes.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObject } from 'src/core/server'; +import { ISavedObjectsManagement } from '../services'; +import { SavedObjectWithMetadata } from '../types'; + +export function injectMetaAttributes( + savedObject: SavedObject | SavedObjectWithMetadata, + savedObjectsManagement: ISavedObjectsManagement +): SavedObjectWithMetadata { + const result = { + ...savedObject, + meta: (savedObject as SavedObjectWithMetadata).meta || {}, + }; + + // Add extra meta information + result.meta.icon = savedObjectsManagement.getIcon(savedObject.type); + result.meta.title = savedObjectsManagement.getTitle(savedObject); + result.meta.editUrl = savedObjectsManagement.getEditUrl(savedObject); + result.meta.inAppUrl = savedObjectsManagement.getInAppUrl(savedObject); + + return result; +} diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy_imports.ts b/src/plugins/saved_objects_management/server/plugin.test.mocks.ts similarity index 86% rename from src/legacy/core_plugins/vis_type_tagcloud/public/legacy_imports.ts rename to src/plugins/saved_objects_management/server/plugin.test.mocks.ts index cd7a8e740d85d..95dba4563a528 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy_imports.ts +++ b/src/plugins/saved_objects_management/server/plugin.test.mocks.ts @@ -17,4 +17,8 @@ * under the License. */ -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +export const registerRoutesMock = jest.fn(); + +jest.doMock('./routes', () => ({ + registerRoutes: registerRoutesMock, +})); diff --git a/test/plugin_functional/test_suites/app_plugins/app_navigation.js b/src/plugins/saved_objects_management/server/plugin.test.ts similarity index 52% rename from test/plugin_functional/test_suites/app_plugins/app_navigation.js rename to src/plugins/saved_objects_management/server/plugin.test.ts index bb39e52287556..6c2c12c10efca 100644 --- a/test/plugin_functional/test_suites/app_plugins/app_navigation.js +++ b/src/plugins/saved_objects_management/server/plugin.test.ts @@ -17,22 +17,29 @@ * under the License. */ -import expect from '@kbn/expect'; +import { registerRoutesMock } from './plugin.test.mocks'; +import { SavedObjectsManagementPlugin } from './plugin'; +import { coreMock } from '../../../core/server/mocks'; -export default function({ getService, getPageObjects }) { - const appsMenu = getService('appsMenu'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header', 'home']); +describe('SavedObjectsManagementPlugin', () => { + let plugin: SavedObjectsManagementPlugin; - describe('app navigation', function describeIndexTests() { - before(async () => { - await PageObjects.common.navigateToApp('settings'); - }); + beforeEach(() => { + plugin = new SavedObjectsManagementPlugin(coreMock.createPluginInitializerContext()); + }); + + describe('#setup', () => { + it('registers the routes', async () => { + const coreSetup = coreMock.createSetup(); + + await plugin.setup(coreSetup); - it('should show nav link that navigates to the app', async () => { - await appsMenu.clickLink('Test Plugin App'); - const pluginContent = await testSubjects.find('pluginContent'); - expect(await pluginContent.getVisibleText()).to.be('Super simple app plugin'); + expect(registerRoutesMock).toHaveBeenCalledTimes(1); + expect(registerRoutesMock).toHaveBeenCalledWith( + expect.objectContaining({ + http: coreSetup.http, + }) + ); }); }); -} +}); diff --git a/src/plugins/saved_objects_management/server/plugin.ts b/src/plugins/saved_objects_management/server/plugin.ts new file mode 100644 index 0000000000000..b72644b500967 --- /dev/null +++ b/src/plugins/saved_objects_management/server/plugin.ts @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subject } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { CoreSetup, CoreStart, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './types'; +import { SavedObjectsManagement } from './services'; +import { registerRoutes } from './routes'; + +export class SavedObjectsManagementPlugin + implements Plugin { + private readonly logger: Logger; + private managementService$ = new Subject(); + + constructor(private readonly context: PluginInitializerContext) { + this.logger = this.context.logger.get(); + } + + public async setup({ http }: CoreSetup) { + this.logger.debug('Setting up SavedObjectsManagement plugin'); + registerRoutes({ + http, + managementServicePromise: this.managementService$.pipe(first()).toPromise(), + }); + + return {}; + } + + public async start(core: CoreStart) { + this.logger.debug('Starting up SavedObjectsManagement plugin'); + const managementService = new SavedObjectsManagement(core.savedObjects.getTypeRegistry()); + this.managementService$.next(managementService); + + return {}; + } +} diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts new file mode 100644 index 0000000000000..a74c92ba6161f --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -0,0 +1,97 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; +import { injectMetaAttributes } from '../lib'; +import { ISavedObjectsManagement } from '../services'; + +export const registerFindRoute = ( + router: IRouter, + managementServicePromise: Promise +) => { + router.get( + { + path: '/api/kibana/management/saved_objects/_find', + validate: { + query: schema.object({ + perPage: schema.number({ min: 0, defaultValue: 20 }), + page: schema.number({ min: 0, defaultValue: 1 }), + type: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]), + search: schema.maybe(schema.string()), + defaultSearchOperator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { + defaultValue: 'OR', + }), + sortField: schema.maybe(schema.string()), + hasReference: schema.maybe( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ), + fields: schema.oneOf([schema.string(), schema.arrayOf(schema.string())], { + defaultValue: [], + }), + }), + }, + }, + router.handleLegacyErrors(async (context, req, res) => { + const managementService = await managementServicePromise; + const { client } = context.core.savedObjects; + const searchTypes = Array.isArray(req.query.type) ? req.query.type : [req.query.type]; + const includedFields = Array.isArray(req.query.fields) + ? req.query.fields + : [req.query.fields]; + const importAndExportableTypes = searchTypes.filter(type => + managementService.isImportAndExportable(type) + ); + + const searchFields = new Set(); + importAndExportableTypes.forEach(type => { + const searchField = managementService.getDefaultSearchField(type); + if (searchField) { + searchFields.add(searchField); + } + }); + + const findResponse = await client.find({ + ...req.query, + fields: undefined, + searchFields: [...searchFields], + }); + + const enhancedSavedObjects = findResponse.saved_objects + .map(so => injectMetaAttributes(so, managementService)) + .map(obj => { + const result = { ...obj, attributes: {} as Record }; + for (const field of includedFields) { + result.attributes[field] = obj.attributes[field]; + } + return result; + }); + + return res.ok({ + body: { + ...findResponse, + saved_objects: enhancedSavedObjects, + }, + }); + }) + ); +}; diff --git a/src/plugins/saved_objects_management/server/routes/index.test.ts b/src/plugins/saved_objects_management/server/routes/index.test.ts new file mode 100644 index 0000000000000..f183972953dce --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/index.test.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { registerRoutes } from './index'; +import { ISavedObjectsManagement } from '../services'; +import { coreMock, httpServiceMock } from '../../../../core/server/mocks'; + +describe('registerRoutes', () => { + it('registers the management routes', () => { + const router = httpServiceMock.createRouter(); + const httpSetup = coreMock.createSetup().http; + httpSetup.createRouter.mockReturnValue(router); + const managementPromise = Promise.resolve({} as ISavedObjectsManagement); + + registerRoutes({ + http: httpSetup, + managementServicePromise: managementPromise, + }); + + expect(httpSetup.createRouter).toHaveBeenCalledTimes(1); + expect(router.get).toHaveBeenCalledTimes(2); + expect(router.post).toHaveBeenCalledTimes(2); + + expect(router.get).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/api/kibana/management/saved_objects/_find', + }), + expect.any(Function) + ); + expect(router.get).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/api/kibana/management/saved_objects/relationships/{type}/{id}', + }), + expect.any(Function) + ); + expect(router.post).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/api/kibana/management/saved_objects/scroll/counts', + }), + expect.any(Function) + ); + expect(router.post).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/api/kibana/management/saved_objects/scroll/export', + }), + expect.any(Function) + ); + }); +}); diff --git a/src/plugins/saved_objects_management/server/routes/index.ts b/src/plugins/saved_objects_management/server/routes/index.ts new file mode 100644 index 0000000000000..2c6adb71ed3ce --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/index.ts @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { HttpServiceSetup } from 'src/core/server'; +import { ISavedObjectsManagement } from '../services'; +import { registerFindRoute } from './find'; +import { registerScrollForCountRoute } from './scroll_count'; +import { registerScrollForExportRoute } from './scroll_export'; +import { registerRelationshipsRoute } from './relationships'; + +interface RegisterRouteOptions { + http: HttpServiceSetup; + managementServicePromise: Promise; +} + +export function registerRoutes({ http, managementServicePromise }: RegisterRouteOptions) { + const router = http.createRouter(); + registerFindRoute(router, managementServicePromise); + registerScrollForCountRoute(router); + registerScrollForExportRoute(router); + registerRelationshipsRoute(router, managementServicePromise); +} diff --git a/src/plugins/saved_objects_management/server/routes/relationships.ts b/src/plugins/saved_objects_management/server/routes/relationships.ts new file mode 100644 index 0000000000000..c9001deb91237 --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/relationships.ts @@ -0,0 +1,66 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; +import { findRelationships } from '../lib'; +import { ISavedObjectsManagement } from '../services'; + +export const registerRelationshipsRoute = ( + router: IRouter, + managementServicePromise: Promise +) => { + router.get( + { + path: '/api/kibana/management/saved_objects/relationships/{type}/{id}', + validate: { + params: schema.object({ + type: schema.string(), + id: schema.string(), + }), + query: schema.object({ + size: schema.number({ defaultValue: 10000 }), + savedObjectTypes: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]), + }), + }, + }, + router.handleLegacyErrors(async (context, req, res) => { + const managementService = await managementServicePromise; + const { client } = context.core.savedObjects; + const { type, id } = req.params; + const { size } = req.query; + const savedObjectTypes = Array.isArray(req.query.savedObjectTypes) + ? req.query.savedObjectTypes + : [req.query.savedObjectTypes]; + + const relations = await findRelationships({ + type, + id, + client, + size, + referenceTypes: savedObjectTypes, + savedObjectsManagement: managementService, + }); + + return res.ok({ + body: relations, + }); + }) + ); +}; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts new file mode 100644 index 0000000000000..58ba90d847791 --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import { IRouter, SavedObjectsFindOptions } from 'src/core/server'; +import { findAll } from '../lib'; + +export const registerScrollForCountRoute = (router: IRouter) => { + router.post( + { + path: '/api/kibana/management/saved_objects/scroll/counts', + validate: { + body: schema.object({ + typesToInclude: schema.arrayOf(schema.string()), + searchString: schema.maybe(schema.string()), + }), + }, + }, + router.handleLegacyErrors(async (context, req, res) => { + const { client } = context.core.savedObjects; + + const findOptions: SavedObjectsFindOptions = { + type: req.body.typesToInclude, + perPage: 1000, + }; + if (req.body.searchString) { + findOptions.search = `${req.body.searchString}*`; + findOptions.searchFields = ['title']; + } + + const objects = await findAll(client, findOptions); + + const counts = objects.reduce((accum, result) => { + const type = result.type; + accum[type] = accum[type] || 0; + accum[type]++; + return accum; + }, {} as Record); + + for (const type of req.body.typesToInclude) { + if (!counts[type]) { + counts[type] = 0; + } + } + + return res.ok({ + body: counts, + }); + }) + ); +}; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_export.ts b/src/plugins/saved_objects_management/server/routes/scroll_export.ts new file mode 100644 index 0000000000000..cda2770234911 --- /dev/null +++ b/src/plugins/saved_objects_management/server/routes/scroll_export.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; +import { findAll } from '../lib'; + +export const registerScrollForExportRoute = (router: IRouter) => { + router.post( + { + path: '/api/kibana/management/saved_objects/scroll/export', + validate: { + body: schema.object({ + typesToInclude: schema.arrayOf(schema.string()), + }), + }, + }, + router.handleLegacyErrors(async (context, req, res) => { + const { client } = context.core.savedObjects; + const objects = await findAll(client, { + perPage: 1000, + type: req.body.typesToInclude, + }); + + return res.ok({ + body: objects.map(hit => { + return { + _id: hit.id, + _source: hit.attributes, + _meta: { + savedObjectVersion: 2, + }, + _migrationVersion: hit.migrationVersion, + _references: hit.references || [], + }; + }), + }); + }) + ); +}; diff --git a/src/core/server/saved_objects/management/index.ts b/src/plugins/saved_objects_management/server/services/index.ts similarity index 90% rename from src/core/server/saved_objects/management/index.ts rename to src/plugins/saved_objects_management/server/services/index.ts index a256a1333c5cc..fddd53c73634e 100644 --- a/src/core/server/saved_objects/management/index.ts +++ b/src/plugins/saved_objects_management/server/services/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { SavedObjectsManagement } from './management'; +export { SavedObjectsManagement, ISavedObjectsManagement } from './management'; diff --git a/src/core/server/saved_objects/management/management.mock.ts b/src/plugins/saved_objects_management/server/services/management.mock.ts similarity index 96% rename from src/core/server/saved_objects/management/management.mock.ts rename to src/plugins/saved_objects_management/server/services/management.mock.ts index e7242c30d3961..2099cc0f77bcc 100644 --- a/src/core/server/saved_objects/management/management.mock.ts +++ b/src/plugins/saved_objects_management/server/services/management.mock.ts @@ -24,7 +24,6 @@ const createManagementMock = () => { const mocked: jest.Mocked = { isImportAndExportable: jest.fn().mockReturnValue(true), getDefaultSearchField: jest.fn(), - getImportableAndExportableTypes: jest.fn(), getIcon: jest.fn(), getTitle: jest.fn(), getEditUrl: jest.fn(), diff --git a/src/core/server/saved_objects/management/management.test.ts b/src/plugins/saved_objects_management/server/services/management.test.ts similarity index 97% rename from src/core/server/saved_objects/management/management.test.ts rename to src/plugins/saved_objects_management/server/services/management.test.ts index dc110dec020f0..6b95048749fae 100644 --- a/src/core/server/saved_objects/management/management.test.ts +++ b/src/plugins/saved_objects_management/server/services/management.test.ts @@ -18,8 +18,7 @@ */ import { SavedObjectsManagement } from './management'; -import { SavedObjectsType } from '../types'; -import { SavedObjectTypeRegistry } from '../saved_objects_type_registry'; +import { SavedObjectsType, SavedObjectTypeRegistry } from '../../../../core/server'; describe('SavedObjectsManagement', () => { let registry: SavedObjectTypeRegistry; diff --git a/src/core/server/saved_objects/management/management.ts b/src/plugins/saved_objects_management/server/services/management.ts similarity index 86% rename from src/core/server/saved_objects/management/management.ts rename to src/plugins/saved_objects_management/server/services/management.ts index db759c4aec752..7aee974182497 100644 --- a/src/core/server/saved_objects/management/management.ts +++ b/src/plugins/saved_objects_management/server/services/management.ts @@ -17,19 +17,13 @@ * under the License. */ -import { SavedObject } from '../types'; -import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; +import { ISavedObjectTypeRegistry, SavedObject } from 'src/core/server'; + +export type ISavedObjectsManagement = PublicMethodsOf; export class SavedObjectsManagement { constructor(private readonly registry: ISavedObjectTypeRegistry) {} - public getImportableAndExportableTypes() { - return this.registry - .getAllTypes() - .map(type => type.name) - .filter(type => this.isImportAndExportable(type)); - } - public isImportAndExportable(type: string) { return this.registry.isImportableAndExportable(type); } diff --git a/src/plugins/saved_objects_management/server/types.ts b/src/plugins/saved_objects_management/server/types.ts new file mode 100644 index 0000000000000..5c4763d357e87 --- /dev/null +++ b/src/plugins/saved_objects_management/server/types.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObject } from 'src/core/server'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SavedObjectsManagementPluginSetup {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SavedObjectsManagementPluginStart {} + +/** + * The metadata injected into a {@link SavedObject | saved object} when returning + * {@link SavedObjectWithMetadata | enhanced objects} from the plugin API endpoints. + */ +export interface SavedObjectMetadata { + icon?: string; + title?: string; + editUrl?: string; + inAppUrl?: { path: string; uiCapabilitiesPath: string }; +} + +/** + * A {@link SavedObject | saved object} enhanced with meta properties used by the client-side plugin. + */ +export type SavedObjectWithMetadata = SavedObject & { + meta: SavedObjectMetadata; +}; + +/** + * Represents a relation between two {@link SavedObject | saved object} + */ +export interface SavedObjectRelation { + id: string; + type: string; + relationship: 'child' | 'parent'; + meta: SavedObjectMetadata; +} diff --git a/src/plugins/telemetry/common/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts b/src/plugins/telemetry/common/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts index d7dcfd606b6ac..030edf7e1c112 100644 --- a/src/plugins/telemetry/common/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts +++ b/src/plugins/telemetry/common/telemetry_config/get_telemetry_allow_changing_opt_in_status.ts @@ -32,9 +32,9 @@ export function getTelemetryAllowChangingOptInStatus({ return configTelemetryAllowChangingOptInStatus; } - if (typeof telemetrySavedObject.telemetryAllowChangingOptInStatus === 'undefined') { + if (typeof telemetrySavedObject.allowChangingOptInStatus === 'undefined') { return configTelemetryAllowChangingOptInStatus; } - return telemetrySavedObject.telemetryAllowChangingOptInStatus; + return telemetrySavedObject.allowChangingOptInStatus; } diff --git a/src/plugins/telemetry/common/telemetry_config/types.ts b/src/plugins/telemetry/common/telemetry_config/types.ts index 7ab37e9544164..4deb1ab9a12f2 100644 --- a/src/plugins/telemetry/common/telemetry_config/types.ts +++ b/src/plugins/telemetry/common/telemetry_config/types.ts @@ -22,7 +22,7 @@ export interface TelemetrySavedObjectAttributes { lastVersionChecked?: string; sendUsageFrom?: 'browser' | 'server'; lastReported?: number; - telemetryAllowChangingOptInStatus?: boolean; + allowChangingOptInStatus?: boolean; userHasSeenNotice?: boolean; reportFailureCount?: number; reportFailureVersion?: string; diff --git a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts index f44603f4f19f4..9dc19f34f7ebe 100644 --- a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts +++ b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.test.ts @@ -119,7 +119,7 @@ describe('telemetry_usage_collector', () => { const usageCollector = mockUsageCollector() as any; const collectorOptions = createTelemetryUsageCollector( usageCollector, - () => tempFiles.unreadable + async () => tempFiles.unreadable ); expect(collectorOptions.type).toBe('static_telemetry'); diff --git a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts index 3daae90106e9e..bde7cfa5c4445 100644 --- a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts +++ b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts @@ -20,11 +20,12 @@ import { accessSync, constants, readFileSync, statSync } from 'fs'; import { safeLoad } from 'js-yaml'; import { dirname, join } from 'path'; +import { Observable } from 'rxjs'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getConfigPath } from '../../../../../core/server/path'; +import { take } from 'rxjs/operators'; +import { TelemetryConfigType } from '../../config'; // look for telemetry.yml in the same places we expect kibana.yml import { ensureDeepObject } from './ensure_deep_object'; @@ -80,20 +81,26 @@ export async function readTelemetryFile(path: string): Promise Promise ) { return usageCollection.makeUsageCollector({ type: 'static_telemetry', isReady: () => true, fetch: async () => { - const configPath = getConfigPathFn(); + const configPath = await getConfigPathFn(); const telemetryPath = join(dirname(configPath), 'telemetry.yml'); return await readTelemetryFile(telemetryPath); }, }); } -export function registerTelemetryUsageCollector(usageCollection: UsageCollectionSetup) { - const collector = createTelemetryUsageCollector(usageCollection); +export function registerTelemetryUsageCollector( + usageCollection: UsageCollectionSetup, + config$: Observable +) { + const collector = createTelemetryUsageCollector(usageCollection, async () => { + const config = await config$.pipe(take(1)).toPromise(); + return config.config; + }); usageCollection.registerCollector(collector); } diff --git a/src/plugins/telemetry/server/config.ts b/src/plugins/telemetry/server/config.ts index 7c62a37df7170..9621a8b5619b2 100644 --- a/src/plugins/telemetry/server/config.ts +++ b/src/plugins/telemetry/server/config.ts @@ -18,6 +18,8 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getConfigPath } from '../../../core/server/path'; import { ENDPOINT_VERSION } from '../common/constants'; export const configSchema = schema.object({ @@ -31,7 +33,7 @@ export const configSchema = schema.object({ { defaultValue: true } ), // `config` is used internally and not intended to be set - // config: Joi.string().default(getConfigPath()), TODO: Get it in some other way + config: schema.string({ defaultValue: getConfigPath() }), banner: schema.boolean({ defaultValue: true }), url: schema.conditional( schema.contextRef('dev'), diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index af512d234a7dc..77036b4ea7ddc 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -143,6 +143,9 @@ export class TelemetryPlugin implements Plugin { reportFailureVersion: { type: 'keyword', }, + allowChangingOptInStatus: { + type: 'boolean', + }, }, }, }); @@ -160,7 +163,7 @@ export class TelemetryPlugin implements Plugin { config$: this.config$, getSavedObjectsClient, }); - registerTelemetryUsageCollector(usageCollection); + registerTelemetryUsageCollector(usageCollection, this.config$); registerManagementUsageCollector(usageCollection, getUiSettingsClient); registerUiMetricUsageCollector(usageCollection, registerType, getSavedObjectsClient); registerApplicationUsageCollector(usageCollection, registerType, getSavedObjectsClient); diff --git a/src/plugins/timelion/config.ts b/src/plugins/timelion/config.ts index eaea1aaca1b7b..97a423331b921 100644 --- a/src/plugins/timelion/config.ts +++ b/src/plugins/timelion/config.ts @@ -21,6 +21,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object( { + enabled: schema.boolean({ defaultValue: true }), ui: schema.object({ enabled: schema.boolean({ defaultValue: false }) }), graphiteUrls: schema.maybe(schema.arrayOf(schema.string())), }, diff --git a/src/plugins/ui_actions/public/actions/action.ts b/src/plugins/ui_actions/public/actions/action.ts index 15f1d6dd79289..2b2fc004a84c6 100644 --- a/src/plugins/ui_actions/public/actions/action.ts +++ b/src/plugins/ui_actions/public/actions/action.ts @@ -19,12 +19,10 @@ import { UiComponent } from 'src/plugins/kibana_utils/common'; import { ActionType, ActionContextMapping } from '../types'; -import { Presentable } from '../util/presentable'; export type ActionByType = Action; -export interface Action - extends Partial> { +export interface Action { /** * Determined the order when there is more than one action matched to a trigger. * Higher numbers are displayed first. @@ -65,30 +63,12 @@ export interface Action isCompatible(context: Context): Promise; /** - * Executes the action. + * If this returns something truthy, this is used in addition to the `execute` method when clicked. */ - execute(context: Context): Promise; -} - -/** - * A convenience interface used to register an action. - */ -export interface ActionDefinition - extends Partial> { - /** - * ID of the action that uniquely identifies this action in the actions registry. - */ - readonly id: string; - - /** - * ID of the factory for this action. Used to construct dynamic actions. - */ - readonly type?: ActionType; + getHref?(context: Context): string | undefined; /** * Executes the action. */ execute(context: Context): Promise; } - -export type ActionContext = A extends ActionDefinition ? Context : never; diff --git a/src/plugins/ui_actions/public/util/presentable.ts b/src/plugins/ui_actions/public/actions/action_definition.ts similarity index 50% rename from src/plugins/ui_actions/public/util/presentable.ts rename to src/plugins/ui_actions/public/actions/action_definition.ts index 945fd2065ce78..c590cf8f34ee0 100644 --- a/src/plugins/ui_actions/public/util/presentable.ts +++ b/src/plugins/ui_actions/public/actions/action_definition.ts @@ -18,46 +18,55 @@ */ import { UiComponent } from 'src/plugins/kibana_utils/common'; +import { ActionType, ActionContextMapping } from '../types'; -/** - * Represents something that can be displayed to user in UI. - */ -export interface Presentable { +export interface ActionDefinition { /** - * ID that uniquely identifies this object. + * Determined the order when there is more than one action matched to a trigger. + * Higher numbers are displayed first. */ - readonly id: string; + order?: number; /** - * Determines the display order in relation to other items. Higher numbers are - * displayed first. + * A unique identifier for this action instance. */ - readonly order: number; + id?: string; /** - * `UiComponent` to render when displaying this entity as a context menu item. - * If not provided, `getDisplayName` will be used instead. + * The action type is what determines the context shape. */ - readonly MenuItem?: UiComponent<{ context: Context }>; + readonly type: T; /** * Optional EUI icon type that can be displayed along with the title. */ - getIconType(context: Context): string | undefined; + getIconType?(context: ActionContextMapping[T]): string; /** * Returns a title to be displayed to the user. + * @param context + */ + getDisplayName?(context: ActionContextMapping[T]): string; + + /** + * `UiComponent` to render when displaying this action as a context menu item. + * If not provided, `getDisplayName` will be used instead. + */ + MenuItem?: UiComponent<{ context: ActionContextMapping[T] }>; + + /** + * Returns a promise that resolves to true if this action is compatible given the context, + * otherwise resolves to false. */ - getDisplayName(context: Context): string; + isCompatible?(context: ActionContextMapping[T]): Promise; /** - * This method should return a link if this item can be clicked on. + * If this returns something truthy, this is used in addition to the `execute` method when clicked. */ - getHref?(context: Context): string | undefined; + getHref?(context: ActionContextMapping[T]): string | undefined; /** - * Returns a promise that resolves to true if this item is compatible given - * the context and should be displayed to user, otherwise resolves to false. + * Executes the action. */ - isCompatible(context: Context): Promise; + execute(context: ActionContextMapping[T]): Promise; } diff --git a/src/plugins/ui_actions/public/actions/action_factory.ts b/src/plugins/ui_actions/public/actions/action_factory.ts deleted file mode 100644 index bc0ec844d00f5..0000000000000 --- a/src/plugins/ui_actions/public/actions/action_factory.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiToReactComponent } from '../../../kibana_react/public'; -import { Presentable } from '../util/presentable'; -import { ActionDefinition } from './action'; -import { ActionFactoryDefinition } from './action_factory_definition'; -import { Configurable } from '../util'; -import { SerializedAction } from './types'; - -export class ActionFactory< - Config extends object = object, - FactoryContext extends object = object, - ActionContext extends object = object -> implements Presentable, Configurable { - constructor( - protected readonly def: ActionFactoryDefinition - ) {} - - public readonly id = this.def.id; - public readonly order = this.def.order || 0; - public readonly MenuItem? = this.def.MenuItem; - public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined; - - public readonly CollectConfig = this.def.CollectConfig; - public readonly ReactCollectConfig = uiToReactComponent(this.CollectConfig); - public readonly createConfig = this.def.createConfig; - public readonly isConfigValid = this.def.isConfigValid; - - public getIconType(context: FactoryContext): string | undefined { - if (!this.def.getIconType) return undefined; - return this.def.getIconType(context); - } - - public getDisplayName(context: FactoryContext): string { - if (!this.def.getDisplayName) return ''; - return this.def.getDisplayName(context); - } - - public async isCompatible(context: FactoryContext): Promise { - if (!this.def.isCompatible) return true; - return await this.def.isCompatible(context); - } - - public getHref(context: FactoryContext): string | undefined { - if (!this.def.getHref) return undefined; - return this.def.getHref(context); - } - - public create( - serializedAction: Omit, 'factoryId'> - ): ActionDefinition { - return this.def.create(serializedAction); - } -} diff --git a/src/plugins/ui_actions/public/actions/action_factory_definition.ts b/src/plugins/ui_actions/public/actions/action_factory_definition.ts deleted file mode 100644 index 7ac94a41e7076..0000000000000 --- a/src/plugins/ui_actions/public/actions/action_factory_definition.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ActionDefinition } from './action'; -import { Presentable, Configurable } from '../util'; -import { SerializedAction } from './types'; - -/** - * This is a convenience interface for registering new action factories. - */ -export interface ActionFactoryDefinition< - Config extends object = object, - FactoryContext extends object = object, - ActionContext extends object = object -> extends Partial>, Configurable { - /** - * Unique ID of the action factory. This ID is used to identify this action - * factory in the registry as well as to construct actions of this type and - * identify this action factory when presenting it to the user in UI. - */ - id: string; - - /** - * This method should return a definition of a new action, normally used to - * register it in `ui_actions` registry. - */ - create( - serializedAction: Omit, 'factoryId'> - ): ActionDefinition; -} diff --git a/src/plugins/ui_actions/public/actions/action_internal.ts b/src/plugins/ui_actions/public/actions/action_internal.ts deleted file mode 100644 index 245ded991c032..0000000000000 --- a/src/plugins/ui_actions/public/actions/action_internal.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Action, ActionContext as Context, ActionDefinition } from './action'; -import { Presentable } from '../util/presentable'; -import { uiToReactComponent } from '../../../kibana_react/public'; -import { ActionType } from '../types'; - -export class ActionInternal - implements Action>, Presentable> { - constructor(public readonly definition: A) {} - - public readonly id: string = this.definition.id; - public readonly type: ActionType = this.definition.type || ''; - public readonly order: number = this.definition.order || 0; - public readonly MenuItem? = this.definition.MenuItem; - public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined; - - public execute(context: Context) { - return this.definition.execute(context); - } - - public getIconType(context: Context): string | undefined { - if (!this.definition.getIconType) return undefined; - return this.definition.getIconType(context); - } - - public getDisplayName(context: Context): string { - if (!this.definition.getDisplayName) return `Action: ${this.id}`; - return this.definition.getDisplayName(context); - } - - public async isCompatible(context: Context): Promise { - if (!this.definition.isCompatible) return true; - return await this.definition.isCompatible(context); - } - - public getHref(context: Context): string | undefined { - if (!this.definition.getHref) return undefined; - return this.definition.getHref(context); - } -} diff --git a/src/plugins/ui_actions/public/actions/create_action.ts b/src/plugins/ui_actions/public/actions/create_action.ts index 8f1cd23715d3f..90a9415c0b497 100644 --- a/src/plugins/ui_actions/public/actions/create_action.ts +++ b/src/plugins/ui_actions/public/actions/create_action.ts @@ -17,19 +17,11 @@ * under the License. */ -import { ActionContextMapping } from '../types'; import { ActionByType } from './action'; import { ActionType } from '../types'; -import { ActionDefinition } from './action'; +import { ActionDefinition } from './action_definition'; -interface ActionDefinitionByType - extends Omit, 'id'> { - id?: string; -} - -export function createAction( - action: ActionDefinitionByType -): ActionByType { +export function createAction(action: ActionDefinition): ActionByType { return { getIconType: () => undefined, order: 0, @@ -38,5 +30,5 @@ export function createAction( getDisplayName: () => '', getHref: () => undefined, ...action, - } as ActionByType; + }; } diff --git a/src/plugins/ui_actions/public/actions/dynamic_action_manager.test.ts b/src/plugins/ui_actions/public/actions/dynamic_action_manager.test.ts deleted file mode 100644 index 2574a9e529ebf..0000000000000 --- a/src/plugins/ui_actions/public/actions/dynamic_action_manager.test.ts +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { DynamicActionManager } from './dynamic_action_manager'; -import { ActionStorage, MemoryActionStorage, SerializedEvent } from './dynamic_action_storage'; -import { UiActionsService } from '../service'; -import { ActionFactoryDefinition } from './action_factory_definition'; -import { ActionRegistry } from '../types'; -import { SerializedAction } from './types'; -import { of } from '../../../kibana_utils'; - -const actionFactoryDefinition1: ActionFactoryDefinition = { - id: 'ACTION_FACTORY_1', - CollectConfig: {} as any, - createConfig: () => ({}), - isConfigValid: (() => true) as any, - create: ({ name }) => ({ - id: '', - execute: async () => {}, - getDisplayName: () => name, - }), -}; - -const actionFactoryDefinition2: ActionFactoryDefinition = { - id: 'ACTION_FACTORY_2', - CollectConfig: {} as any, - createConfig: () => ({}), - isConfigValid: (() => true) as any, - create: ({ name }) => ({ - id: '', - execute: async () => {}, - getDisplayName: () => name, - }), -}; - -const event1: SerializedEvent = { - eventId: 'EVENT_ID_1', - triggers: ['VALUE_CLICK_TRIGGER'], - action: { - factoryId: actionFactoryDefinition1.id, - name: 'Action 1', - config: {}, - }, -}; - -const event2: SerializedEvent = { - eventId: 'EVENT_ID_2', - triggers: ['VALUE_CLICK_TRIGGER'], - action: { - factoryId: actionFactoryDefinition1.id, - name: 'Action 2', - config: {}, - }, -}; - -const event3: SerializedEvent = { - eventId: 'EVENT_ID_3', - triggers: ['VALUE_CLICK_TRIGGER'], - action: { - factoryId: actionFactoryDefinition2.id, - name: 'Action 3', - config: {}, - }, -}; - -const setup = (events: readonly SerializedEvent[] = []) => { - const isCompatible = async () => true; - const storage: ActionStorage = new MemoryActionStorage(events); - const actions: ActionRegistry = new Map(); - const uiActions = new UiActionsService({ - actions, - }); - const manager = new DynamicActionManager({ - isCompatible, - storage, - uiActions, - }); - - uiActions.registerTrigger({ - id: 'VALUE_CLICK_TRIGGER', - }); - - return { - isCompatible, - actions, - storage, - uiActions, - manager, - }; -}; - -describe('DynamicActionManager', () => { - test('can instantiate', () => { - const { manager } = setup([event1]); - expect(manager).toBeInstanceOf(DynamicActionManager); - }); - - describe('.start()', () => { - test('instantiates stored events', async () => { - const { manager, actions, uiActions } = setup([event1]); - const create1 = jest.fn(); - const create2 = jest.fn(); - - uiActions.registerActionFactory({ ...actionFactoryDefinition1, create: create1 }); - uiActions.registerActionFactory({ ...actionFactoryDefinition2, create: create2 }); - - expect(create1).toHaveBeenCalledTimes(0); - expect(create2).toHaveBeenCalledTimes(0); - expect(actions.size).toBe(0); - - await manager.start(); - - expect(create1).toHaveBeenCalledTimes(1); - expect(create2).toHaveBeenCalledTimes(0); - expect(actions.size).toBe(1); - }); - - test('does nothing when no events stored', async () => { - const { manager, actions, uiActions } = setup(); - const create1 = jest.fn(); - const create2 = jest.fn(); - - uiActions.registerActionFactory({ ...actionFactoryDefinition1, create: create1 }); - uiActions.registerActionFactory({ ...actionFactoryDefinition2, create: create2 }); - - expect(create1).toHaveBeenCalledTimes(0); - expect(create2).toHaveBeenCalledTimes(0); - expect(actions.size).toBe(0); - - await manager.start(); - - expect(create1).toHaveBeenCalledTimes(0); - expect(create2).toHaveBeenCalledTimes(0); - expect(actions.size).toBe(0); - }); - - test('UI state is empty before manager starts', async () => { - const { manager } = setup([event1]); - - expect(manager.state.get()).toMatchObject({ - events: [], - isFetchingEvents: false, - fetchCount: 0, - }); - }); - - test('loads events into UI state', async () => { - const { manager, uiActions } = setup([event1, event2, event3]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - uiActions.registerActionFactory(actionFactoryDefinition2); - - await manager.start(); - - expect(manager.state.get()).toMatchObject({ - events: [event1, event2, event3], - isFetchingEvents: false, - fetchCount: 1, - }); - }); - - test('sets isFetchingEvents to true while fetching events', async () => { - const { manager, uiActions } = setup([event1, event2, event3]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - uiActions.registerActionFactory(actionFactoryDefinition2); - - const promise = manager.start().catch(() => {}); - - expect(manager.state.get().isFetchingEvents).toBe(true); - - await promise; - - expect(manager.state.get().isFetchingEvents).toBe(false); - }); - - test('throws if storage threw', async () => { - const { manager, storage } = setup([event1]); - - storage.list = async () => { - throw new Error('baz'); - }; - - const [, error] = await of(manager.start()); - - expect(error).toEqual(new Error('baz')); - }); - - test('sets UI state error if error happened during initial fetch', async () => { - const { manager, storage } = setup([event1]); - - storage.list = async () => { - throw new Error('baz'); - }; - - await of(manager.start()); - - expect(manager.state.get().fetchError!.message).toBe('baz'); - }); - }); - - describe('.stop()', () => { - test('removes events from UI actions registry', async () => { - const { manager, actions, uiActions } = setup([event1, event2]); - const create1 = jest.fn(); - const create2 = jest.fn(); - - uiActions.registerActionFactory({ ...actionFactoryDefinition1, create: create1 }); - uiActions.registerActionFactory({ ...actionFactoryDefinition2, create: create2 }); - - expect(actions.size).toBe(0); - - await manager.start(); - - expect(actions.size).toBe(2); - - await manager.stop(); - - expect(actions.size).toBe(0); - }); - }); - - describe('.createEvent()', () => { - describe('when storage succeeds', () => { - test('stores new event in storage', async () => { - const { manager, storage, uiActions } = setup([]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - expect(await storage.count()).toBe(0); - - await manager.createEvent(action, ['VALUE_CLICK_TRIGGER']); - - expect(await storage.count()).toBe(1); - - const [event] = await storage.list(); - - expect(event).toMatchObject({ - eventId: expect.any(String), - triggers: ['VALUE_CLICK_TRIGGER'], - action: { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }, - }); - }); - - test('adds event to UI state', async () => { - const { manager, uiActions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(manager.state.get().events.length).toBe(0); - - await manager.createEvent(action, ['VALUE_CLICK_TRIGGER']); - - expect(manager.state.get().events.length).toBe(1); - }); - - test('optimistically adds event to UI state', async () => { - const { manager, uiActions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(manager.state.get().events.length).toBe(0); - - const promise = manager.createEvent(action, ['VALUE_CLICK_TRIGGER']).catch(e => e); - - expect(manager.state.get().events.length).toBe(1); - - await promise; - - expect(manager.state.get().events.length).toBe(1); - }); - - test('instantiates event in actions service', async () => { - const { manager, uiActions, actions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(actions.size).toBe(0); - - await manager.createEvent(action, ['VALUE_CLICK_TRIGGER']); - - expect(actions.size).toBe(1); - }); - }); - - describe('when storage fails', () => { - test('throws an error', async () => { - const { manager, storage, uiActions } = setup([]); - - storage.create = async () => { - throw new Error('foo'); - }; - - uiActions.registerActionFactory(actionFactoryDefinition1); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - const [, error] = await of(manager.createEvent(action, ['VALUE_CLICK_TRIGGER'])); - - expect(error).toEqual(new Error('foo')); - }); - - test('does not add even to UI state', async () => { - const { manager, storage, uiActions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - storage.create = async () => { - throw new Error('foo'); - }; - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - await of(manager.createEvent(action, ['VALUE_CLICK_TRIGGER'])); - - expect(manager.state.get().events.length).toBe(0); - }); - - test('optimistically adds event to UI state and then removes it', async () => { - const { manager, storage, uiActions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - storage.create = async () => { - throw new Error('foo'); - }; - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(manager.state.get().events.length).toBe(0); - - const promise = manager.createEvent(action, ['VALUE_CLICK_TRIGGER']).catch(e => e); - - expect(manager.state.get().events.length).toBe(1); - - await promise; - - expect(manager.state.get().events.length).toBe(0); - }); - - test('does not instantiate event in actions service', async () => { - const { manager, storage, uiActions, actions } = setup([]); - const action: SerializedAction = { - factoryId: actionFactoryDefinition1.id, - name: 'foo', - config: {}, - }; - - storage.create = async () => { - throw new Error('foo'); - }; - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(actions.size).toBe(0); - - await of(manager.createEvent(action, ['VALUE_CLICK_TRIGGER'])); - - expect(actions.size).toBe(0); - }); - }); - }); - - describe('.updateEvent()', () => { - describe('when storage succeeds', () => { - test('un-registers old event from ui actions service and registers the new one', async () => { - const { manager, actions, uiActions } = setup([event3]); - - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - expect(actions.size).toBe(1); - - const registeredAction1 = actions.values().next().value; - - expect(registeredAction1.getDisplayName()).toBe('Action 3'); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - await manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER']); - - expect(actions.size).toBe(1); - - const registeredAction2 = actions.values().next().value; - - expect(registeredAction2.getDisplayName()).toBe('foo'); - }); - - test('updates event in storage', async () => { - const { manager, storage, uiActions } = setup([event3]); - const storageUpdateSpy = jest.spyOn(storage, 'update'); - - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - expect(storageUpdateSpy).toHaveBeenCalledTimes(0); - - await manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER']); - - expect(storageUpdateSpy).toHaveBeenCalledTimes(1); - expect(storageUpdateSpy.mock.calls[0][0]).toMatchObject({ - eventId: expect.any(String), - triggers: ['VALUE_CLICK_TRIGGER'], - action: { - factoryId: actionFactoryDefinition2.id, - }, - }); - }); - - test('updates event in UI state', async () => { - const { manager, uiActions } = setup([event3]); - - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - expect(manager.state.get().events[0].action.name).toBe('Action 3'); - - await manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER']); - - expect(manager.state.get().events[0].action.name).toBe('foo'); - }); - - test('optimistically updates event in UI state', async () => { - const { manager, uiActions } = setup([event3]); - - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - expect(manager.state.get().events[0].action.name).toBe('Action 3'); - - const promise = manager - .updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER']) - .catch(e => e); - - expect(manager.state.get().events[0].action.name).toBe('foo'); - - await promise; - }); - }); - - describe('when storage fails', () => { - test('throws error', async () => { - const { manager, storage, uiActions } = setup([event3]); - - storage.update = () => { - throw new Error('bar'); - }; - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - const [, error] = await of( - manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER']) - ); - - expect(error).toEqual(new Error('bar')); - }); - - test('keeps the old action in actions registry', async () => { - const { manager, storage, actions, uiActions } = setup([event3]); - - storage.update = () => { - throw new Error('bar'); - }; - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - expect(actions.size).toBe(1); - - const registeredAction1 = actions.values().next().value; - - expect(registeredAction1.getDisplayName()).toBe('Action 3'); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - await of(manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER'])); - - expect(actions.size).toBe(1); - - const registeredAction2 = actions.values().next().value; - - expect(registeredAction2.getDisplayName()).toBe('Action 3'); - }); - - test('keeps old event in UI state', async () => { - const { manager, storage, uiActions } = setup([event3]); - - storage.update = () => { - throw new Error('bar'); - }; - uiActions.registerActionFactory(actionFactoryDefinition2); - await manager.start(); - - const action: SerializedAction = { - factoryId: actionFactoryDefinition2.id, - name: 'foo', - config: {}, - }; - - expect(manager.state.get().events[0].action.name).toBe('Action 3'); - - await of(manager.updateEvent(event3.eventId, action, ['VALUE_CLICK_TRIGGER'])); - - expect(manager.state.get().events[0].action.name).toBe('Action 3'); - }); - }); - }); - - describe('.deleteEvents()', () => { - describe('when storage succeeds', () => { - test('removes all actions from uiActions service', async () => { - const { manager, actions, uiActions } = setup([event2, event1]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(actions.size).toBe(2); - - await manager.deleteEvents([event1.eventId, event2.eventId]); - - expect(actions.size).toBe(0); - }); - - test('removes all events from storage', async () => { - const { manager, uiActions, storage } = setup([event2, event1]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(await storage.list()).toEqual([event2, event1]); - - await manager.deleteEvents([event1.eventId, event2.eventId]); - - expect(await storage.list()).toEqual([]); - }); - - test('removes all events from UI state', async () => { - const { manager, uiActions } = setup([event2, event1]); - - uiActions.registerActionFactory(actionFactoryDefinition1); - - await manager.start(); - - expect(manager.state.get().events).toEqual([event2, event1]); - - await manager.deleteEvents([event1.eventId, event2.eventId]); - - expect(manager.state.get().events).toEqual([]); - }); - }); - }); -}); diff --git a/src/plugins/ui_actions/public/actions/dynamic_action_manager.ts b/src/plugins/ui_actions/public/actions/dynamic_action_manager.ts deleted file mode 100644 index 97eb5b05fbbc2..0000000000000 --- a/src/plugins/ui_actions/public/actions/dynamic_action_manager.ts +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { v4 as uuidv4 } from 'uuid'; -import { Subscription } from 'rxjs'; -import { ActionStorage, SerializedEvent } from './dynamic_action_storage'; -import { UiActionsService } from '../service'; -import { SerializedAction } from './types'; -import { TriggerContextMapping } from '../types'; -import { ActionDefinition } from './action'; -import { defaultState, transitions, selectors, State } from './dynamic_action_manager_state'; -import { StateContainer, createStateContainer } from '../../../kibana_utils'; - -const compareEvents = ( - a: ReadonlyArray<{ eventId: string }>, - b: ReadonlyArray<{ eventId: string }> -) => { - if (a.length !== b.length) return false; - for (let i = 0; i < a.length; i++) if (a[i].eventId !== b[i].eventId) return false; - return true; -}; - -export type DynamicActionManagerState = State; - -export interface DynamicActionManagerParams { - storage: ActionStorage; - uiActions: Pick< - UiActionsService, - 'registerAction' | 'attachAction' | 'unregisterAction' | 'detachAction' | 'getActionFactory' - >; - isCompatible: (context: C) => Promise; -} - -export class DynamicActionManager { - static idPrefixCounter = 0; - - private readonly idPrefix = `D_ACTION_${DynamicActionManager.idPrefixCounter++}_`; - private stopped: boolean = false; - private reloadSubscription?: Subscription; - - /** - * UI State of the dynamic action manager. - */ - protected readonly ui = createStateContainer(defaultState, transitions, selectors); - - constructor(protected readonly params: DynamicActionManagerParams) {} - - protected getEvent(eventId: string): SerializedEvent { - const oldEvent = this.ui.selectors.getEvent(eventId); - if (!oldEvent) throw new Error(`Could not find event [eventId = ${eventId}].`); - return oldEvent; - } - - /** - * We prefix action IDs with a unique `.idPrefix`, so we can render the - * same dashboard twice on the screen. - */ - protected generateActionId(eventId: string): string { - return this.idPrefix + eventId; - } - - protected reviveAction(event: SerializedEvent) { - const { eventId, triggers, action } = event; - const { uiActions, isCompatible } = this.params; - - const actionId = this.generateActionId(eventId); - const factory = uiActions.getActionFactory(event.action.factoryId); - const actionDefinition: ActionDefinition = { - ...factory.create(action as SerializedAction), - id: actionId, - isCompatible, - }; - - uiActions.registerAction(actionDefinition); - for (const trigger of triggers) uiActions.attachAction(trigger as any, actionId); - } - - protected killAction({ eventId, triggers }: SerializedEvent) { - const { uiActions } = this.params; - const actionId = this.generateActionId(eventId); - - for (const trigger of triggers) uiActions.detachAction(trigger as any, actionId); - uiActions.unregisterAction(actionId); - } - - private syncId = 0; - - /** - * This function is called every time stored events might have changed not by - * us. For example, when in edit mode on dashboard user presses "back" button - * in the browser, then contents of storage changes. - */ - private onSync = () => { - if (this.stopped) return; - - (async () => { - const syncId = ++this.syncId; - const events = await this.params.storage.list(); - - if (this.stopped) return; - if (syncId !== this.syncId) return; - if (compareEvents(events, this.ui.get().events)) return; - - for (const event of this.ui.get().events) this.killAction(event); - for (const event of events) this.reviveAction(event); - this.ui.transitions.finishFetching(events); - })().catch(error => { - /* eslint-disable */ - console.log('Dynamic action manager storage reload failed.'); - console.error(error); - /* eslint-enable */ - }); - }; - - // Public API: --------------------------------------------------------------- - - /** - * Read-only state container of dynamic action manager. Use it to perform all - * *read* operations. - */ - public readonly state: StateContainer = this.ui; - - /** - * 1. Loads all events from @type {DynamicActionStorage} storage. - * 2. Creates actions for each event in `ui_actions` registry. - * 3. Adds events to UI state. - * 4. Does nothing if dynamic action manager was stopped or if event fetching - * is already taking place. - */ - public async start() { - if (this.stopped) return; - if (this.ui.get().isFetchingEvents) return; - - this.ui.transitions.startFetching(); - try { - const events = await this.params.storage.list(); - for (const event of events) this.reviveAction(event); - this.ui.transitions.finishFetching(events); - } catch (error) { - this.ui.transitions.failFetching(error instanceof Error ? error : { message: String(error) }); - throw error; - } - - if (this.params.storage.reload$) { - this.reloadSubscription = this.params.storage.reload$.subscribe(this.onSync); - } - } - - /** - * 1. Removes all events from `ui_actions` registry. - * 2. Puts dynamic action manager is stopped state. - */ - public async stop() { - this.stopped = true; - const events = await this.params.storage.list(); - - for (const event of events) { - this.killAction(event); - } - - if (this.reloadSubscription) { - this.reloadSubscription.unsubscribe(); - } - } - - /** - * Creates a new event. - * - * 1. Stores event in @type {DynamicActionStorage} storage. - * 2. Optimistically adds it to UI state, and rolls back on failure. - * 3. Adds action to `ui_actions` registry. - * - * @param action Dynamic action for which to create an event. - * @param triggers List of triggers to which action should react. - */ - public async createEvent( - action: SerializedAction, - triggers: Array - ) { - const event: SerializedEvent = { - eventId: uuidv4(), - triggers, - action, - }; - - this.ui.transitions.addEvent(event); - try { - await this.params.storage.create(event); - this.reviveAction(event); - } catch (error) { - this.ui.transitions.removeEvent(event.eventId); - throw error; - } - } - - /** - * Updates an existing event. Fails if event with given `eventId` does not - * exit. - * - * 1. Updates the event in @type {DynamicActionStorage} storage. - * 2. Optimistically replaces the old event by the new one in UI state, and - * rolls back on failure. - * 3. Replaces action in `ui_actions` registry with the new event. - * - * - * @param eventId ID of the event to replace. - * @param action New action for which to create the event. - * @param triggers List of triggers to which action should react. - */ - public async updateEvent( - eventId: string, - action: SerializedAction, - triggers: Array - ) { - const event: SerializedEvent = { - eventId, - triggers, - action, - }; - const oldEvent = this.getEvent(eventId); - this.killAction(oldEvent); - - this.reviveAction(event); - this.ui.transitions.replaceEvent(event); - - try { - await this.params.storage.update(event); - } catch (error) { - this.killAction(event); - this.reviveAction(oldEvent); - this.ui.transitions.replaceEvent(oldEvent); - throw error; - } - } - - /** - * Removes existing event. Throws if event does not exist. - * - * 1. Removes the event from @type {DynamicActionStorage} storage. - * 2. Optimistically removes event from UI state, and puts it back on failure. - * 3. Removes associated action from `ui_actions` registry. - * - * @param eventId ID of the event to remove. - */ - public async deleteEvent(eventId: string) { - const event = this.getEvent(eventId); - - this.killAction(event); - this.ui.transitions.removeEvent(eventId); - - try { - await this.params.storage.remove(eventId); - } catch (error) { - this.reviveAction(event); - this.ui.transitions.addEvent(event); - throw error; - } - } - - /** - * Deletes multiple events at once. - * - * @param eventIds List of event IDs. - */ - public async deleteEvents(eventIds: string[]) { - await Promise.all(eventIds.map(this.deleteEvent.bind(this))); - } -} diff --git a/src/plugins/ui_actions/public/actions/dynamic_action_manager_state.ts b/src/plugins/ui_actions/public/actions/dynamic_action_manager_state.ts deleted file mode 100644 index 636af076ea39f..0000000000000 --- a/src/plugins/ui_actions/public/actions/dynamic_action_manager_state.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SerializedEvent } from './dynamic_action_storage'; - -/** - * This interface represents the state of @type {DynamicActionManager} at any - * point in time. - */ -export interface State { - /** - * Whether dynamic action manager is currently in process of fetching events - * from storage. - */ - readonly isFetchingEvents: boolean; - - /** - * Number of times event fetching has been completed. - */ - readonly fetchCount: number; - - /** - * Error received last time when fetching events. - */ - readonly fetchError?: { - message: string; - }; - - /** - * List of all fetched events. - */ - readonly events: readonly SerializedEvent[]; -} - -export interface Transitions { - startFetching: (state: State) => () => State; - finishFetching: (state: State) => (events: SerializedEvent[]) => State; - failFetching: (state: State) => (error: { message: string }) => State; - addEvent: (state: State) => (event: SerializedEvent) => State; - removeEvent: (state: State) => (eventId: string) => State; - replaceEvent: (state: State) => (event: SerializedEvent) => State; -} - -export interface Selectors { - getEvent: (state: State) => (eventId: string) => SerializedEvent | null; -} - -export const defaultState: State = { - isFetchingEvents: false, - fetchCount: 0, - events: [], -}; - -export const transitions: Transitions = { - startFetching: state => () => ({ ...state, isFetchingEvents: true }), - - finishFetching: state => events => ({ - ...state, - isFetchingEvents: false, - fetchCount: state.fetchCount + 1, - fetchError: undefined, - events, - }), - - failFetching: state => ({ message }) => ({ - ...state, - isFetchingEvents: false, - fetchCount: state.fetchCount + 1, - fetchError: { message }, - }), - - addEvent: state => (event: SerializedEvent) => ({ - ...state, - events: [...state.events, event], - }), - - removeEvent: state => (eventId: string) => ({ - ...state, - events: state.events ? state.events.filter(event => event.eventId !== eventId) : state.events, - }), - - replaceEvent: state => event => { - const index = state.events.findIndex(({ eventId }) => eventId === event.eventId); - if (index === -1) return state; - - return { - ...state, - events: [...state.events.slice(0, index), event, ...state.events.slice(index + 1)], - }; - }, -}; - -export const selectors: Selectors = { - getEvent: state => eventId => state.events.find(event => event.eventId === eventId) || null, -}; diff --git a/src/plugins/ui_actions/public/actions/dynamic_action_storage.ts b/src/plugins/ui_actions/public/actions/dynamic_action_storage.ts deleted file mode 100644 index 28550a671782e..0000000000000 --- a/src/plugins/ui_actions/public/actions/dynamic_action_storage.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* eslint-disable max-classes-per-file */ - -import { Observable, Subject } from 'rxjs'; -import { SerializedAction } from './types'; - -/** - * Serialized representation of event-action pair, used to persist in storage. - */ -export interface SerializedEvent { - eventId: string; - triggers: string[]; - action: SerializedAction; -} - -/** - * This CRUD interface needs to be implemented by dynamic action users if they - * want to persist the dynamic actions. It has a default implementation in - * Embeddables, however one can use the dynamic actions without Embeddables, - * in that case they have to implement this interface. - */ -export interface ActionStorage { - create(event: SerializedEvent): Promise; - update(event: SerializedEvent): Promise; - remove(eventId: string): Promise; - read(eventId: string): Promise; - count(): Promise; - list(): Promise; - - /** - * Triggered every time events changed in storage and should be re-loaded. - */ - readonly reload$?: Observable; -} - -export abstract class AbstractActionStorage implements ActionStorage { - public readonly reload$: Observable & Pick, 'next'> = new Subject(); - - public async count(): Promise { - return (await this.list()).length; - } - - public async read(eventId: string): Promise { - const events = await this.list(); - const event = events.find(ev => ev.eventId === eventId); - if (!event) throw new Error(`Event [eventId = ${eventId}] not found.`); - return event; - } - - abstract create(event: SerializedEvent): Promise; - abstract update(event: SerializedEvent): Promise; - abstract remove(eventId: string): Promise; - abstract list(): Promise; -} - -/** - * This is an in-memory implementation of ActionStorage. It is used in testing, - * but can also be used production code to store events in memory. - */ -export class MemoryActionStorage extends AbstractActionStorage { - constructor(public events: readonly SerializedEvent[] = []) { - super(); - } - - public async list() { - return this.events.map(event => ({ ...event })); - } - - public async create(event: SerializedEvent) { - this.events = [...this.events, { ...event }]; - } - - public async update(event: SerializedEvent) { - const index = this.events.findIndex(({ eventId }) => eventId === event.eventId); - if (index < 0) throw new Error(`Event [eventId = ${event.eventId}] not found`); - this.events = [...this.events.slice(0, index), { ...event }, ...this.events.slice(index + 1)]; - } - - public async remove(eventId: string) { - const index = this.events.findIndex(ev => eventId === ev.eventId); - if (index < 0) throw new Error(`Event [eventId = ${eventId}] not found`); - this.events = [...this.events.slice(0, index), ...this.events.slice(index + 1)]; - } -} diff --git a/src/plugins/ui_actions/public/actions/index.ts b/src/plugins/ui_actions/public/actions/index.ts index 0ddba197aced6..64bfd368e3dfa 100644 --- a/src/plugins/ui_actions/public/actions/index.ts +++ b/src/plugins/ui_actions/public/actions/index.ts @@ -18,11 +18,5 @@ */ export * from './action'; -export * from './action_internal'; -export * from './action_factory_definition'; -export * from './action_factory'; export * from './create_action'; export * from './incompatible_action_error'; -export * from './dynamic_action_storage'; -export * from './dynamic_action_manager'; -export * from './types'; diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx index ec58261d9e4f7..3dce2c1f4c257 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx @@ -24,25 +24,19 @@ import { i18n } from '@kbn/i18n'; import { uiToReactComponent } from '../../../kibana_react/public'; import { Action } from '../actions'; -export const defaultTitle = i18n.translate('uiActions.actionPanel.title', { - defaultMessage: 'Options', -}); - /** * Transforms an array of Actions to the shape EuiContextMenuPanel expects. */ -export async function buildContextMenuForActions({ +export async function buildContextMenuForActions({ actions, actionContext, - title = defaultTitle, closeMenu, }: { - actions: Array>; - actionContext: Context; - title?: string; + actions: Array>; + actionContext: A; closeMenu: () => void; }): Promise { - const menuItems = await buildEuiContextMenuPanelItems({ + const menuItems = await buildEuiContextMenuPanelItems({ actions, actionContext, closeMenu, @@ -50,7 +44,9 @@ export async function buildContextMenuForActions({ return { id: 'mainMenu', - title, + title: i18n.translate('uiActions.actionPanel.title', { + defaultMessage: 'Options', + }), items: menuItems, }; } @@ -58,41 +54,49 @@ export async function buildContextMenuForActions({ /** * Transform an array of Actions into the shape needed to build an EUIContextMenu */ -async function buildEuiContextMenuPanelItems({ +async function buildEuiContextMenuPanelItems({ actions, actionContext, closeMenu, }: { - actions: Array>; - actionContext: Context; + actions: Array>; + actionContext: A; closeMenu: () => void; }) { - const items: EuiContextMenuPanelItemDescriptor[] = new Array(actions.length); - const promises = actions.map(async (action, index) => { + const items: EuiContextMenuPanelItemDescriptor[] = []; + const promises = actions.map(async action => { const isCompatible = await action.isCompatible(actionContext); if (!isCompatible) { return; } - items[index] = convertPanelActionToContextMenuItem({ - action, - actionContext, - closeMenu, - }); + items.push( + convertPanelActionToContextMenuItem({ + action, + actionContext, + closeMenu, + }) + ); }); await Promise.all(promises); - return items.filter(Boolean); + return items; } -function convertPanelActionToContextMenuItem({ +/** + * + * @param {ContextMenuAction} action + * @param {Embeddable} embeddable + * @return {EuiContextMenuPanelItemDescriptor} + */ +function convertPanelActionToContextMenuItem({ action, actionContext, closeMenu, }: { - action: Action; - actionContext: Context; + action: Action; + actionContext: A; closeMenu: () => void; }): EuiContextMenuPanelItemDescriptor { const menuPanelItem: EuiContextMenuPanelItemDescriptor = { @@ -111,11 +115,8 @@ function convertPanelActionToContextMenuItem({ closeMenu(); }; - if (action.getHref) { - const href = action.getHref(actionContext); - if (href) { - menuPanelItem.href = action.getHref(actionContext); - } + if (action.getHref && action.getHref(actionContext)) { + menuPanelItem.href = action.getHref(actionContext); } return menuPanelItem; diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts index 9265d35bad9a9..49b6bd5e17699 100644 --- a/src/plugins/ui_actions/public/index.ts +++ b/src/plugins/ui_actions/public/index.ts @@ -26,26 +26,8 @@ export function plugin(initializerContext: PluginInitializerContext) { export { UiActionsSetup, UiActionsStart } from './plugin'; export { UiActionsServiceParams, UiActionsService } from './service'; -export { - Action, - ActionDefinition as UiActionsActionDefinition, - ActionFactoryDefinition as UiActionsActionFactoryDefinition, - ActionInternal as UiActionsActionInternal, - ActionStorage as UiActionsActionStorage, - AbstractActionStorage as UiActionsAbstractActionStorage, - createAction, - DynamicActionManager, - DynamicActionManagerState, - IncompatibleActionError, - SerializedAction as UiActionsSerializedAction, - SerializedEvent as UiActionsSerializedEvent, -} from './actions'; +export { Action, createAction, IncompatibleActionError } from './actions'; export { buildContextMenuForActions } from './context_menu'; -export { - Presentable as UiActionsPresentable, - Configurable as UiActionsConfigurable, - CollectConfigProps as UiActionsCollectConfigProps, -} from './util'; export { Trigger, TriggerContext, @@ -57,4 +39,4 @@ export { applyFilterTrigger, } from './triggers'; export { TriggerContextMapping, TriggerId, ActionContextMapping, ActionType } from './types'; -export { ActionByType, DynamicActionManager as UiActionsDynamicActionManager } from './actions'; +export { ActionByType } from './actions'; diff --git a/src/plugins/ui_actions/public/mocks.ts b/src/plugins/ui_actions/public/mocks.ts index 4de38eb5421e9..c1be6b2626525 100644 --- a/src/plugins/ui_actions/public/mocks.ts +++ b/src/plugins/ui_actions/public/mocks.ts @@ -28,13 +28,10 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { - addTriggerAction: jest.fn(), attachAction: jest.fn(), detachAction: jest.fn(), registerAction: jest.fn(), - registerActionFactory: jest.fn(), registerTrigger: jest.fn(), - unregisterAction: jest.fn(), }; return setupContract; }; @@ -42,21 +39,16 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { attachAction: jest.fn(), - unregisterAction: jest.fn(), - addTriggerAction: jest.fn(), - clear: jest.fn(), + registerAction: jest.fn(), + registerTrigger: jest.fn(), + getAction: jest.fn(), detachAction: jest.fn(), executeTriggerActions: jest.fn(), - fork: jest.fn(), - getAction: jest.fn(), - getActionFactories: jest.fn(), - getActionFactory: jest.fn(), getTrigger: jest.fn(), getTriggerActions: jest.fn((id: TriggerId) => []), getTriggerCompatibleActions: jest.fn(), - registerAction: jest.fn(), - registerActionFactory: jest.fn(), - registerTrigger: jest.fn(), + clear: jest.fn(), + fork: jest.fn(), }; return startContract; diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts index 88a5cb04eac6f..928e57937a9b5 100644 --- a/src/plugins/ui_actions/public/plugin.ts +++ b/src/plugins/ui_actions/public/plugin.ts @@ -23,13 +23,7 @@ import { selectRangeTrigger, valueClickTrigger, applyFilterTrigger } from './tri export type UiActionsSetup = Pick< UiActionsService, - | 'addTriggerAction' - | 'attachAction' - | 'detachAction' - | 'registerAction' - | 'registerActionFactory' - | 'registerTrigger' - | 'unregisterAction' + 'attachAction' | 'detachAction' | 'registerAction' | 'registerTrigger' >; export type UiActionsStart = PublicMethodsOf; diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.test.ts b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts index 41e2b57d53dd8..bdf71a25e6dbc 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_service.test.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts @@ -18,13 +18,7 @@ */ import { UiActionsService } from './ui_actions_service'; -import { - Action, - ActionInternal, - createAction, - ActionFactoryDefinition, - ActionFactory, -} from '../actions'; +import { Action, createAction } from '../actions'; import { createHelloWorldAction } from '../tests/test_samples'; import { ActionRegistry, TriggerRegistry, TriggerId, ActionType } from '../types'; import { Trigger } from '../triggers'; @@ -108,21 +102,6 @@ describe('UiActionsService', () => { type: 'test' as ActionType, }); }); - - test('return action instance', () => { - const service = new UiActionsService(); - const action = service.registerAction({ - id: 'test', - execute: async () => {}, - getDisplayName: () => 'test', - getIconType: () => '', - isCompatible: async () => true, - type: 'test' as ActionType, - }); - - expect(action).toBeInstanceOf(ActionInternal); - expect(action.id).toBe('test'); - }); }); describe('.getTriggerActions()', () => { @@ -160,14 +139,13 @@ describe('UiActionsService', () => { expect(list0).toHaveLength(0); - service.addTriggerAction(FOO_TRIGGER, action1); + service.attachAction(FOO_TRIGGER, action1); const list1 = service.getTriggerActions(FOO_TRIGGER); expect(list1).toHaveLength(1); - expect(list1[0]).toBeInstanceOf(ActionInternal); - expect(list1[0].id).toBe(action1.id); + expect(list1).toEqual([action1]); - service.addTriggerAction(FOO_TRIGGER, action2); + service.attachAction(FOO_TRIGGER, action2); const list2 = service.getTriggerActions(FOO_TRIGGER); expect(list2).toHaveLength(2); @@ -186,7 +164,7 @@ describe('UiActionsService', () => { service.registerAction(helloWorldAction); expect(actions.size - length).toBe(1); - expect(actions.get(helloWorldAction.id)!.id).toBe(helloWorldAction.id); + expect(actions.get(helloWorldAction.id)).toBe(helloWorldAction); }); test('getTriggerCompatibleActions returns attached actions', async () => { @@ -200,7 +178,7 @@ describe('UiActionsService', () => { title: 'My trigger', }; service.registerTrigger(testTrigger); - service.addTriggerAction(MY_TRIGGER, helloWorldAction); + service.attachAction(MY_TRIGGER, helloWorldAction); const compatibleActions = await service.getTriggerCompatibleActions(MY_TRIGGER, { hi: 'there', @@ -226,7 +204,7 @@ describe('UiActionsService', () => { }; service.registerTrigger(testTrigger); - service.addTriggerAction(testTrigger.id, action); + service.attachAction(testTrigger.id, action); const compatibleActions1 = await service.getTriggerCompatibleActions(testTrigger.id, { accept: true, @@ -310,7 +288,7 @@ describe('UiActionsService', () => { id: FOO_TRIGGER, }); service1.registerAction(testAction1); - service1.addTriggerAction(FOO_TRIGGER, testAction1); + service1.attachAction(FOO_TRIGGER, testAction1); const service2 = service1.fork(); @@ -331,14 +309,14 @@ describe('UiActionsService', () => { }); service1.registerAction(testAction1); service1.registerAction(testAction2); - service1.addTriggerAction(FOO_TRIGGER, testAction1); + service1.attachAction(FOO_TRIGGER, testAction1); const service2 = service1.fork(); expect(service1.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); expect(service2.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); - service2.addTriggerAction(FOO_TRIGGER, testAction2); + service2.attachAction(FOO_TRIGGER, testAction2); expect(service1.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); expect(service2.getTriggerActions(FOO_TRIGGER)).toHaveLength(2); @@ -352,14 +330,14 @@ describe('UiActionsService', () => { }); service1.registerAction(testAction1); service1.registerAction(testAction2); - service1.addTriggerAction(FOO_TRIGGER, testAction1); + service1.attachAction(FOO_TRIGGER, testAction1); const service2 = service1.fork(); expect(service1.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); expect(service2.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); - service1.addTriggerAction(FOO_TRIGGER, testAction2); + service1.attachAction(FOO_TRIGGER, testAction2); expect(service1.getTriggerActions(FOO_TRIGGER)).toHaveLength(2); expect(service2.getTriggerActions(FOO_TRIGGER)).toHaveLength(1); @@ -414,7 +392,7 @@ describe('UiActionsService', () => { } as any; service.registerTrigger(trigger); - service.addTriggerAction(MY_TRIGGER, action); + service.attachAction(MY_TRIGGER, action); const actions = service.getTriggerActions(trigger.id); @@ -422,7 +400,7 @@ describe('UiActionsService', () => { expect(actions[0].id).toBe(ACTION_HELLO_WORLD); }); - test('can detach an action from a trigger', () => { + test('can detach an action to a trigger', () => { const service = new UiActionsService(); const trigger: Trigger = { @@ -435,7 +413,7 @@ describe('UiActionsService', () => { service.registerTrigger(trigger); service.registerAction(action); - service.addTriggerAction(trigger.id, action); + service.attachAction(trigger.id, action); service.detachAction(trigger.id, action.id); const actions2 = service.getTriggerActions(trigger.id); @@ -467,7 +445,7 @@ describe('UiActionsService', () => { } as any; service.registerAction(action); - expect(() => service.addTriggerAction('i do not exist' as TriggerId, action)).toThrowError( + expect(() => service.attachAction('i do not exist' as TriggerId, action)).toThrowError( 'No trigger [triggerId = i do not exist] exists, for attaching action [actionId = ACTION_HELLO_WORLD].' ); }); @@ -497,64 +475,4 @@ describe('UiActionsService', () => { ); }); }); - - describe('action factories', () => { - const factoryDefinition1: ActionFactoryDefinition = { - id: 'test-factory-1', - CollectConfig: {} as any, - createConfig: () => ({}), - isConfigValid: () => true, - create: () => ({} as any), - }; - const factoryDefinition2: ActionFactoryDefinition = { - id: 'test-factory-2', - CollectConfig: {} as any, - createConfig: () => ({}), - isConfigValid: () => true, - create: () => ({} as any), - }; - - test('.getActionFactories() returns empty array if no action factories registered', () => { - const service = new UiActionsService(); - - const factories = service.getActionFactories(); - - expect(factories).toEqual([]); - }); - - test('can register and retrieve an action factory', () => { - const service = new UiActionsService(); - - service.registerActionFactory(factoryDefinition1); - - const factory = service.getActionFactory(factoryDefinition1.id); - - expect(factory).toBeInstanceOf(ActionFactory); - expect(factory.id).toBe(factoryDefinition1.id); - }); - - test('can retrieve all action factories', () => { - const service = new UiActionsService(); - - service.registerActionFactory(factoryDefinition1); - service.registerActionFactory(factoryDefinition2); - - const factories = service.getActionFactories(); - const factoriesSorted = [...factories].sort((f1, f2) => (f1.id > f2.id ? 1 : -1)); - - expect(factoriesSorted.length).toBe(2); - expect(factoriesSorted[0].id).toBe(factoryDefinition1.id); - expect(factoriesSorted[1].id).toBe(factoryDefinition2.id); - }); - - test('throws when retrieving action factory that does not exist', () => { - const service = new UiActionsService(); - - service.registerActionFactory(factoryDefinition1); - - expect(() => service.getActionFactory('UNKNOWN_ID')).toThrowError( - 'Action factory [actionFactoryId = UNKNOWN_ID] does not exist.' - ); - }); - }); }); diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.ts b/src/plugins/ui_actions/public/service/ui_actions_service.ts index 8bd3bb34fbbd8..f7718e63773f5 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_service.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_service.ts @@ -24,17 +24,8 @@ import { TriggerId, TriggerContextMapping, ActionType, - ActionFactoryRegistry, } from '../types'; -import { - ActionInternal, - Action, - ActionByType, - ActionFactory, - ActionDefinition, - ActionFactoryDefinition, - ActionContext, -} from '../actions'; +import { Action, ActionByType } from '../actions'; import { Trigger, TriggerContext } from '../triggers/trigger'; import { TriggerInternal } from '../triggers/trigger_internal'; import { TriggerContract } from '../triggers/trigger_contract'; @@ -47,25 +38,21 @@ export interface UiActionsServiceParams { * A 1-to-N mapping from `Trigger` to zero or more `Action`. */ readonly triggerToActions?: TriggerToActionsRegistry; - readonly actionFactories?: ActionFactoryRegistry; } export class UiActionsService { protected readonly triggers: TriggerRegistry; protected readonly actions: ActionRegistry; protected readonly triggerToActions: TriggerToActionsRegistry; - protected readonly actionFactories: ActionFactoryRegistry; constructor({ triggers = new Map(), actions = new Map(), triggerToActions = new Map(), - actionFactories = new Map(), }: UiActionsServiceParams = {}) { this.triggers = triggers; this.actions = actions; this.triggerToActions = triggerToActions; - this.actionFactories = actionFactories; } public readonly registerTrigger = (trigger: Trigger) => { @@ -89,44 +76,49 @@ export class UiActionsService { return trigger.contract; }; - public readonly registerAction = ( - definition: A - ): ActionInternal => { - if (this.actions.has(definition.id)) { - throw new Error(`Action [action.id = ${definition.id}] already registered.`); + public readonly registerAction = (action: ActionByType) => { + if (this.actions.has(action.id)) { + throw new Error(`Action [action.id = ${action.id}] already registered.`); } - const action = new ActionInternal(definition); - this.actions.set(action.id, action); - - return action; }; - public readonly unregisterAction = (actionId: string): void => { - if (!this.actions.has(actionId)) { - throw new Error(`Action [action.id = ${actionId}] is not registered.`); + public readonly getAction = (id: string): ActionByType => { + if (!this.actions.has(id)) { + throw new Error(`Action [action.id = ${id}] not registered.`); } - this.actions.delete(actionId); + return this.actions.get(id) as ActionByType; }; - public readonly attachAction = ( - triggerId: TriggerId, - actionId: string + public readonly attachAction = ( + triggerId: TType, + // The action can accept partial or no context, but if it needs context not provided + // by this type of trigger, typescript will complain. yay! + action: ActionByType & Action ): void => { + if (!this.actions.has(action.id)) { + this.registerAction(action); + } else { + const registeredAction = this.actions.get(action.id); + if (registeredAction !== action) { + throw new Error(`A different action instance with this id is already registered.`); + } + } + const trigger = this.triggers.get(triggerId); if (!trigger) { throw new Error( - `No trigger [triggerId = ${triggerId}] exists, for attaching action [actionId = ${actionId}].` + `No trigger [triggerId = ${triggerId}] exists, for attaching action [actionId = ${action.id}].` ); } const actionIds = this.triggerToActions.get(triggerId); - if (!actionIds!.find(id => id === actionId)) { - this.triggerToActions.set(triggerId, [...actionIds!, actionId]); + if (!actionIds!.find(id => id === action.id)) { + this.triggerToActions.set(triggerId, [...actionIds!, action.id]); } }; @@ -147,26 +139,6 @@ export class UiActionsService { ); }; - public readonly addTriggerAction = ( - triggerId: TType, - // The action can accept partial or no context, but if it needs context not provided - // by this type of trigger, typescript will complain. yay! - action: ActionByType & Action - ): void => { - if (!this.actions.has(action.id)) this.registerAction(action); - this.attachAction(triggerId, action.id); - }; - - public readonly getAction = ( - id: string - ): Action> => { - if (!this.actions.has(id)) { - throw new Error(`Action [action.id = ${id}] not registered.`); - } - - return this.actions.get(id) as ActionInternal; - }; - public readonly getTriggerActions = ( triggerId: T ): Array> => { @@ -175,9 +147,9 @@ export class UiActionsService { const actionIds = this.triggerToActions.get(triggerId); - const actions = actionIds! - .map(actionId => this.actions.get(actionId) as ActionInternal) - .filter(Boolean); + const actions = actionIds!.map(actionId => this.actions.get(actionId)).filter(Boolean) as Array< + Action + >; return actions as Array>>; }; @@ -215,7 +187,6 @@ export class UiActionsService { this.actions.clear(); this.triggers.clear(); this.triggerToActions.clear(); - this.actionFactories.clear(); }; /** @@ -235,41 +206,4 @@ export class UiActionsService { return new UiActionsService({ triggers, actions, triggerToActions }); }; - - /** - * Register an action factory. Action factories are used to configure and - * serialize/deserialize dynamic actions. - */ - public readonly registerActionFactory = < - Config extends object = object, - FactoryContext extends object = object, - ActionContext extends object = object - >( - definition: ActionFactoryDefinition - ) => { - if (this.actionFactories.has(definition.id)) { - throw new Error(`ActionFactory [actionFactory.id = ${definition.id}] already registered.`); - } - - const actionFactory = new ActionFactory(definition); - - this.actionFactories.set(actionFactory.id, actionFactory as ActionFactory); - }; - - public readonly getActionFactory = (actionFactoryId: string): ActionFactory => { - const actionFactory = this.actionFactories.get(actionFactoryId); - - if (!actionFactory) { - throw new Error(`Action factory [actionFactoryId = ${actionFactoryId}] does not exist.`); - } - - return actionFactory; - }; - - /** - * Returns an array of all action factories. - */ - public readonly getActionFactories = (): ActionFactory[] => { - return [...this.actionFactories.values()]; - }; } diff --git a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts index ade21ee4b7d91..5b427f918c173 100644 --- a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts @@ -69,7 +69,7 @@ test('executes a single action mapped to a trigger', async () => { const action = createTestAction('test1', () => true); setup.registerTrigger(trigger); - setup.addTriggerAction(trigger.id, action); + setup.attachAction(trigger.id, action); const context = {}; const start = doStart(); @@ -109,7 +109,7 @@ test('does not execute an incompatible action', async () => { ); setup.registerTrigger(trigger); - setup.addTriggerAction(trigger.id, action); + setup.attachAction(trigger.id, action); const start = doStart(); const context = { @@ -130,8 +130,8 @@ test('shows a context menu when more than one action is mapped to a trigger', as const action2 = createTestAction('test2', () => true); setup.registerTrigger(trigger); - setup.addTriggerAction(trigger.id, action1); - setup.addTriggerAction(trigger.id, action2); + setup.attachAction(trigger.id, action1); + setup.attachAction(trigger.id, action2); expect(openContextMenu).toHaveBeenCalledTimes(0); @@ -155,7 +155,7 @@ test('passes whole action context to isCompatible()', async () => { }); setup.registerTrigger(trigger); - setup.addTriggerAction(trigger.id, action); + setup.attachAction(trigger.id, action); const start = doStart(); diff --git a/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts index 55ccac42ff255..f5a6a96fb41a4 100644 --- a/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { ActionInternal, Action } from '../actions'; +import { Action } from '../actions'; import { uiActionsPluginMock } from '../mocks'; import { TriggerId, ActionType } from '../types'; @@ -47,14 +47,13 @@ test('returns actions set on trigger', () => { expect(list0).toHaveLength(0); - setup.addTriggerAction('trigger' as TriggerId, action1); + setup.attachAction('trigger' as TriggerId, action1); const list1 = start.getTriggerActions('trigger' as TriggerId); expect(list1).toHaveLength(1); - expect(list1[0]).toBeInstanceOf(ActionInternal); - expect(list1[0].id).toBe(action1.id); + expect(list1).toEqual([action1]); - setup.addTriggerAction('trigger' as TriggerId, action2); + setup.attachAction('trigger' as TriggerId, action2); const list2 = start.getTriggerActions('trigger' as TriggerId); expect(list2).toHaveLength(2); diff --git a/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts index 21dd17ed82e3f..c5e68e5d5ca5a 100644 --- a/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts @@ -37,7 +37,7 @@ beforeEach(() => { id: 'trigger' as TriggerId, title: 'trigger', }); - uiActions.setup.addTriggerAction('trigger' as TriggerId, action); + uiActions.setup.attachAction('trigger' as TriggerId, action); }); test('can register action', async () => { @@ -58,7 +58,7 @@ test('getTriggerCompatibleActions returns attached actions', async () => { title: 'My trigger', }; setup.registerTrigger(testTrigger); - setup.addTriggerAction('MY-TRIGGER' as TriggerId, helloWorldAction); + setup.attachAction('MY-TRIGGER' as TriggerId, helloWorldAction); const start = doStart(); const actions = await start.getTriggerCompatibleActions('MY-TRIGGER' as TriggerId, {}); @@ -84,7 +84,7 @@ test('filters out actions not applicable based on the context', async () => { setup.registerTrigger(testTrigger); setup.registerAction(action1); - setup.addTriggerAction(testTrigger.id, action1); + setup.attachAction(testTrigger.id, action1); const start = doStart(); let actions = await start.getTriggerCompatibleActions(testTrigger.id, { accept: true }); diff --git a/src/plugins/ui_actions/public/tests/test_samples/index.ts b/src/plugins/ui_actions/public/tests/test_samples/index.ts index dfa71cec89595..7d63b1b6d5669 100644 --- a/src/plugins/ui_actions/public/tests/test_samples/index.ts +++ b/src/plugins/ui_actions/public/tests/test_samples/index.ts @@ -16,5 +16,4 @@ * specific language governing permissions and limitations * under the License. */ - export { createHelloWorldAction } from './hello_world_action'; diff --git a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts b/src/plugins/ui_actions/public/triggers/select_range_trigger.ts index 9758508dc3dac..c638db0ce9dab 100644 --- a/src/plugins/ui_actions/public/triggers/select_range_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/select_range_trigger.ts @@ -22,6 +22,6 @@ import { Trigger } from '.'; export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER'; export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = { id: SELECT_RANGE_TRIGGER, - title: '', + title: 'Select range', description: 'Applies a range filter', }; diff --git a/src/plugins/ui_actions/public/triggers/trigger_internal.ts b/src/plugins/ui_actions/public/triggers/trigger_internal.ts index 9885ed3abe93b..5b670df354f78 100644 --- a/src/plugins/ui_actions/public/triggers/trigger_internal.ts +++ b/src/plugins/ui_actions/public/triggers/trigger_internal.ts @@ -72,7 +72,6 @@ export class TriggerInternal { const panel = await buildContextMenuForActions({ actions, actionContext: context, - title: this.trigger.title, closeMenu: () => session.close(), }); const session = openContextMenu([panel]); diff --git a/src/plugins/ui_actions/public/triggers/value_click_trigger.ts b/src/plugins/ui_actions/public/triggers/value_click_trigger.ts index 2671584d105c8..ad32bdc1b564e 100644 --- a/src/plugins/ui_actions/public/triggers/value_click_trigger.ts +++ b/src/plugins/ui_actions/public/triggers/value_click_trigger.ts @@ -22,6 +22,6 @@ import { Trigger } from '.'; export const VALUE_CLICK_TRIGGER = 'VALUE_CLICK_TRIGGER'; export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> = { id: VALUE_CLICK_TRIGGER, - title: '', + title: 'Value clicked', description: 'Value was clicked', }; diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts index 2cb4a8f26a879..c7e6d61e15f31 100644 --- a/src/plugins/ui_actions/public/types.ts +++ b/src/plugins/ui_actions/public/types.ts @@ -17,17 +17,15 @@ * under the License. */ -import { ActionInternal } from './actions/action_internal'; +import { ActionByType } from './actions/action'; import { TriggerInternal } from './triggers/trigger_internal'; -import { ActionFactory } from './actions'; import { EmbeddableVisTriggerContext, IEmbeddable } from '../../embeddable/public'; import { Filter } from '../../data/public'; import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER, APPLY_FILTER_TRIGGER } from './triggers'; export type TriggerRegistry = Map>; -export type ActionRegistry = Map; +export type ActionRegistry = Map>; export type TriggerToActionsRegistry = Map; -export type ActionFactoryRegistry = Map; const DEFAULT_TRIGGER = ''; diff --git a/src/plugins/ui_actions/public/util/configurable.ts b/src/plugins/ui_actions/public/util/configurable.ts deleted file mode 100644 index d3a527a2183b1..0000000000000 --- a/src/plugins/ui_actions/public/util/configurable.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { UiComponent } from 'src/plugins/kibana_utils/common'; - -/** - * Represents something that can be configured by user using UI. - */ -export interface Configurable { - /** - * Create default config for this item, used when item is created for the first time. - */ - readonly createConfig: () => Config; - - /** - * Is this config valid. Used to validate user's input before saving. - */ - readonly isConfigValid: (config: Config) => boolean; - - /** - * `UiComponent` to be rendered when collecting configuration for this item. - */ - readonly CollectConfig: UiComponent>; -} - -/** - * Props provided to `CollectConfig` component on every re-render. - */ -export interface CollectConfigProps { - /** - * Current (latest) config of the item. - */ - config: Config; - - /** - * Callback called when user updates the config in UI. - */ - onConfig: (config: Config) => void; - - /** - * Context information about where component is being rendered. - */ - context: Context; -} diff --git a/src/plugins/ui_actions/public/util/index.ts b/src/plugins/ui_actions/public/util/index.ts deleted file mode 100644 index 53c6109cac4ca..0000000000000 --- a/src/plugins/ui_actions/public/util/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './presentable'; -export * from './configurable'; diff --git a/src/plugins/usage_collection/README.md b/src/plugins/usage_collection/README.md index 1c97c9c63c0e2..e32dfae35832b 100644 --- a/src/plugins/usage_collection/README.md +++ b/src/plugins/usage_collection/README.md @@ -83,14 +83,14 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { CoreSetup, CoreStart } from 'kibana/server'; class Plugin { - private savedObjectsClient?: ISavedObjectsRepository; + private savedObjectsRepository?: ISavedObjectsRepository; public setup(core: CoreSetup, plugins: { usageCollection?: UsageCollectionSetup }) { - registerMyPluginUsageCollector(() => this.savedObjectsClient, plugins.usageCollection); + registerMyPluginUsageCollector(() => this.savedObjectsRepository, plugins.usageCollection); } public start(core: CoreStart) { - this.savedObjectsClient = core.savedObjects.client + this.savedObjectsRepository = core.savedObjects.createInternalRepository(); } } ``` @@ -101,7 +101,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { ISavedObjectsRepository } from 'kibana/server'; export function registerMyPluginUsageCollector( - getSavedObjectsClient: () => ISavedObjectsRepository | undefined, + getSavedObjectsRepository: () => ISavedObjectsRepository | undefined, usageCollection?: UsageCollectionSetup ): void { // usageCollection is an optional dependency, so make sure to return if it is not registered. @@ -112,9 +112,9 @@ export function registerMyPluginUsageCollector( // create usage collector const myCollector = usageCollection.makeUsageCollector({ type: MY_USAGE_TYPE, - isReady: () => typeof getSavedObjectsClient() !== 'undefined', + isReady: () => typeof getSavedObjectsRepository() !== 'undefined', fetch: async () => { - const savedObjectsClient = getSavedObjectsClient()!; + const savedObjectsRepository = getSavedObjectsRepository()!; // get something from the savedObjects return { my_objects }; diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index 8e63ea7833327..cd22b1375ae1b 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -3,7 +3,5 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": [ - "expressions" - ] + "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection"] } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/__snapshots__/visualization_noresults.test.js.snap b/src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/__snapshots__/visualization_noresults.test.js.snap rename to src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/__snapshots__/visualization_requesterror.test.js.snap b/src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/__snapshots__/visualization_requesterror.test.js.snap rename to src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/_index.scss b/src/plugins/visualizations/public/components/_index.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/_index.scss rename to src/plugins/visualizations/public/components/_index.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/_visualization.scss b/src/plugins/visualizations/public/components/_visualization.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/_visualization.scss rename to src/plugins/visualizations/public/components/_visualization.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/index.ts b/src/plugins/visualizations/public/components/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/index.ts rename to src/plugins/visualizations/public/components/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.test.js b/src/plugins/visualizations/public/components/visualization.test.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.test.js rename to src/plugins/visualizations/public/components/visualization.test.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx b/src/plugins/visualizations/public/components/visualization.tsx similarity index 96% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx rename to src/plugins/visualizations/public/components/visualization.tsx index 5296de365daec..c17e088d7635b 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx +++ b/src/plugins/visualizations/public/components/visualization.tsx @@ -19,7 +19,7 @@ import { get } from 'lodash'; import React from 'react'; -import { PersistedState } from '../../../../../../../plugins/visualizations/public'; +import { PersistedState } from '../../../../plugins/visualizations/public'; import { memoizeLast } from '../legacy/memoize'; import { VisualizationChart } from './visualization_chart'; import { VisualizationNoResults } from './visualization_noresults'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.test.js b/src/plugins/visualizations/public/components/visualization_chart.test.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.test.js rename to src/plugins/visualizations/public/components/visualization_chart.test.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx b/src/plugins/visualizations/public/components/visualization_chart.tsx similarity index 96% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx rename to src/plugins/visualizations/public/components/visualization_chart.tsx index fcfbc8445952c..7d163d2067ee5 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx +++ b/src/plugins/visualizations/public/components/visualization_chart.tsx @@ -20,9 +20,9 @@ import React from 'react'; import * as Rx from 'rxjs'; import { debounceTime, filter, share, switchMap } from 'rxjs/operators'; -import { PersistedState } from '../../../../../../../plugins/visualizations/public'; +import { PersistedState } from '../../../../plugins/visualizations/public'; import { VisualizationController } from '../types'; -import { ResizeChecker } from '../../../../../../../plugins/kibana_utils/public'; +import { ResizeChecker } from '../../../../plugins/kibana_utils/public'; import { ExprVis } from '../expressions/vis'; interface VisualizationChartProps { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_noresults.test.js b/src/plugins/visualizations/public/components/visualization_noresults.test.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_noresults.test.js rename to src/plugins/visualizations/public/components/visualization_noresults.test.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_noresults.tsx b/src/plugins/visualizations/public/components/visualization_noresults.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_noresults.tsx rename to src/plugins/visualizations/public/components/visualization_noresults.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.test.js b/src/plugins/visualizations/public/components/visualization_requesterror.test.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.test.js rename to src/plugins/visualizations/public/components/visualization_requesterror.test.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx b/src/plugins/visualizations/public/components/visualization_requesterror.tsx similarity index 96% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx rename to src/plugins/visualizations/public/components/visualization_requesterror.tsx index 406f24741c911..3e677e609ad9a 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx +++ b/src/plugins/visualizations/public/components/visualization_requesterror.tsx @@ -19,7 +19,7 @@ import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; -import { SearchError } from '../../../../../../../plugins/data/public'; +import { SearchError } from '../../../../plugins/data/public'; interface VisualizationRequestErrorProps { onInit?: () => void; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_embeddables.scss b/src/plugins/visualizations/public/embeddable/_embeddables.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_embeddables.scss rename to src/plugins/visualizations/public/embeddable/_embeddables.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_index.scss b/src/plugins/visualizations/public/embeddable/_index.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_index.scss rename to src/plugins/visualizations/public/embeddable/_index.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_visualize_lab_disabled.scss b/src/plugins/visualizations/public/embeddable/_visualize_lab_disabled.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/_visualize_lab_disabled.scss rename to src/plugins/visualizations/public/embeddable/_visualize_lab_disabled.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/constants.ts b/src/plugins/visualizations/public/embeddable/constants.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/constants.ts rename to src/plugins/visualizations/public/embeddable/constants.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/disabled_lab_embeddable.tsx b/src/plugins/visualizations/public/embeddable/disabled_lab_embeddable.tsx similarity index 94% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/disabled_lab_embeddable.tsx rename to src/plugins/visualizations/public/embeddable/disabled_lab_embeddable.tsx index fbb2eba3afe79..af8121d8bf033 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/disabled_lab_embeddable.tsx +++ b/src/plugins/visualizations/public/embeddable/disabled_lab_embeddable.tsx @@ -19,7 +19,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { Embeddable, EmbeddableOutput } from '../../../../../../../plugins/embeddable/public'; +import { Embeddable, EmbeddableOutput } from '../../../../plugins/embeddable/public'; import { DisabledLabVisualization } from './disabled_lab_visualization'; import { VisualizeInput } from './visualize_embeddable'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/disabled_lab_visualization.tsx b/src/plugins/visualizations/public/embeddable/disabled_lab_visualization.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/disabled_lab_visualization.tsx rename to src/plugins/visualizations/public/embeddable/disabled_lab_visualization.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/events.ts b/src/plugins/visualizations/public/embeddable/events.ts similarity index 90% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/events.ts rename to src/plugins/visualizations/public/embeddable/events.ts index 53d04bf6eb04a..0957895a21403 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/events.ts +++ b/src/plugins/visualizations/public/embeddable/events.ts @@ -17,10 +17,7 @@ * under the License. */ -import { - SELECT_RANGE_TRIGGER, - VALUE_CLICK_TRIGGER, -} from '../../../../../../../plugins/ui_actions/public'; +import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER } from '../../../../plugins/ui_actions/public'; export interface VisEventToTrigger { ['brush']: typeof SELECT_RANGE_TRIGGER; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts b/src/plugins/visualizations/public/embeddable/get_index_pattern.ts similarity index 97% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts rename to src/plugins/visualizations/public/embeddable/get_index_pattern.ts index 05ce68221eaf0..c12c95145fe44 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts +++ b/src/plugins/visualizations/public/embeddable/get_index_pattern.ts @@ -22,7 +22,7 @@ import { indexPatterns, IIndexPattern, IndexPatternAttributes, -} from '../../../../../../../plugins/data/public'; +} from '../../../../plugins/data/public'; import { getUISettings, getSavedObjects } from '../services'; export async function getIndexPattern( diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/index.ts b/src/plugins/visualizations/public/embeddable/index.ts similarity index 95% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/index.ts rename to src/plugins/visualizations/public/embeddable/index.ts index a1cd31eebef20..78f9827ffde3e 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/index.ts +++ b/src/plugins/visualizations/public/embeddable/index.ts @@ -20,3 +20,4 @@ export { DisabledLabEmbeddable } from './disabled_lab_embeddable'; export { VisualizeEmbeddable, VisualizeInput } from './visualize_embeddable'; export { VisualizeEmbeddableFactory } from './visualize_embeddable_factory'; export { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; +export { VIS_EVENT_TO_TRIGGER } from './events'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts similarity index 93% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts rename to src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 4b21be83f1722..0c7e732f0b185 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -28,24 +28,19 @@ import { esFilters, Filter, TimefilterContract, -} from '../../../../../../../plugins/data/public'; +} from '../../../../plugins/data/public'; import { EmbeddableInput, EmbeddableOutput, Embeddable, Container, EmbeddableVisTriggerContext, -} from '../../../../../../../plugins/embeddable/public'; -import { dispatchRenderComplete } from '../../../../../../../plugins/kibana_utils/public'; -import { - IExpressionLoaderParams, - ExpressionsStart, -} from '../../../../../../../plugins/expressions/public'; -import { PersistedState } from '../../../../../../../plugins/visualizations/public'; +} from '../../../../plugins/embeddable/public'; +import { dispatchRenderComplete } from '../../../../plugins/kibana_utils/public'; +import { IExpressionLoaderParams, ExpressionsStart } from '../../../../plugins/expressions/public'; import { buildPipeline } from '../legacy/build_pipeline'; import { Vis } from '../vis'; import { getExpressions, getUiActions } from '../services'; -import { VisualizationsStartDeps } from '../plugin'; import { VIS_EVENT_TO_TRIGGER } from './events'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -55,9 +50,6 @@ export interface VisualizeEmbeddableConfiguration { indexPatterns?: IIndexPattern[]; editUrl: string; editable: boolean; - appState?: { save(): void }; - uiState?: PersistedState; - uiActions?: VisualizationsStartDeps['uiActions']; } export interface VisualizeInput extends EmbeddableInput { @@ -67,8 +59,6 @@ export interface VisualizeInput extends EmbeddableInput { vis?: { colors?: { [key: string]: string }; }; - appState?: { save(): void }; - uiState?: PersistedState; } export interface VisualizeOutput extends EmbeddableOutput { @@ -93,10 +83,11 @@ export class VisualizeEmbeddable extends Embeddable { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; - constructor( - private readonly getUiActions: () => Promise< - Pick['uiActions'] - > - ) { + constructor() { super({ savedObjectMetaData: { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), @@ -119,8 +114,6 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< const indexPattern = vis.data.indexPattern; const indexPatterns = indexPattern ? [indexPattern] : []; - const uiActions = await this.getUiActions(); - const editable = await this.isEditable(); return new VisualizeEmbeddable( getTimeFilter(), @@ -129,9 +122,6 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< indexPatterns, editUrl, editable, - appState: input.appState, - uiState: input.uiState, - uiActions, }, input, parent diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts b/src/plugins/visualizations/public/expressions/vis.ts similarity index 95% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts rename to src/plugins/visualizations/public/expressions/vis.ts index 3b0458a6c8dcc..a7d4a28070620 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts +++ b/src/plugins/visualizations/public/expressions/vis.ts @@ -29,11 +29,10 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; -import { PersistedState } from '../../../../../../../plugins/visualizations/public'; +import { VisParams, PersistedState } from '../../../../plugins/visualizations/public'; import { getTypes } from '../services'; import { VisType } from '../vis_types'; -import { VisParams } from '../types'; export interface ExprVisState { title?: string; @@ -82,10 +81,11 @@ export class ExprVis extends EventEmitter { private getType(type: string | VisType) { if (_.isString(type)) { - return getTypes().get(type); - if (!this.type) { + const newType = getTypes().get(type); + if (!newType) { throw new Error(`Invalid type "${type}"`); } + return newType; } else { return type; } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts b/src/plugins/visualizations/public/expressions/visualization_function.ts similarity index 95% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts rename to src/plugins/visualizations/public/expressions/visualization_function.ts index d98eda4c50ef9..52177f6ec381a 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts +++ b/src/plugins/visualizations/public/expressions/visualization_function.ts @@ -19,14 +19,8 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { - VisResponseValue, - PersistedState, -} from '../../../../../../../plugins/visualizations/public'; -import { - ExpressionFunctionDefinition, - Render, -} from '../../../../../../../plugins/expressions/public'; +import { VisResponseValue, PersistedState } from '../../../../plugins/visualizations/public'; +import { ExpressionFunctionDefinition, Render } from '../../../../plugins/expressions/public'; import { getTypes, getIndexPatterns, getFilterManager } from '../services'; interface Arguments { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx b/src/plugins/visualizations/public/expressions/visualization_renderer.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx rename to src/plugins/visualizations/public/expressions/visualization_renderer.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/_index.scss b/src/plugins/visualizations/public/index.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/_index.scss rename to src/plugins/visualizations/public/index.scss diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index c08dbf890b8da..7df420e7ba585 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -17,15 +17,37 @@ * under the License. */ -import { PluginInitializerContext } from '../../../core/public'; -import { VisualizationsPublicPlugin } from './plugin'; +import './index.scss'; + +import { PublicContract } from '@kbn/utility-types'; +import { PluginInitializerContext } from 'src/core/public'; +import { VisualizationsPlugin, VisualizationsSetup, VisualizationsStart } from './plugin'; +import { VisualizeEmbeddableFactory, VisualizeEmbeddable } from './embeddable'; +import { ExprVis as ExprVisClass } from './expressions/vis'; export function plugin(initializerContext: PluginInitializerContext) { - return new VisualizationsPublicPlugin(initializerContext); + return new VisualizationsPlugin(initializerContext); } -export { VisualizationsPublicPlugin as Plugin }; -export * from './plugin'; -export * from './types'; +/** @public static code */ +export { Vis } from './vis'; +export { TypesService } from './vis_types/types_service'; +export { VISUALIZE_EMBEDDABLE_TYPE, VIS_EVENT_TO_TRIGGER } from './embeddable'; +/** @public types */ +export { VisualizationsSetup, VisualizationsStart }; +export { VisTypeAlias, VisType } from './vis_types'; +export { VisParams, SerializedVis, SerializedVisData, VisData } from './vis'; +export type VisualizeEmbeddableFactoryContract = PublicContract; +export type VisualizeEmbeddableContract = PublicContract; +export { VisualizeInput } from './embeddable'; +export type ExprVis = ExprVisClass; +export { SchemaConfig } from './legacy/build_pipeline'; export { PersistedState } from './persisted_state'; +export { + VisualizationController, + SavedVisState, + ISavedVis, + VisSavedObject, + VisResponseValue, +} from './types'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__snapshots__/build_pipeline.test.ts.snap rename to src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_update_objs/gauge_objs.js b/src/plugins/visualizations/public/legacy/__tests__/vis_update_objs/gauge_objs.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_update_objs/gauge_objs.js rename to src/plugins/visualizations/public/legacy/__tests__/vis_update_objs/gauge_objs.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts similarity index 98% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts rename to src/plugins/visualizations/public/legacy/build_pipeline.test.ts index d5c532b53a53e..5476ce6df0390 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts @@ -27,10 +27,8 @@ import { Schemas, } from './build_pipeline'; import { Vis } from '..'; -import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks'; -import { IAggConfig } from '../../../../../../../plugins/data/public'; - -jest.mock('ui/new_platform'); +import { dataPluginMock } from '../../../../plugins/data/public/mocks'; +import { IAggConfig } from '../../../../plugins/data/public'; describe('visualize loader pipeline helpers: build pipeline', () => { describe('prepareJson', () => { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts similarity index 99% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts rename to src/plugins/visualizations/public/legacy/build_pipeline.ts index ea15cd9201fd7..18af94c919247 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts @@ -19,13 +19,13 @@ import { get } from 'lodash'; import moment from 'moment'; -import { SerializedFieldFormat } from '../../../../../../../plugins/expressions/public'; +import { SerializedFieldFormat } from '../../../../plugins/expressions/public'; import { IAggConfig, fieldFormats, search, TimefilterContract, -} from '../../../../../../../plugins/data/public'; +} from '../../../../plugins/data/public'; import { Vis, VisParams } from '../types'; const { isDateHistogramBucketAggConfig } = search.aggs; @@ -490,6 +490,7 @@ export const buildPipeline = async ( params: { timefilter: TimefilterContract; timeRange?: any; + abortSignal?: AbortSignal; } ) => { const { indexPattern, searchSource } = vis.data; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/memoize.test.ts b/src/plugins/visualizations/public/legacy/memoize.test.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/memoize.test.ts rename to src/plugins/visualizations/public/legacy/memoize.test.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/memoize.ts b/src/plugins/visualizations/public/legacy/memoize.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/memoize.ts rename to src/plugins/visualizations/public/legacy/memoize.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update.js b/src/plugins/visualizations/public/legacy/vis_update.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update.js rename to src/plugins/visualizations/public/legacy/vis_update.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update_state.js b/src/plugins/visualizations/public/legacy/vis_update_state.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update_state.js rename to src/plugins/visualizations/public/legacy/vis_update_state.js diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update_state.test.js b/src/plugins/visualizations/public/legacy/vis_update_state.test.js similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/vis_update_state.test.js rename to src/plugins/visualizations/public/legacy/vis_update_state.test.js diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index af7688d019f65..f4983a4313c4d 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -16,22 +16,60 @@ * specific language governing permissions and limitations * under the License. */ -import { VisualizationsSetup, VisualizationsStart } from '.'; -export type Setup = jest.Mocked; -export type Start = jest.Mocked; +import { PluginInitializerContext } from '../../../core/public'; +import { VisualizationsSetup, VisualizationsStart } from './'; +import { VisualizationsPlugin } from './plugin'; +import { coreMock } from '../../../core/public/mocks'; +import { embeddablePluginMock } from '../../../plugins/embeddable/public/mocks'; +import { expressionsPluginMock } from '../../../plugins/expressions/public/mocks'; +import { dataPluginMock } from '../../../plugins/data/public/mocks'; +import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks'; +import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks'; -const createSetupContract = (): Setup => { - const setupContract: Setup = undefined; - return setupContract; -}; +const createSetupContract = (): VisualizationsSetup => ({ + createBaseVisualization: jest.fn(), + createReactVisualization: jest.fn(), + registerAlias: jest.fn(), + hideTypes: jest.fn(), +}); + +const createStartContract = (): VisualizationsStart => ({ + get: jest.fn(), + all: jest.fn(), + getAliases: jest.fn(), + savedVisualizationsLoader: {} as any, + showNewVisModal: jest.fn(), + createVis: jest.fn(), + convertFromSerializedVis: jest.fn(), + convertToSerializedVis: jest.fn(), +}); + +const createInstance = async () => { + const plugin = new VisualizationsPlugin({} as PluginInitializerContext); + + const setup = plugin.setup(coreMock.createSetup(), { + data: dataPluginMock.createSetupContract(), + expressions: expressionsPluginMock.createSetupContract(), + embeddable: embeddablePluginMock.createSetupContract(), + usageCollection: usageCollectionPluginMock.createSetupContract(), + }); + const doStart = () => + plugin.start(coreMock.createStart(), { + data: dataPluginMock.createStartContract(), + expressions: expressionsPluginMock.createStartContract(), + uiActions: uiActionsPluginMock.createStartContract(), + }); -const createStartContract = (): Start => { - const startContract: Start = undefined; - return startContract; + return { + plugin, + setup, + doStart, + }; }; -export const expressionsPluginMock = { +export const visualizationsPluginMock = { createSetupContract, createStartContract, + createInstance, }; diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index cceb63122820d..d3e7b759a4416 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -18,23 +18,81 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; -import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public'; +import { TypesService, TypesSetup, TypesStart } from './vis_types'; +import { + setUISettings, + setTypes, + setI18n, + setCapabilities, + setHttp, + setIndexPatterns, + setSavedObjects, + setUsageCollector, + setFilterManager, + setExpressions, + setUiActions, + setSavedVisualizationsLoader, + setTimeFilter, + setAggs, + setChrome, + setOverlays, +} from './services'; +import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeEmbeddableFactory } from './embeddable'; +import { ExpressionsSetup, ExpressionsStart } from '../../../plugins/expressions/public'; +import { EmbeddableSetup } from '../../../plugins/embeddable/public'; +import { visualization as visualizationFunction } from './expressions/visualization_function'; +import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { range as rangeExpressionFunction } from './expression_functions/range'; import { visDimension as visDimensionExpressionFunction } from './expression_functions/vis_dimension'; +import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../plugins/data/public'; +import { UsageCollectionSetup } from '../../../plugins/usage_collection/public'; +import { createSavedVisLoader, SavedVisualizationsLoader } from './saved_visualizations'; +import { SerializedVis, Vis } from './vis'; +import { showNewVisModal } from './wizard'; +import { UiActionsStart } from '../../../plugins/ui_actions/public'; +import { + convertFromSerializedVis, + convertToSerializedVis, +} from './saved_visualizations/_saved_vis'; + +/** + * Interface for this plugin's returned setup/start contracts. + * + * @public + */ + +export type VisualizationsSetup = TypesSetup; + +export interface VisualizationsStart extends TypesStart { + savedVisualizationsLoader: SavedVisualizationsLoader; + createVis: (visType: string, visState?: SerializedVis) => Vis; + convertToSerializedVis: typeof convertToSerializedVis; + convertFromSerializedVis: typeof convertFromSerializedVis; + showNewVisModal: typeof showNewVisModal; +} export interface VisualizationsSetupDeps { expressions: ExpressionsSetup; + embeddable: EmbeddableSetup; + usageCollection: UsageCollectionSetup; + data: DataPublicPluginSetup; } export interface VisualizationsStartDeps { + data: DataPublicPluginStart; expressions: ExpressionsStart; + uiActions: UiActionsStart; } -export type VisualizationsSetup = void; - -export type VisualizationsStart = void; - -export class VisualizationsPublicPlugin +/** + * Visualizations Plugin - public + * + * This plugin's stateful contracts are returned from the `setup` and `start` methods + * below. The interfaces for these contracts are provided above. + * + * @internal + */ +export class VisualizationsPlugin implements Plugin< VisualizationsSetup, @@ -42,18 +100,73 @@ export class VisualizationsPublicPlugin VisualizationsSetupDeps, VisualizationsStartDeps > { + private readonly types: TypesService = new TypesService(); + constructor(initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup, { expressions }: VisualizationsSetupDeps): VisualizationsSetup { + public setup( + core: CoreSetup, + { expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps + ): VisualizationsSetup { + setUISettings(core.uiSettings); + setUsageCollector(usageCollection); + + expressions.registerFunction(visualizationFunction); + expressions.registerRenderer(visualizationRenderer); expressions.registerFunction(rangeExpressionFunction); expressions.registerFunction(visDimensionExpressionFunction); - return undefined; + const embeddableFactory = new VisualizeEmbeddableFactory(); + embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); + + return { + ...this.types.setup(), + }; } - public start(core: CoreStart, { expressions }: VisualizationsStartDeps): VisualizationsStart { - return undefined; + public start( + core: CoreStart, + { data, expressions, uiActions }: VisualizationsStartDeps + ): VisualizationsStart { + const types = this.types.start(); + setI18n(core.i18n); + setTypes(types); + setCapabilities(core.application.capabilities); + setHttp(core.http); + setSavedObjects(core.savedObjects); + setIndexPatterns(data.indexPatterns); + setFilterManager(data.query.filterManager); + setExpressions(expressions); + setUiActions(uiActions); + setTimeFilter(data.query.timefilter.timefilter); + setAggs(data.search.aggs); + setOverlays(core.overlays); + setChrome(core.chrome); + const savedVisualizationsLoader = createSavedVisLoader({ + savedObjectsClient: core.savedObjects.client, + indexPatterns: data.indexPatterns, + chrome: core.chrome, + overlays: core.overlays, + visualizationTypes: types, + }); + setSavedVisualizationsLoader(savedVisualizationsLoader); + + return { + ...types, + showNewVisModal, + /** + * creates new instance of Vis + * @param {IIndexPattern} indexPattern - index pattern to use + * @param {VisState} visState - visualization configuration + */ + createVis: (visType: string, visState?: SerializedVis) => new Vis(visType, visState), + convertToSerializedVis, + convertFromSerializedVis, + savedVisualizationsLoader, + }; } - public stop() {} + public stop() { + this.types.stop(); + } } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts similarity index 94% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts rename to src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts index c9906428ccb31..bc96e08f4b9da 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts +++ b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts @@ -28,17 +28,13 @@ import { createSavedObjectClass, SavedObject, SavedObjectKibanaServices, -} from '../../../../../../../plugins/saved_objects/public'; +} from '../../../../plugins/saved_objects/public'; // @ts-ignore import { updateOldState } from '../legacy/vis_update_state'; import { extractReferences, injectReferences } from './saved_visualization_references'; -import { - IIndexPattern, - ISearchSource, - SearchSource, -} from '../../../../../../../plugins/data/public'; +import { IIndexPattern, ISearchSource, SearchSource } from '../../../../plugins/data/public'; import { ISavedVis, SerializedVis } from '../types'; -import { createSavedSearchesLoader } from '../../../../../../../plugins/discover/public'; +import { createSavedSearchesLoader } from '../../../../plugins/discover/public'; import { getChrome, getOverlays, getIndexPatterns, getSavedObjects } from '../services'; export const convertToSerializedVis = async (savedVis: ISavedVis): Promise => { @@ -159,5 +155,5 @@ export function createSavedVisClass(services: SavedObjectKibanaServices) { } } - return SavedVis; + return SavedVis as new (opts: Record | string) => SavedObject; } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.test.ts b/src/plugins/visualizations/public/saved_visualizations/find_list_items.test.ts similarity index 97% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.test.ts rename to src/plugins/visualizations/public/saved_visualizations/find_list_items.test.ts index d1def09978dbb..4a50590e26251 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.test.ts +++ b/src/plugins/visualizations/public/saved_visualizations/find_list_items.test.ts @@ -18,8 +18,8 @@ */ import { findListItems } from './find_list_items'; -import { coreMock } from '../../../../../../../core/public/mocks'; -import { SavedObjectsClientContract } from '../../../../../../../core/public'; +import { coreMock } from '../../../../core/public/mocks'; +import { SavedObjectsClientContract } from '../../../../core/public'; import { VisTypeAlias } from '../vis_types'; describe('saved_visualizations', () => { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.ts b/src/plugins/visualizations/public/saved_visualizations/find_list_items.ts similarity index 92% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.ts rename to src/plugins/visualizations/public/saved_visualizations/find_list_items.ts index 02db90a762e89..c0203a7441a61 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/find_list_items.ts +++ b/src/plugins/visualizations/public/saved_visualizations/find_list_items.ts @@ -18,11 +18,8 @@ */ import _ from 'lodash'; -import { - SavedObjectAttributes, - SavedObjectsClientContract, -} from '../../../../../../../core/public'; -import { SavedObjectLoader } from '../../../../../../../plugins/saved_objects/public'; +import { SavedObjectAttributes, SavedObjectsClientContract } from '../../../../core/public'; +import { SavedObjectLoader } from '../../../../plugins/saved_objects/public'; import { VisTypeAlias } from '../vis_types'; import { VisualizationsAppExtension } from '../vis_types/vis_type_alias_registry'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/index.ts b/src/plugins/visualizations/public/saved_visualizations/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/index.ts rename to src/plugins/visualizations/public/saved_visualizations/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts rename to src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts similarity index 99% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.ts rename to src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts index b995d340d44d9..a14595524100b 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { SavedObjectAttributes, SavedObjectReference } from '../../../../../../../core/public'; +import { SavedObjectAttributes, SavedObjectReference } from '../../../../core/public'; import { VisSavedObject } from '../types'; export function extractReferences({ diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualizations.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts similarity index 92% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualizations.ts rename to src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts index fc0f77d54059c..e5d0c41712a91 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualizations.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts @@ -19,7 +19,7 @@ import { SavedObjectLoader, SavedObjectKibanaServices, -} from '../../../../../../../plugins/saved_objects/public'; +} from '../../../../plugins/saved_objects/public'; import { findListItems } from './find_list_items'; import { createSavedVisClass } from './_saved_vis'; import { TypesStart } from '../vis_types'; @@ -76,5 +76,9 @@ export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisu } } const SavedVis = createSavedVisClass(services); - return new SavedObjectLoaderVisualize(SavedVis, savedObjectsClient, services.chrome); + return new SavedObjectLoaderVisualize( + SavedVis, + savedObjectsClient, + services.chrome + ) as SavedObjectLoader & { findListItems: (search: string, size: number) => any }; } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts b/src/plugins/visualizations/public/services.ts similarity index 83% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts rename to src/plugins/visualizations/public/services.ts index 23cdeae7d15ff..c4668fa4b0c79 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts +++ b/src/plugins/visualizations/public/services.ts @@ -18,7 +18,6 @@ */ import { - ApplicationStart, Capabilities, ChromeStart, HttpStart, @@ -26,18 +25,18 @@ import { IUiSettingsClient, OverlayStart, SavedObjectsStart, -} from '../../../../../../core/public'; +} from '../../../core/public'; import { TypesStart } from './vis_types'; -import { createGetterSetter } from '../../../../../../plugins/kibana_utils/public'; +import { createGetterSetter } from '../../../plugins/kibana_utils/public'; import { DataPublicPluginStart, FilterManager, IndexPatternsContract, TimefilterContract, -} from '../../../../../../plugins/data/public'; -import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; -import { ExpressionsStart } from '../../../../../../plugins/expressions/public'; -import { UiActionsStart } from '../../../../../../plugins/ui_actions/public'; +} from '../../../plugins/data/public'; +import { UsageCollectionSetup } from '../../../plugins/usage_collection/public'; +import { ExpressionsStart } from '../../../plugins/expressions/public'; +import { UiActionsStart } from '../../../plugins/ui_actions/public'; import { SavedVisualizationsLoader } from './saved_visualizations'; export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); @@ -83,5 +82,3 @@ export const [getAggs, setAggs] = createGetterSetter('Overlays'); export const [getChrome, setChrome] = createGetterSetter('Chrome'); - -export const [getApplication, setApplication] = createGetterSetter('Application'); diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index 6487266956119..54528a33414c3 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -17,6 +17,42 @@ * under the License. */ +import { SavedObject } from '../../../plugins/saved_objects/public'; +import { ISearchSource, AggConfigOptions } from '../../../plugins/data/public'; +import { SerializedVis, Vis, VisParams } from './vis'; + +export { Vis, SerializedVis, VisParams }; + +export interface VisualizationController { + render(visData: any, visParams: any): Promise; + destroy(): void; + isLoaded?(): Promise | void; +} + +export type VisualizationControllerConstructor = new ( + el: HTMLElement, + vis: Vis +) => VisualizationController; + +export interface SavedVisState { + type: string; + params: VisParams; + aggs: AggConfigOptions[]; +} + +export interface ISavedVis { + id?: string; + title: string; + description?: string; + visState: SavedVisState; + searchSource?: ISearchSource; + uiStateJSON?: string; + savedSearchRefName?: string; + savedSearchId?: string; +} + +export interface VisSavedObject extends SavedObject, ISavedVis {} + export interface VisResponseValue { visType: string; visData: object; diff --git a/src/plugins/visualizations/public/vis.test.ts b/src/plugins/visualizations/public/vis.test.ts new file mode 100644 index 0000000000000..fc9327903fc90 --- /dev/null +++ b/src/plugins/visualizations/public/vis.test.ts @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Vis } from './vis'; +// @ts-ignore +import fixturesStubbedLogstashIndexPatternProvider from '../../../fixtures/stubbed_logstash_index_pattern'; + +jest.mock('./services', () => { + class MockVisualizationController { + constructor() {} + + render(): Promise { + return new Promise(resolve => { + resolve(); + }); + } + + destroy() {} + } + + // eslint-disable-next-line + const { BaseVisType } = require('./vis_types/base_vis_type'); + + const visType = new BaseVisType({ + name: 'pie', + title: 'pie', + icon: 'pie-icon', + visualization: MockVisualizationController, + }); + + return { + getTypes: () => ({ get: () => visType }), + getAggs: () => ({ + createAggConfigs: (indexPattern: any, cfg: any) => ({ + aggs: cfg.map((aggConfig: any) => ({ ...aggConfig, toJSON: () => aggConfig })), + }), + }), + }; +}); + +describe('Vis Class', function() { + let vis: Vis; + const stateFixture = { + type: 'pie', + title: 'pie', + data: { + aggs: [ + { type: 'avg' as any, schema: 'metric', params: { field: 'bytes' } }, + { type: 'terms' as any, schema: 'segment', params: { field: 'machine.os' } }, + { type: 'terms' as any, schema: 'segment', params: { field: 'geo.src' } }, + ], + searchSource: { + getField: (name: string) => { + if (name === 'index') { + return fixturesStubbedLogstashIndexPatternProvider(); + } + }, + createCopy: jest.fn(), + }, + }, + params: { isDonut: true }, + }; + + beforeEach(function() { + vis = new Vis('test', stateFixture as any); + }); + + const verifyVis = function(visToVerify: Vis) { + expect(visToVerify).toHaveProperty('data'); + expect(visToVerify.data).toHaveProperty('aggs'); + expect(visToVerify.data.aggs!.aggs).toHaveLength(3); + + expect(visToVerify).toHaveProperty('type'); + + expect(visToVerify).toHaveProperty('params'); + expect(visToVerify.params).toHaveProperty('isDonut', true); + }; + + describe('initialization', function() { + it('should set the state', function() { + verifyVis(vis); + }); + }); + + describe('getState()', function() { + it('should get a state that represents the... er... state', function() { + const state = vis.serialize(); + expect(state).toHaveProperty('type', 'pie'); + + expect(state).toHaveProperty('params'); + expect(state.params).toHaveProperty('isDonut', true); + + expect(state.data).toHaveProperty('aggs'); + expect(state.data.aggs).toHaveLength(3); + }); + }); + + describe('isHierarchical()', function() { + it('should return false for non-hierarchical vis (like histogram)', function() { + expect(vis.isHierarchical()).toBe(false); + }); + + it('should return true for hierarchical vis (like pie)', function() { + vis.type.hierarchicalData = true; + expect(vis.isHierarchical()).toBe(true); + }); + }); +}); diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts b/src/plugins/visualizations/public/vis.ts similarity index 94% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts rename to src/plugins/visualizations/public/vis.ts index 0ba936c9f6567..3cab4faf2a27f 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -28,7 +28,7 @@ */ import { isFunction, defaults, cloneDeep } from 'lodash'; -import { PersistedState } from '../../../../../../../src/plugins/visualizations/public'; +import { PersistedState } from './persisted_state'; // @ts-ignore import { updateVisualizationConfig } from './legacy/vis_update'; import { getTypes, getAggs } from './services'; @@ -38,7 +38,7 @@ import { IndexPattern, ISearchSource, AggConfigOptions, -} from '../../../../../../plugins/data/public'; +} from '../../../plugins/data/public'; export interface SerializedVisData { expression?: string; @@ -49,7 +49,7 @@ export interface SerializedVisData { } export interface SerializedVis { - id: string; + id?: string; title: string; description?: string; type: string; @@ -72,7 +72,7 @@ export interface VisParams { export class Vis { public readonly type: VisType; - public readonly id: string; + public readonly id?: string; public title: string = ''; public description: string = ''; public params: VisParams = {}; @@ -132,8 +132,10 @@ export class Vis { this.data.savedSearchId = state.data.savedSearchId; } if (state.data && state.data.aggs) { - let configStates = state.data.aggs; - configStates = this.initializeDefaultsFromSchemas(configStates, this.type.schemas.all || []); + const configStates = this.initializeDefaultsFromSchemas( + cloneDeep(state.data.aggs), + this.type.schemas.all || [] + ); if (!this.data.indexPattern) { if (state.data.aggs.length) { throw new Error('trying to initialize aggs without index pattern'); diff --git a/src/plugins/ui_actions/public/actions/action_internal.test.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts similarity index 68% rename from src/plugins/ui_actions/public/actions/action_internal.test.ts rename to src/plugins/visualizations/public/vis_types/base_vis_type.test.ts index b14346180c274..ac1242b2a1321 100644 --- a/src/plugins/ui_actions/public/actions/action_internal.test.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts @@ -17,17 +17,19 @@ * under the License. */ -import { ActionDefinition } from './action'; -import { ActionInternal } from './action_internal'; +import { BaseVisType } from './base_vis_type'; -const defaultActionDef: ActionDefinition = { - id: 'test-action', - execute: jest.fn(), -}; - -describe('ActionInternal', () => { - test('can instantiate from action definition', () => { - const action = new ActionInternal(defaultActionDef); - expect(action.id).toBe('test-action'); +describe('BaseVisType', () => { + describe('constructor', () => { + test('should throw if image and icon are missing', () => { + expect(() => { + new BaseVisType({ + name: 'test', + title: 'test', + description: 'test', + visualization: {} as any, + }); + }).toThrow(); + }); }); }); diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts new file mode 100644 index 0000000000000..2464bb72d2695 --- /dev/null +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -0,0 +1,110 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import { VisualizationControllerConstructor } from '../types'; + +export interface BaseVisTypeOptions { + name: string; + title: string; + description?: string; + icon?: string; + image?: string; + stage?: 'experimental' | 'beta' | 'production'; + feedbackMessage?: string; + options?: Record; + visualization: VisualizationControllerConstructor; + visConfig?: Record; + editor?: any; + editorConfig?: Record; + hidden?: boolean; + requestHandler?: string | unknown; + responseHandler?: string | unknown; + hierarchicalData?: boolean | unknown; + setup?: unknown; + useCustomNoDataScreen?: boolean; +} + +export class BaseVisType { + name: string; + title: string; + description: string; + icon?: string; + image?: string; + stage: 'experimental' | 'beta' | 'production'; + feedbackMessage: string; + options: Record; + visualization: VisualizationControllerConstructor; + visConfig: Record; + editor: any; + editorConfig: Record; + hidden: boolean; + requiresSearch: boolean; + requestHandler: string | unknown; + responseHandler: string | unknown; + hierarchicalData: boolean | unknown; + setup?: unknown; + useCustomNoDataScreen: boolean; + + constructor(opts: BaseVisTypeOptions) { + if (!opts.icon && !opts.image) { + throw new Error('vis_type must define its icon or image'); + } + + const defaultOptions = { + // controls the visualize editor + showTimePicker: true, + showQueryBar: true, + showFilterBar: true, + showIndexSelection: true, + hierarchicalData: false, // we should get rid of this i guess ? + }; + + this.name = opts.name; + this.description = opts.description || ''; + this.title = opts.title; + this.icon = opts.icon; + this.image = opts.image; + this.visualization = opts.visualization; + this.visConfig = _.defaultsDeep({}, opts.visConfig, { defaults: {} }); + this.editor = opts.editor; + this.editorConfig = _.defaultsDeep({}, opts.editorConfig, { collections: {} }); + this.options = _.defaultsDeep({}, opts.options, defaultOptions); + this.stage = opts.stage || 'production'; + this.feedbackMessage = opts.feedbackMessage || ''; + this.hidden = opts.hidden || false; + this.requestHandler = opts.requestHandler || 'courier'; + this.responseHandler = opts.responseHandler || 'none'; + this.setup = opts.setup; + this.requiresSearch = this.requestHandler !== 'none'; + this.hierarchicalData = opts.hierarchicalData || false; + this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false; + } + + shouldMarkAsExperimentalInUI() { + return this.stage === 'experimental'; + } + + public get schemas() { + if (this.editorConfig && this.editorConfig.schemas) { + return this.editorConfig.schemas; + } + return []; + } +} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/index.ts b/src/plugins/visualizations/public/vis_types/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/index.ts rename to src/plugins/visualizations/public/vis_types/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/react_vis_type.js b/src/plugins/visualizations/public/vis_types/react_vis_controller.tsx similarity index 70% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/react_vis_type.js rename to src/plugins/visualizations/public/vis_types/react_vis_controller.tsx index e8ee7bc6e5445..643e6ffcb730b 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/react_vis_type.js +++ b/src/plugins/visualizations/public/vis_types/react_vis_controller.tsx @@ -19,21 +19,26 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { getUISettings, getI18n } from '../services'; -import { BaseVisType } from './base_vis_type'; +import { Vis, VisualizationController } from '../types'; +import { getI18n, getUISettings } from '../services'; -class ReactVisController { - constructor(element, vis) { +export class ReactVisController implements VisualizationController { + private el: HTMLElement; + private vis: Vis; + + constructor(element: HTMLElement, vis: Vis) { this.el = element; this.vis = vis; } - render(visData, visParams, updateStatus) { - this.visData = visData; - + public render(visData: any, visParams: any): Promise { const I18nContext = getI18n().Context; - return new Promise(resolve => { + return new Promise((resolve, reject) => { + if (!this.vis.type || !this.vis.type.visConfig || !this.vis.type.visConfig.component) { + reject('Missing component for ReactVisType'); + } + const Component = this.vis.type.visConfig.component; const config = getUISettings(); render( @@ -44,7 +49,6 @@ class ReactVisController { visData={visData} visParams={visParams} renderComplete={resolve} - updateStatus={updateStatus} /> , this.el @@ -52,20 +56,7 @@ class ReactVisController { }); } - destroy() { + public destroy() { unmountComponentAtNode(this.el); } } - -export class ReactVisType extends BaseVisType { - constructor(opts) { - super({ - ...opts, - visualization: ReactVisController, - }); - - if (!this.visConfig.component) { - throw new Error('Missing component for ReactVisType'); - } - } -} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/react_vis_type.js b/src/plugins/visualizations/public/vis_types/react_vis_type.test.ts similarity index 55% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/react_vis_type.js rename to src/plugins/visualizations/public/vis_types/react_vis_type.test.ts index 2474a58870424..134106bb3d42a 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/__tests__/vis_types/react_vis_type.js +++ b/src/plugins/visualizations/public/vis_types/react_vis_type.test.ts @@ -17,57 +17,30 @@ * under the License. */ -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { ReactVisType } from '../../../vis_types/react_vis_type'; +import { cloneDeep } from 'lodash'; +import { ReactVisType } from './react_vis_type'; -describe('React Vis Type', function() { +describe('React Vis Type', () => { const visConfig = { name: 'test', title: 'test', description: 'test', icon: 'test', visConfig: { component: 'test' }, - type: { visConfig: { component: 'test' } }, }; - beforeEach(ngMock.module('kibana')); - describe('initialization', () => { it('should throw if component is not set', () => { expect(() => { - new ReactVisType({}); - }).to.throwError(); + const missingConfig = cloneDeep(visConfig); + delete missingConfig.visConfig.component; + new ReactVisType(missingConfig); + }).toThrow(); }); it('creates react controller', () => { const visType = new ReactVisType(visConfig); - expect(visType.visualization).to.not.be.an('undefined'); - }); - }); - - describe('controller render method', () => { - let vis; - beforeEach(() => { - const visType = new ReactVisType(visConfig); - const Vis = visType.visualization; - - vis = new Vis(window.document.body, {}); - }); - - it('rejects if data is not provided', () => { - vis - .render() - .then(() => { - expect('promise was not rejected').to.equal(false); - }) - .catch(() => {}); - }); - - it('renders the component', () => { - expect(() => { - vis.render({}); - }).to.not.throwError(); + expect(visType.visualization).not.toBeUndefined(); }); }); }); diff --git a/src/plugins/visualizations/public/vis_types/react_vis_type.ts b/src/plugins/visualizations/public/vis_types/react_vis_type.ts new file mode 100644 index 0000000000000..68979abe52a3c --- /dev/null +++ b/src/plugins/visualizations/public/vis_types/react_vis_type.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BaseVisType, BaseVisTypeOptions } from './base_vis_type'; +import { ReactVisController } from './react_vis_controller'; + +export class ReactVisType extends BaseVisType { + constructor(opts: Omit) { + super({ + ...opts, + visualization: ReactVisController, + }); + + if (!this.visConfig.component) { + throw new Error('Missing component for ReactVisType'); + } + } +} diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/types_service.ts b/src/plugins/visualizations/public/vis_types/types_service.ts similarity index 98% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/types_service.ts rename to src/plugins/visualizations/public/vis_types/types_service.ts index 6bcaa9a3e1dac..321f96180fd68 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/types_service.ts +++ b/src/plugins/visualizations/public/vis_types/types_service.ts @@ -30,8 +30,8 @@ export interface VisType { description?: string; visualization: any; isAccessible?: boolean; - requestHandler: string; - responseHandler: string; + requestHandler: string | unknown; + responseHandler: string | unknown; icon?: IconType; image?: string; stage: 'experimental' | 'beta' | 'production'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts similarity index 98% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/vis_type_alias_registry.ts rename to src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index 12b02ee9e6b32..040fa22352a3a 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -17,7 +17,7 @@ * under the License. */ -interface VisualizationListItem { +export interface VisualizationListItem { editUrl: string; icon: string; id: string; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap rename to src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/_dialog.scss b/src/plugins/visualizations/public/wizard/_dialog.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/_dialog.scss rename to src/plugins/visualizations/public/wizard/_dialog.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/_index.scss b/src/plugins/visualizations/public/wizard/_index.scss similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/_index.scss rename to src/plugins/visualizations/public/wizard/_index.scss diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/index.ts b/src/plugins/visualizations/public/wizard/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/index.ts rename to src/plugins/visualizations/public/wizard/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx similarity index 99% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx rename to src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx index 2712019e42609..5637aeafc6f14 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { TypesStart, VisType } from '../vis_types'; import { NewVisModal } from './new_vis_modal'; -import { SavedObjectsStart } from '../../../../../../../core/public'; +import { SavedObjectsStart } from '../../../../core/public'; describe('NewVisModal', () => { const { location } = window; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx similarity index 97% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx rename to src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 7c10001eddb50..448077819bb8d 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -23,11 +23,11 @@ import { EuiModal, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE, UiStatsMetricType } from '@kbn/analytics'; -import { IUiSettingsClient, SavedObjectsStart } from '../../../../../../../core/public'; +import { IUiSettingsClient, SavedObjectsStart } from '../../../../core/public'; import { SearchSelection } from './search_selection'; import { TypeSelection } from './type_selection'; import { TypesStart, VisType, VisTypeAlias } from '../vis_types'; -import { UsageCollectionSetup } from '../../../../../../../plugins/usage_collection/public'; +import { UsageCollectionSetup } from '../../../../plugins/usage_collection/public'; interface TypeSelectionProps { isOpen: boolean; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/search_selection/index.ts b/src/plugins/visualizations/public/wizard/search_selection/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/search_selection/index.ts rename to src/plugins/visualizations/public/wizard/search_selection/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/search_selection/search_selection.tsx b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx similarity index 96% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/search_selection/search_selection.tsx rename to src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx index f8eb191dd5f92..c9fb592d1f936 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/search_selection/search_selection.tsx +++ b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx @@ -21,9 +21,9 @@ import { EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui' import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; -import { IUiSettingsClient, SavedObjectsStart } from '../../../../../../../../core/public'; +import { IUiSettingsClient, SavedObjectsStart } from '../../../../../core/public'; -import { SavedObjectFinderUi } from '../../../../../../../../plugins/saved_objects/public'; +import { SavedObjectFinderUi } from '../../../../../plugins/saved_objects/public'; import { VisType } from '../../vis_types'; interface SearchSelectionProps { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/show_new_vis.tsx b/src/plugins/visualizations/public/wizard/show_new_vis.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/show_new_vis.tsx rename to src/plugins/visualizations/public/wizard/show_new_vis.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/index.ts b/src/plugins/visualizations/public/wizard/type_selection/index.ts similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/index.ts rename to src/plugins/visualizations/public/wizard/type_selection/index.ts diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/new_vis_help.test.tsx b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/new_vis_help.test.tsx rename to src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/new_vis_help.tsx b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/new_vis_help.tsx rename to src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/type_selection.tsx b/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx similarity index 98% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/type_selection.tsx rename to src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx index 81dcecfee2613..bb5037545cc82 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/type_selection.tsx +++ b/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx @@ -35,8 +35,8 @@ import { EuiTitle, } from '@elastic/eui'; -import { memoizeLast } from '../../../../../../visualizations/public/np_ready/public/legacy/memoize'; -import { VisTypeAlias } from '../../../../../../visualizations/public'; +import { memoizeLast } from '../../legacy/memoize'; +import { VisTypeAlias } from '../../vis_types/vis_type_alias_registry'; import { NewVisHelp } from './new_vis_help'; import { VisHelpText } from './vis_help_text'; import { VisTypeIcon } from './vis_type_icon'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/vis_help_text.tsx b/src/plugins/visualizations/public/wizard/type_selection/vis_help_text.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/vis_help_text.tsx rename to src/plugins/visualizations/public/wizard/type_selection/vis_help_text.tsx diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/vis_type_icon.tsx b/src/plugins/visualizations/public/wizard/type_selection/vis_type_icon.tsx similarity index 100% rename from src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/type_selection/vis_type_icon.tsx rename to src/plugins/visualizations/public/wizard/type_selection/vis_type_icon.tsx diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js index 57e9120773f33..c5bfc847d0041 100644 --- a/test/api_integration/apis/index.js +++ b/test/api_integration/apis/index.js @@ -25,7 +25,7 @@ export default function({ loadTestFile }) { loadTestFile(require.resolve('./home')); loadTestFile(require.resolve('./index_patterns')); loadTestFile(require.resolve('./kql_telemetry')); - loadTestFile(require.resolve('./management')); + loadTestFile(require.resolve('./saved_objects_management')); loadTestFile(require.resolve('./saved_objects')); loadTestFile(require.resolve('./scripts')); loadTestFile(require.resolve('./shorten')); diff --git a/test/api_integration/apis/management/saved_objects/relationships.js b/test/api_integration/apis/management/saved_objects/relationships.js deleted file mode 100644 index d202094e6d6f8..0000000000000 --- a/test/api_integration/apis/management/saved_objects/relationships.js +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -const Joi = require('joi'); - -export default function({ getService }) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - const GENERIC_RESPONSE_SCHEMA = Joi.array().items( - Joi.object().keys({ - id: Joi.string() - .uuid() - .required(), - type: Joi.string().required(), - relationship: Joi.string() - .valid('parent', 'child') - .required(), - meta: Joi.object() - .keys({ - title: Joi.string().required(), - icon: Joi.string().required(), - editUrl: Joi.string().required(), - inAppUrl: Joi.object() - .keys({ - path: Joi.string().required(), - uiCapabilitiesPath: Joi.string().required(), - }) - .required(), - }) - .required(), - }) - ); - - describe('relationships', () => { - before(() => esArchiver.load('management/saved_objects')); - after(() => esArchiver.unload('management/saved_objects')); - - const baseApiUrl = `/api/kibana/management/saved_objects/relationships`; - const coerceToArray = itemOrItems => [].concat(itemOrItems); - const getSavedObjectTypesQuery = types => - coerceToArray(types) - .map(type => `savedObjectTypes=${type}`) - .join('&'); - const defaultQuery = getSavedObjectTypesQuery([ - 'visualization', - 'index-pattern', - 'search', - 'dashboard', - ]); - - describe('searches', () => { - it('should validate search response schema', async () => { - await supertest - .get(`${baseApiUrl}/search/960372e0-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - const validationResult = Joi.validate(resp.body, GENERIC_RESPONSE_SCHEMA); - expect(validationResult.error).to.be(null); - }); - }); - - it('should work for searches', async () => { - await supertest - .get(`${baseApiUrl}/search/960372e0-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '8963ca30-3224-11e8-a572-ffca06da1357', - type: 'index-pattern', - relationship: 'child', - meta: { - title: 'saved_objects*', - icon: 'indexPatternApp', - editUrl: '/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: - '/app/kibana#/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'management.kibana.index_patterns', - }, - }, - }, - { - id: 'a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - relationship: 'parent', - meta: { - title: 'VisualizationFromSavedSearch', - icon: 'visualizeApp', - editUrl: - '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - }, - ]); - }); - }); - - it('should filter based on savedObjectTypes', async () => { - await supertest - .get( - `${baseApiUrl}/search/960372e0-3224-11e8-a572-ffca06da1357?${getSavedObjectTypesQuery( - 'visualization' - )}` - ) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '8963ca30-3224-11e8-a572-ffca06da1357', - type: 'index-pattern', - meta: { - icon: 'indexPatternApp', - title: 'saved_objects*', - editUrl: '/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: - '/app/kibana#/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'management.kibana.index_patterns', - }, - }, - relationship: 'child', - }, - { - id: 'a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - meta: { - icon: 'visualizeApp', - title: 'VisualizationFromSavedSearch', - editUrl: - '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - relationship: 'parent', - }, - ]); - }); - }); - - //TODO: https://github.com/elastic/kibana/issues/19713 causes this test to fail. - it.skip('should return 404 if search finds no results', async () => { - await supertest - .get(`${baseApiUrl}/search/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx${defaultQuery}`) - .expect(404); - }); - }); - - describe('dashboards', () => { - it('should validate dashboard response schema', async () => { - await supertest - .get(`${baseApiUrl}/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - const validationResult = Joi.validate(resp.body, GENERIC_RESPONSE_SCHEMA); - expect(validationResult.error).to.be(null); - }); - }); - - it('should work for dashboards', async () => { - await supertest - .get(`${baseApiUrl}/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: 'add810b0-3224-11e8-a572-ffca06da1357', - type: 'visualization', - relationship: 'child', - meta: { - icon: 'visualizeApp', - title: 'Visualization', - editUrl: - '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - }, - { - id: 'a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - relationship: 'child', - meta: { - icon: 'visualizeApp', - title: 'VisualizationFromSavedSearch', - editUrl: - '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - }, - ]); - }); - }); - - it('should filter based on savedObjectTypes', async () => { - await supertest - .get( - `${baseApiUrl}/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357?${getSavedObjectTypesQuery( - 'search' - )}` - ) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: 'add810b0-3224-11e8-a572-ffca06da1357', - type: 'visualization', - meta: { - icon: 'visualizeApp', - title: 'Visualization', - editUrl: - '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - relationship: 'child', - }, - { - id: 'a42c0580-3224-11e8-a572-ffca06da1357', - type: 'visualization', - meta: { - icon: 'visualizeApp', - title: 'VisualizationFromSavedSearch', - editUrl: - '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - relationship: 'child', - }, - ]); - }); - }); - - //TODO: https://github.com/elastic/kibana/issues/19713 causes this test to fail. - it.skip('should return 404 if dashboard finds no results', async () => { - await supertest - .get(`${baseApiUrl}/dashboard/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx${defaultQuery}`) - .expect(404); - }); - }); - - describe('visualizations', () => { - it('should validate visualization response schema', async () => { - await supertest - .get(`${baseApiUrl}/visualization/a42c0580-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - const validationResult = Joi.validate(resp.body, GENERIC_RESPONSE_SCHEMA); - expect(validationResult.error).to.be(null); - }); - }); - - it('should work for visualizations', async () => { - await supertest - .get(`${baseApiUrl}/visualization/a42c0580-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - relationship: 'child', - meta: { - icon: 'discoverApp', - title: 'OneRecord', - editUrl: - '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'discover.show', - }, - }, - }, - { - id: 'b70c7ae0-3224-11e8-a572-ffca06da1357', - type: 'dashboard', - relationship: 'parent', - meta: { - icon: 'dashboardApp', - title: 'Dashboard', - editUrl: - '/management/kibana/objects/savedDashboards/b70c7ae0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'dashboard.show', - }, - }, - }, - ]); - }); - }); - - it('should filter based on savedObjectTypes', async () => { - await supertest - .get( - `${baseApiUrl}/visualization/a42c0580-3224-11e8-a572-ffca06da1357?${getSavedObjectTypesQuery( - 'search' - )}` - ) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - meta: { - icon: 'discoverApp', - title: 'OneRecord', - editUrl: - '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'discover.show', - }, - }, - relationship: 'child', - }, - ]); - }); - }); - - it('should return 404 if visualizations finds no results', async () => { - await supertest - .get(`${baseApiUrl}/visualization/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx?${defaultQuery}`) - .expect(404); - }); - }); - - describe('index patterns', () => { - it('should validate visualization response schema', async () => { - await supertest - .get(`${baseApiUrl}/index-pattern/8963ca30-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - const validationResult = Joi.validate(resp.body, GENERIC_RESPONSE_SCHEMA); - expect(validationResult.error).to.be(null); - }); - }); - - it('should work for index patterns', async () => { - await supertest - .get(`${baseApiUrl}/index-pattern/8963ca30-3224-11e8-a572-ffca06da1357?${defaultQuery}`) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - relationship: 'parent', - meta: { - icon: 'discoverApp', - title: 'OneRecord', - editUrl: - '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'discover.show', - }, - }, - }, - { - id: 'add810b0-3224-11e8-a572-ffca06da1357', - type: 'visualization', - relationship: 'parent', - meta: { - icon: 'visualizeApp', - title: 'Visualization', - editUrl: - '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'visualize.show', - }, - }, - }, - ]); - }); - }); - - it('should filter based on savedObjectTypes', async () => { - await supertest - .get( - `${baseApiUrl}/index-pattern/8963ca30-3224-11e8-a572-ffca06da1357?${getSavedObjectTypesQuery( - 'search' - )}` - ) - .expect(200) - .then(resp => { - expect(resp.body).to.eql([ - { - id: '960372e0-3224-11e8-a572-ffca06da1357', - type: 'search', - meta: { - icon: 'discoverApp', - title: 'OneRecord', - editUrl: - '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', - inAppUrl: { - path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'discover.show', - }, - }, - relationship: 'parent', - }, - ]); - }); - }); - - it('should return 404 if index pattern finds no results', async () => { - await supertest - .get(`${baseApiUrl}/index-pattern/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx?${defaultQuery}`) - .expect(404); - }); - }); - }); -} diff --git a/test/api_integration/apis/management/saved_objects/find.js b/test/api_integration/apis/saved_objects_management/find.ts similarity index 89% rename from test/api_integration/apis/management/saved_objects/find.js rename to test/api_integration/apis/saved_objects_management/find.ts index 89e158671c3ca..9b3eda4c0664b 100644 --- a/test/api_integration/apis/management/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -18,8 +18,10 @@ */ import expect from '@kbn/expect'; +import { Response } from 'supertest'; +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const es = getService('legacyEs'); const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -33,7 +35,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=visualization&fields=title') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 1, per_page: 20, @@ -75,7 +77,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=wigwags') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 1, per_page: 20, @@ -92,7 +94,7 @@ export default function({ getService }) { '/api/kibana/management/saved_objects/_find?type=visualization&page=100&perPage=100' ) .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 100, per_page: 100, @@ -107,15 +109,11 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=url&searchFields=a') .expect(400) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: '"searchFields" is not allowed', - validation: { - source: 'query', - keys: ['searchFields'], - }, + message: '[request query.searchFields]: definition for this key is missing', }); })); }); @@ -135,7 +133,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=visualization') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 1, per_page: 20, @@ -149,7 +147,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=wigwags') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 1, per_page: 20, @@ -164,15 +162,12 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find') .expect(400) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ error: 'Bad Request', - message: 'child "type" fails because ["type" is required]', + message: + '[request query.type]: expected at least one defined value but got [undefined]', statusCode: 400, - validation: { - keys: ['type'], - source: 'query', - }, }); })); }); @@ -184,7 +179,7 @@ export default function({ getService }) { '/api/kibana/management/saved_objects/_find?type=visualization&page=100&perPage=100' ) .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ page: 100, per_page: 100, @@ -199,29 +194,25 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=url&searchFields=a') .expect(400) - .then(resp => { + .then((resp: Response) => { expect(resp.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: '"searchFields" is not allowed', - validation: { - source: 'query', - keys: ['searchFields'], - }, + message: '[request query.searchFields]: definition for this key is missing', }); })); }); }); describe('meta attributes injected properly', () => { - before(() => esArchiver.load('management/saved_objects')); - after(() => esArchiver.unload('management/saved_objects')); + before(() => esArchiver.load('management/saved_objects/search')); + after(() => esArchiver.unload('management/saved_objects/search')); it('should inject meta attributes for searches', async () => await supertest .get('/api/kibana/management/saved_objects/_find?type=search') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body.saved_objects).to.have.length(1); expect(resp.body.saved_objects[0].meta).to.eql({ icon: 'discoverApp', @@ -239,7 +230,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=dashboard') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body.saved_objects).to.have.length(1); expect(resp.body.saved_objects[0].meta).to.eql({ icon: 'dashboardApp', @@ -257,7 +248,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=visualization') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body.saved_objects).to.have.length(2); expect(resp.body.saved_objects[0].meta).to.eql({ icon: 'visualizeApp', @@ -285,7 +276,7 @@ export default function({ getService }) { await supertest .get('/api/kibana/management/saved_objects/_find?type=index-pattern') .expect(200) - .then(resp => { + .then((resp: Response) => { expect(resp.body.saved_objects).to.have.length(1); expect(resp.body.saved_objects[0].meta).to.eql({ icon: 'indexPatternApp', diff --git a/test/api_integration/apis/management/saved_objects/index.js b/test/api_integration/apis/saved_objects_management/index.ts similarity index 79% rename from test/api_integration/apis/management/saved_objects/index.js rename to test/api_integration/apis/saved_objects_management/index.ts index 01fab4a3c74b1..5895940c4bbef 100644 --- a/test/api_integration/apis/management/saved_objects/index.js +++ b/test/api_integration/apis/saved_objects_management/index.ts @@ -17,9 +17,12 @@ * under the License. */ -export default function({ loadTestFile }) { - describe('saved_objects', () => { +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ loadTestFile }: FtrProviderContext) { + describe('saved objects management apis', () => { loadTestFile(require.resolve('./find')); loadTestFile(require.resolve('./relationships')); + loadTestFile(require.resolve('./scroll_count')); }); } diff --git a/test/api_integration/apis/saved_objects_management/relationships.ts b/test/api_integration/apis/saved_objects_management/relationships.ts new file mode 100644 index 0000000000000..78a437ab56cf7 --- /dev/null +++ b/test/api_integration/apis/saved_objects_management/relationships.ts @@ -0,0 +1,423 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { schema } from '@kbn/config-schema'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + const responseSchema = schema.arrayOf( + schema.object({ + id: schema.string(), + type: schema.string(), + relationship: schema.oneOf([schema.literal('parent'), schema.literal('child')]), + meta: schema.object({ + title: schema.string(), + icon: schema.string(), + editUrl: schema.string(), + inAppUrl: schema.object({ + path: schema.string(), + uiCapabilitiesPath: schema.string(), + }), + }), + }) + ); + + describe('relationships', () => { + before(async () => { + await esArchiver.load('management/saved_objects/relationships'); + }); + after(async () => { + await esArchiver.unload('management/saved_objects/relationships'); + }); + + const baseApiUrl = `/api/kibana/management/saved_objects/relationships`; + const defaultTypes = ['visualization', 'index-pattern', 'search', 'dashboard']; + + const relationshipsUrl = (type: string, id: string, types: string[] = defaultTypes) => { + const typesQuery = types.map(t => `savedObjectTypes=${t}`).join('&'); + return `${baseApiUrl}/${type}/${id}?${typesQuery}`; + }; + + describe('searches', () => { + it('should validate search response schema', async () => { + const resp = await supertest + .get(relationshipsUrl('search', '960372e0-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(() => { + responseSchema.validate(resp.body); + }).not.to.throwError(); + }); + + it('should work for searches', async () => { + const resp = await supertest + .get(relationshipsUrl('search', '960372e0-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '8963ca30-3224-11e8-a572-ffca06da1357', + type: 'index-pattern', + relationship: 'child', + meta: { + title: 'saved_objects*', + icon: 'indexPatternApp', + editUrl: '/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: + '/app/kibana#/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'management.kibana.index_patterns', + }, + }, + }, + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + type: 'visualization', + relationship: 'parent', + meta: { + title: 'VisualizationFromSavedSearch', + icon: 'visualizeApp', + editUrl: + '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + }, + ]); + }); + + it('should filter based on savedObjectTypes', async () => { + const resp = await supertest + .get( + relationshipsUrl('search', '960372e0-3224-11e8-a572-ffca06da1357', ['visualization']) + ) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '8963ca30-3224-11e8-a572-ffca06da1357', + type: 'index-pattern', + meta: { + icon: 'indexPatternApp', + title: 'saved_objects*', + editUrl: '/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: + '/app/kibana#/management/kibana/index_patterns/8963ca30-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'management.kibana.index_patterns', + }, + }, + relationship: 'child', + }, + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + type: 'visualization', + meta: { + icon: 'visualizeApp', + title: 'VisualizationFromSavedSearch', + editUrl: + '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + relationship: 'parent', + }, + ]); + }); + + // TODO: https://github.com/elastic/kibana/issues/19713 causes this test to fail. + it.skip('should return 404 if search finds no results', async () => { + await supertest + .get(relationshipsUrl('search', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')) + .expect(404); + }); + }); + + describe('dashboards', () => { + it('should validate dashboard response schema', async () => { + const resp = await supertest + .get(relationshipsUrl('dashboard', 'b70c7ae0-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(() => { + responseSchema.validate(resp.body); + }).not.to.throwError(); + }); + + it('should work for dashboards', async () => { + const resp = await supertest + .get(relationshipsUrl('dashboard', 'b70c7ae0-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(resp.body).to.eql([ + { + id: 'add810b0-3224-11e8-a572-ffca06da1357', + type: 'visualization', + relationship: 'child', + meta: { + icon: 'visualizeApp', + title: 'Visualization', + editUrl: + '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + }, + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + type: 'visualization', + relationship: 'child', + meta: { + icon: 'visualizeApp', + title: 'VisualizationFromSavedSearch', + editUrl: + '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + }, + ]); + }); + + it('should filter based on savedObjectTypes', async () => { + const resp = await supertest + .get(relationshipsUrl('dashboard', 'b70c7ae0-3224-11e8-a572-ffca06da1357', ['search'])) + .expect(200); + + expect(resp.body).to.eql([ + { + id: 'add810b0-3224-11e8-a572-ffca06da1357', + type: 'visualization', + meta: { + icon: 'visualizeApp', + title: 'Visualization', + editUrl: + '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + relationship: 'child', + }, + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + type: 'visualization', + meta: { + icon: 'visualizeApp', + title: 'VisualizationFromSavedSearch', + editUrl: + '/management/kibana/objects/savedVisualizations/a42c0580-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/a42c0580-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + relationship: 'child', + }, + ]); + }); + + // TODO: https://github.com/elastic/kibana/issues/19713 causes this test to fail. + it.skip('should return 404 if dashboard finds no results', async () => { + await supertest + .get(relationshipsUrl('dashboard', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')) + .expect(404); + }); + }); + + describe('visualizations', () => { + it('should validate visualization response schema', async () => { + const resp = await supertest + .get(relationshipsUrl('visualization', 'a42c0580-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(() => { + responseSchema.validate(resp.body); + }).not.to.throwError(); + }); + + it('should work for visualizations', async () => { + const resp = await supertest + .get(relationshipsUrl('visualization', 'a42c0580-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '960372e0-3224-11e8-a572-ffca06da1357', + type: 'search', + relationship: 'child', + meta: { + icon: 'discoverApp', + title: 'OneRecord', + editUrl: + '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'discover.show', + }, + }, + }, + { + id: 'b70c7ae0-3224-11e8-a572-ffca06da1357', + type: 'dashboard', + relationship: 'parent', + meta: { + icon: 'dashboardApp', + title: 'Dashboard', + editUrl: + '/management/kibana/objects/savedDashboards/b70c7ae0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'dashboard.show', + }, + }, + }, + ]); + }); + + it('should filter based on savedObjectTypes', async () => { + const resp = await supertest + .get( + relationshipsUrl('visualization', 'a42c0580-3224-11e8-a572-ffca06da1357', ['search']) + ) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '960372e0-3224-11e8-a572-ffca06da1357', + type: 'search', + meta: { + icon: 'discoverApp', + title: 'OneRecord', + editUrl: + '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'discover.show', + }, + }, + relationship: 'child', + }, + ]); + }); + + it('should return 404 if visualizations finds no results', async () => { + await supertest + .get(relationshipsUrl('visualization', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')) + .expect(404); + }); + }); + + describe('index patterns', () => { + it('should validate visualization response schema', async () => { + const resp = await supertest + .get(relationshipsUrl('index-pattern', '8963ca30-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(() => { + responseSchema.validate(resp.body); + }).not.to.throwError(); + }); + + it('should work for index patterns', async () => { + const resp = await supertest + .get(relationshipsUrl('index-pattern', '8963ca30-3224-11e8-a572-ffca06da1357')) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '960372e0-3224-11e8-a572-ffca06da1357', + type: 'search', + relationship: 'parent', + meta: { + icon: 'discoverApp', + title: 'OneRecord', + editUrl: + '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'discover.show', + }, + }, + }, + { + id: 'add810b0-3224-11e8-a572-ffca06da1357', + type: 'visualization', + relationship: 'parent', + meta: { + icon: 'visualizeApp', + title: 'Visualization', + editUrl: + '/management/kibana/objects/savedVisualizations/add810b0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/visualize/edit/add810b0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'visualize.show', + }, + }, + }, + ]); + }); + + it('should filter based on savedObjectTypes', async () => { + const resp = await supertest + .get( + relationshipsUrl('index-pattern', '8963ca30-3224-11e8-a572-ffca06da1357', ['search']) + ) + .expect(200); + + expect(resp.body).to.eql([ + { + id: '960372e0-3224-11e8-a572-ffca06da1357', + type: 'search', + meta: { + icon: 'discoverApp', + title: 'OneRecord', + editUrl: + '/management/kibana/objects/savedSearches/960372e0-3224-11e8-a572-ffca06da1357', + inAppUrl: { + path: '/app/kibana#/discover/960372e0-3224-11e8-a572-ffca06da1357', + uiCapabilitiesPath: 'discover.show', + }, + }, + relationship: 'parent', + }, + ]); + }); + + it('should return 404 if index pattern finds no results', async () => { + await supertest + .get(relationshipsUrl('index-pattern', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')) + .expect(404); + }); + }); + }); +} diff --git a/test/api_integration/apis/saved_objects_management/scroll_count.ts b/test/api_integration/apis/saved_objects_management/scroll_count.ts new file mode 100644 index 0000000000000..3c29d45244dec --- /dev/null +++ b/test/api_integration/apis/saved_objects_management/scroll_count.ts @@ -0,0 +1,102 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SuperTest, Test } from 'supertest'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const apiUrl = '/api/kibana/management/saved_objects/scroll/counts'; +const defaultTypes = ['visualization', 'index-pattern', 'search', 'dashboard']; + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest') as SuperTest; + const esArchiver = getService('esArchiver'); + + describe('scroll_count', () => { + before(async () => { + await esArchiver.load('management/saved_objects/scroll_count'); + }); + after(async () => { + await esArchiver.unload('management/saved_objects/scroll_count'); + }); + + it('returns the count for each included types', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: defaultTypes, + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 2, + 'index-pattern': 1, + search: 1, + visualization: 2, + }); + }); + + it('only returns count for types to include', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: ['dashboard', 'search'], + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 2, + search: 1, + }); + }); + + it('filters on title when `searchString` is provided', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: defaultTypes, + searchString: 'Amazing', + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 1, + visualization: 1, + 'index-pattern': 0, + search: 0, + }); + }); + + it('includes all requested types even when none match the search', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: ['dashboard', 'search', 'visualization'], + searchString: 'nothing-will-match', + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 0, + visualization: 0, + search: 0, + }); + }); + }); +} diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/relationships/data.json.gz similarity index 100% rename from test/api_integration/fixtures/es_archiver/management/saved_objects/data.json.gz rename to test/api_integration/fixtures/es_archiver/management/saved_objects/relationships/data.json.gz diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/relationships/mappings.json similarity index 100% rename from test/api_integration/fixtures/es_archiver/management/saved_objects/mappings.json rename to test/api_integration/fixtures/es_archiver/management/saved_objects/relationships/mappings.json diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz new file mode 100644 index 0000000000000..1c327e7e0769b Binary files /dev/null and b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/data.json.gz differ diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json new file mode 100644 index 0000000000000..8270c573e4c1e --- /dev/null +++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count/mappings.json @@ -0,0 +1,213 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "telemetry:optIn": { + "type": "boolean" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + } + } +} diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz new file mode 100644 index 0000000000000..0834567abb66b Binary files /dev/null and b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/data.json.gz differ diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json new file mode 100644 index 0000000000000..c670508247b1a --- /dev/null +++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/search/mappings.json @@ -0,0 +1,283 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "telemetry:optIn": { + "type": "boolean" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "graph-workspace": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "numLinks": { + "type": "integer" + }, + "numVertices": { + "type": "integer" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "wsState": { + "type": "text" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test/api_integration/services/supertest.js b/test/api_integration/services/supertest.ts similarity index 83% rename from test/api_integration/services/supertest.js rename to test/api_integration/services/supertest.ts index b53b4ae0ef32f..d5505c080468a 100644 --- a/test/api_integration/services/supertest.js +++ b/test/api_integration/services/supertest.ts @@ -16,18 +16,18 @@ * specific language governing permissions and limitations * under the License. */ - +import { FtrProviderContext } from 'test/functional/ftr_provider_context'; import { format as formatUrl } from 'url'; import supertestAsPromised from 'supertest-as-promised'; -export function KibanaSupertestProvider({ getService }) { +export function KibanaSupertestProvider({ getService }: FtrProviderContext) { const config = getService('config'); const kibanaServerUrl = formatUrl(config.get('servers.kibana')); return supertestAsPromised(kibanaServerUrl); } -export function ElasticsearchSupertestProvider({ getService }) { +export function ElasticsearchSupertestProvider({ getService }: FtrProviderContext) { const config = getService('config'); const elasticSearchServerUrl = formatUrl(config.get('servers.elasticsearch')); return supertestAsPromised(elasticSearchServerUrl); diff --git a/test/common/fixtures/plugins/newsfeed/newsfeed_simulation.ts b/test/common/fixtures/plugins/newsfeed/newsfeed_simulation.ts index 4bf92868b0eca..5aa44b48f9d59 100644 --- a/test/common/fixtures/plugins/newsfeed/newsfeed_simulation.ts +++ b/test/common/fixtures/plugins/newsfeed/newsfeed_simulation.ts @@ -44,7 +44,7 @@ export async function initPlugin(server: Hapi.Server, path: string) { ], }, }, - handler: newsfeedHandler, + handler: newsfeedHandler as Hapi.Lifecycle.Method, }); server.route({ diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index 6cba92349ffc0..850b2773b5025 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -199,5 +199,22 @@ export default function({ getService, getPageObjects }) { expect(rowData.startsWith('Sep 22, 2015 @ 16:50:13.253')).to.be.ok(); }); }); + describe('usage of discover:searchOnPageLoad', () => { + it('should fetch data from ES initially when discover:searchOnPageLoad is false', async function() { + await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': false }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.awaitKibanaChrome(); + + expect(await PageObjects.discover.getNrOfFetches()).to.be(0); + }); + + it('should not fetch data from ES initially when discover:searchOnPageLoad is true', async function() { + await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': true }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.awaitKibanaChrome(); + + expect(await PageObjects.discover.getNrOfFetches()).to.be(1); + }); + }); }); } diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.js index 7dbb93c884f46..9a7356d8e521a 100644 --- a/test/functional/apps/discover/_errors.js +++ b/test/functional/apps/discover/_errors.js @@ -35,7 +35,8 @@ export default function({ getService, getPageObjects }) { await esArchiver.unload('invalid_scripted_field'); }); - describe('invalid scripted field error', () => { + // https://github.com/elastic/kibana/issues/61366 + describe.skip('invalid scripted field error', () => { it('is rendered', async () => { const isFetchErrorVisible = await testSubjects.exists('discoverFetchError'); expect(isFetchErrorVisible).to.be(true); diff --git a/test/functional/apps/discover/_field_visualize.ts b/test/functional/apps/discover/_field_visualize.ts new file mode 100644 index 0000000000000..46238bf143290 --- /dev/null +++ b/test/functional/apps/discover/_field_visualize.ts @@ -0,0 +1,154 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const filterBar = getService('filterBar'); + const inspector = getService('inspector'); + const kibanaServer = getService('kibanaServer'); + const log = getService('log'); + const queryBar = getService('queryBar'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + const defaultSettings = { + defaultIndex: 'logstash-*', + }; + + describe('discover field visualize button', () => { + before(async function() { + log.debug('load kibana index with default index pattern'); + await esArchiver.load('discover'); + + // and load a set of makelogs data + await esArchiver.loadIfNeeded('logstash_functional'); + await kibanaServer.uiSettings.replace(defaultSettings); + }); + + beforeEach(async () => { + log.debug('go to discover'); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + }); + + it('should visualize a field in area chart', async () => { + await PageObjects.discover.clickFieldListItem('phpmemory'); + log.debug('visualize a phpmemory field'); + await PageObjects.discover.clickFieldListItemVisualize('phpmemory'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const expectedTableData = [ + ['0', '10'], + ['58,320', '2'], + ['171,080', '2'], + ['3,240', '1'], + ['3,520', '1'], + ['3,880', '1'], + ['4,120', '1'], + ['4,640', '1'], + ['4,760', '1'], + ['5,680', '1'], + ['7,160', '1'], + ['7,400', '1'], + ['8,400', '1'], + ['8,800', '1'], + ['8,960', '1'], + ['9,400', '1'], + ['10,280', '1'], + ['10,840', '1'], + ['13,080', '1'], + ['13,360', '1'], + ]; + await inspector.open(); + await inspector.expectTableData(expectedTableData); + await inspector.close(); + }); + + it('should preserve app filters in visualize', async () => { + await filterBar.addFilter('bytes', 'is between', '3500', '4000'); + await PageObjects.discover.clickFieldListItem('geo.src'); + log.debug('visualize a geo.src field with filter applied'); + await PageObjects.discover.clickFieldListItemVisualize('geo.src'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + expect(await filterBar.hasFilter('bytes', '3,500 to 4,000')).to.be(true); + const expectedTableData = [ + ['CN', '133'], + ['IN', '120'], + ['US', '58'], + ['ID', '28'], + ['BD', '25'], + ['BR', '22'], + ['EG', '14'], + ['NG', '14'], + ['PK', '13'], + ['IR', '12'], + ['PH', '12'], + ['JP', '11'], + ['RU', '11'], + ['DE', '8'], + ['FR', '8'], + ['MX', '8'], + ['TH', '8'], + ['TR', '8'], + ['CA', '6'], + ['SA', '6'], + ]; + await inspector.open(); + await inspector.expectTableData(expectedTableData); + await inspector.close(); + }); + + it('should preserve query in visualize', async () => { + await queryBar.setQuery('machine.os : ios'); + await queryBar.submitQuery(); + await PageObjects.discover.clickFieldListItem('geo.dest'); + log.debug('visualize a geo.dest field with query applied'); + await PageObjects.discover.clickFieldListItemVisualize('geo.dest'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + expect(await queryBar.getQueryString()).to.equal('machine.os : ios'); + const expectedTableData = [ + ['CN', '519'], + ['IN', '495'], + ['US', '275'], + ['ID', '82'], + ['PK', '75'], + ['BR', '71'], + ['NG', '54'], + ['BD', '51'], + ['JP', '47'], + ['MX', '47'], + ['IR', '44'], + ['PH', '44'], + ['RU', '42'], + ['ET', '33'], + ['TH', '33'], + ['EG', '32'], + ['VN', '32'], + ['DE', '31'], + ['FR', '30'], + ['GB', '30'], + ]; + await inspector.open(); + await inspector.expectTableData(expectedTableData); + await inspector.close(); + }); + }); +} diff --git a/test/functional/apps/discover/index.js b/test/functional/apps/discover/index.js index 64a5a61335365..582c979a194f4 100644 --- a/test/functional/apps/discover/index.js +++ b/test/functional/apps/discover/index.js @@ -35,6 +35,7 @@ export default function({ getService, loadTestFile }) { loadTestFile(require.resolve('./_saved_queries')); loadTestFile(require.resolve('./_discover')); loadTestFile(require.resolve('./_discover_histogram')); + loadTestFile(require.resolve('./_field_visualize')); loadTestFile(require.resolve('./_filter_editor')); loadTestFile(require.resolve('./_errors')); loadTestFile(require.resolve('./_field_data')); diff --git a/test/functional/apps/getting_started/_shakespeare.js b/test/functional/apps/getting_started/_shakespeare.js index ded4eca908410..9a4bb0081b7ad 100644 --- a/test/functional/apps/getting_started/_shakespeare.js +++ b/test/functional/apps/getting_started/_shakespeare.js @@ -60,8 +60,7 @@ export default function({ getService, getPageObjects }) { it('should create shakespeare index pattern', async function() { log.debug('Create shakespeare index pattern'); await PageObjects.settings.createIndexPattern('shakes', null); - const indexPageHeading = await PageObjects.settings.getIndexPageHeading(); - const patternName = await indexPageHeading.getVisibleText(); + const patternName = await PageObjects.settings.getIndexPageHeading(); expect(patternName).to.be('shakes*'); }); diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index 4ef02f6c9e873..35c43c4633410 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -51,8 +51,7 @@ export default function({ getService, getPageObjects }) { it('should be able to create index pattern without time field', async function() { await PageObjects.settings.createIndexPattern('alias1', null); - const indexPageHeading = await PageObjects.settings.getIndexPageHeading(); - const patternName = await indexPageHeading.getVisibleText(); + const patternName = await PageObjects.settings.getIndexPageHeading(); expect(patternName).to.be('alias1*'); }); @@ -66,8 +65,7 @@ export default function({ getService, getPageObjects }) { it('should be able to create index pattern with timefield', async function() { await PageObjects.settings.createIndexPattern('alias2', 'date'); - const indexPageHeading = await PageObjects.settings.getIndexPageHeading(); - const patternName = await indexPageHeading.getVisibleText(); + const patternName = await PageObjects.settings.getIndexPageHeading(); expect(patternName).to.be('alias2*'); }); diff --git a/test/functional/apps/management/_index_pattern_create_delete.js b/test/functional/apps/management/_index_pattern_create_delete.js index 4661c9b4d53b8..a74620b696d1b 100644 --- a/test/functional/apps/management/_index_pattern_create_delete.js +++ b/test/functional/apps/management/_index_pattern_create_delete.js @@ -71,8 +71,7 @@ export default function({ getService, getPageObjects }) { }); it('should have index pattern in page header', async function() { - const indexPageHeading = await PageObjects.settings.getIndexPageHeading(); - const patternName = await indexPageHeading.getVisibleText(); + const patternName = await PageObjects.settings.getIndexPageHeading(); expect(patternName).to.be('logstash-*'); }); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index bf836cfe778b4..ebbeb01cbc917 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -21,10 +21,12 @@ import expect from '@kbn/expect'; export default function({ getService, getPageObjects }) { const log = getService('log'); + const find = getService('find'); const inspector = getService('inspector'); const browser = getService('browser'); const retry = getService('retry'); const security = getService('security'); + const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects([ 'common', 'visualize', @@ -465,5 +467,92 @@ export default function({ getService, getPageObjects }) { expect(paths.length).to.eql(numberOfSegments); }); }); + + describe('date histogram when no date field', () => { + before(async () => { + await PageObjects.visualize.loadSavedVisualization('AreaChart [no date field]'); + await PageObjects.visChart.waitForVisualization(); + + log.debug('Click X-axis'); + await PageObjects.visEditor.clickBucket('X-axis'); + log.debug('Click Date Histogram'); + await PageObjects.visEditor.selectAggregation('Date Histogram'); + }); + + it('should show error message for field', async () => { + const fieldErrorMessage = await find.byCssSelector( + '[data-test-subj="visDefaultEditorField"] + .euiFormErrorText' + ); + const errorMessage = await fieldErrorMessage.getVisibleText(); + expect(errorMessage).to.be( + 'The index pattern test_index* does not contain any of the following compatible field types: date' + ); + }); + }); + + describe('date histogram when no time filter', () => { + before(async () => { + await PageObjects.visualize.loadSavedVisualization('AreaChart [no time filter]'); + await PageObjects.visChart.waitForVisualization(); + + log.debug('Click X-axis'); + await PageObjects.visEditor.clickBucket('X-axis'); + log.debug('Click Date Histogram'); + await PageObjects.visEditor.selectAggregation('Date Histogram'); + }); + + it('should not show error message on init when the field is not selected', async () => { + const fieldValues = await PageObjects.visEditor.getField(); + expect(fieldValues[0]).to.be(undefined); + const isFieldErrorMessageExists = await find.existsByCssSelector( + '[data-test-subj="visDefaultEditorField"] + .euiFormErrorText' + ); + expect(isFieldErrorMessageExists).to.be(false); + }); + + describe('interval errors', () => { + before(async () => { + // to trigger displaying of error messages + await testSubjects.clickWhenNotDisabled('visualizeEditorRenderButton'); + // this will avoid issues with the play tooltip covering the interval field + await testSubjects.scrollIntoView('advancedParams-2'); + }); + + it('should not fail during changing interval when the field is not selected', async () => { + await PageObjects.visEditor.setInterval('m'); + const intervalValues = await PageObjects.visEditor.getInterval(); + expect(intervalValues[0]).to.be('Millisecond'); + }); + + it('should not fail during changing custom interval when the field is not selected', async () => { + await PageObjects.visEditor.setInterval('4d', { type: 'custom' }); + const isInvalidIntervalExists = await find.existsByCssSelector( + '.euiComboBox-isInvalid[data-test-subj="visEditorInterval"]' + ); + expect(isInvalidIntervalExists).to.be(false); + }); + + it('should show error when interval invalid', async () => { + await PageObjects.visEditor.setInterval('xx', { type: 'custom' }); + const isIntervalErrorMessageExists = await find.existsByCssSelector( + '[data-test-subj="visEditorInterval"] + .euiFormErrorText' + ); + expect(isIntervalErrorMessageExists).to.be(true); + }); + + it('should show error when calendar interval invalid', async () => { + await PageObjects.visEditor.setInterval('14d', { type: 'custom' }); + const intervalErrorMessage = await find.byCssSelector( + '[data-test-subj="visEditorInterval"] + .euiFormErrorText' + ); + let errorMessage = await intervalErrorMessage.getVisibleText(); + expect(errorMessage).to.be('Invalid calendar interval: 2w, value must be 1'); + + await PageObjects.visEditor.setInterval('3w', { type: 'custom' }); + errorMessage = await intervalErrorMessage.getVisibleText(); + expect(errorMessage).to.be('Invalid calendar interval: 3w, value must be 1'); + }); + }); + }); }); } diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 9e39e93926c95..0a7be3d682311 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -57,7 +57,6 @@ export default function({ getService, getPageObjects }) { }); describe('complete config', function describeIndexTests() { - this.tags(['skipCoverage']); before(async function() { await browser.setWindowSize(1280, 1000); diff --git a/test/functional/fixtures/es_archiver/visualize/data.json b/test/functional/fixtures/es_archiver/visualize/data.json index 9fb8747a7376a..845e9a5e08825 100644 --- a/test/functional/fixtures/es_archiver/visualize/data.json +++ b/test/functional/fixtures/es_archiver/visualize/data.json @@ -174,3 +174,76 @@ } } } + +{ + "type": "doc", + "value": { + "id": "index-pattern:test_index*", + "index": ".kibana", + "source": { + "index-pattern": { + "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"message\"}}},{\"name\":\"user\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"user.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"user\"}}}]", + "title": "test_index*" + }, + "type": "test_index*" + } + } +} + +{ + "type": "doc", + "value": { + "id": "visualization:AreaChart-no-date-field", + "index": ".kibana", + "source": { + "type": "visualization", + "visualization": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"test_index*\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "AreaChart [no date field]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"AreaChart [no date field]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}" + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "index-pattern:log*", + "index": ".kibana", + "source": { + "index-pattern": { + "fieldFormatMap": "{\"bytes\":{\"id\":\"bytes\"}}", + "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false}]", + "title": "log*" + }, + "type": "index-pattern" + } + } +} + +{ + "type": "doc", + "value": { + "id": "visualization:AreaChart-no-time-filter", + "index": ".kibana", + "source": { + "type": "visualization", + "visualization": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"log*\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "AreaChart [no time filter]", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"AreaChart [no time filter]\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"addTooltip\":true,\"addLegend\":true,\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}" + } + } + } +} diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index a126cfb1bce4b..1d4e51360f319 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -300,6 +300,11 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider 'true' ); } + public async getNrOfFetches() { + const el = await find.byCssSelector('[data-fetch-counter]'); + const nr = await el.getAttribute('data-fetch-counter'); + return Number(nr); + } } return new DiscoverPage(); diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index 25706fda74925..3f6036f58f0a9 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -169,7 +169,7 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider } async getIndexPageHeading() { - return await testSubjects.find('indexPatternTitle'); + return await testSubjects.getVisibleText('indexPatternTitle'); } async getConfigureHeader() { diff --git a/test/functional/services/remote/remote.ts b/test/functional/services/remote/remote.ts index afe8499a1c2ea..e571a1a7e5551 100644 --- a/test/functional/services/remote/remote.ts +++ b/test/functional/services/remote/remote.ts @@ -48,6 +48,9 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { }; const writeCoverage = (coverageJson: string) => { + if (!Fs.existsSync(coverageDir)) { + Fs.mkdirSync(coverageDir, { recursive: true }); + } const id = coverageCounter++; const timestamp = Date.now(); const path = resolve(coverageDir, `${id}.${timestamp}.coverage.json`); @@ -75,12 +78,6 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { }, w3c=${isW3CEnabled}, codeCoverage=${collectCoverage}` ); } - // code coverage is supported only in Chrome browser - if (collectCoverage) { - // We are running xpack tests with different configs and cleanup will delete collected coverage - // del.sync(coverageDir); - Fs.mkdirSync(coverageDir, { recursive: true }); - } consoleLog$ .pipe( diff --git a/test/plugin_functional/config.js b/test/plugin_functional/config.js index 7017c01cc5634..c7fa0f40e1d0c 100644 --- a/test/plugin_functional/config.js +++ b/test/plugin_functional/config.js @@ -32,7 +32,6 @@ export default async function({ readConfigFile }) { return { testFiles: [ - require.resolve('./test_suites/app_plugins'), require.resolve('./test_suites/custom_visualizations'), require.resolve('./test_suites/panel_actions'), require.resolve('./test_suites/embeddable_explorer'), diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/kibana.json b/test/plugin_functional/plugins/core_plugin_static_assets/kibana.json new file mode 100644 index 0000000000000..6f9fb94e9b49c --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_static_assets/kibana.json @@ -0,0 +1,7 @@ +{ + "id": "corePluginStaticAssets", + "version": "0.0.1", + "kibanaVersion": "kibana", + "server": false, + "ui": true +} diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/package.json b/test/plugin_functional/plugins/core_plugin_static_assets/package.json new file mode 100644 index 0000000000000..304e1b11fde42 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_static_assets/package.json @@ -0,0 +1,17 @@ +{ + "name": "corePluginStaticAssets", + "version": "1.0.0", + "main": "target/test/plugin_functional/plugins/core_plugin_static_assets", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "typescript": "3.7.2" + } +} diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/public/assets/chart.svg b/test/plugin_functional/plugins/core_plugin_static_assets/public/assets/chart.svg new file mode 100644 index 0000000000000..44553960a5cce --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_static_assets/public/assets/chart.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/plugins/kibana_utils/index.ts b/test/plugin_functional/plugins/core_plugin_static_assets/public/index.ts similarity index 87% rename from src/plugins/kibana_utils/index.ts rename to test/plugin_functional/plugins/core_plugin_static_assets/public/index.ts index 14d6e52dc0465..2bdb40cf19cb5 100644 --- a/src/plugins/kibana_utils/index.ts +++ b/test/plugin_functional/plugins/core_plugin_static_assets/public/index.ts @@ -17,4 +17,6 @@ * under the License. */ -export { createStateContainer, StateContainer, of } from './common'; +import { CorePluginStaticAssets } from './plugin'; + +export const plugin = () => new CorePluginStaticAssets(); diff --git a/test/api_integration/apis/management/index.js b/test/plugin_functional/plugins/core_plugin_static_assets/public/plugin.tsx similarity index 80% rename from test/api_integration/apis/management/index.js rename to test/plugin_functional/plugins/core_plugin_static_assets/public/plugin.tsx index a442e3e4fee74..d9f3d62937584 100644 --- a/test/api_integration/apis/management/index.js +++ b/test/plugin_functional/plugins/core_plugin_static_assets/public/plugin.tsx @@ -17,8 +17,11 @@ * under the License. */ -export default function({ loadTestFile }) { - describe('management apis', () => { - loadTestFile(require.resolve('./saved_objects')); - }); +import { Plugin, CoreSetup } from 'kibana/public'; + +export class CorePluginStaticAssets implements Plugin { + public setup(core: CoreSetup, deps: {}) {} + + public start() {} + public stop() {} } diff --git a/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json new file mode 100644 index 0000000000000..4a564ee1e5578 --- /dev/null +++ b/test/plugin_functional/plugins/core_plugin_static_assets/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "../../../../typings/**/*" + ], + "exclude": [] +} diff --git a/test/plugin_functional/plugins/kbn_top_nav/kibana.json b/test/plugin_functional/plugins/kbn_top_nav/kibana.json new file mode 100644 index 0000000000000..b274e80b9ef65 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_top_nav/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "kbn_top_nav", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["kbn_top_nav"], + "server": false, + "ui": true, + "requiredPlugins": ["navigation"] +} \ No newline at end of file diff --git a/test/plugin_functional/plugins/kbn_top_nav/package.json b/test/plugin_functional/plugins/kbn_top_nav/package.json new file mode 100644 index 0000000000000..510d681a4a75c --- /dev/null +++ b/test/plugin_functional/plugins/kbn_top_nav/package.json @@ -0,0 +1,18 @@ +{ + "name": "kbn_top_nav", + "version": "1.0.0", + "main": "target/test/plugin_functional/plugins/kbn_top_nav", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "typescript": "3.7.2" + } +} + diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx b/test/plugin_functional/plugins/kbn_top_nav/public/application.tsx similarity index 71% rename from test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx rename to test/plugin_functional/plugins/kbn_top_nav/public/application.tsx index f77db4fe1654e..0f65e6159796b 100644 --- a/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx +++ b/test/plugin_functional/plugins/kbn_top_nav/public/application.tsx @@ -18,11 +18,15 @@ */ import React from 'react'; -import './initialize'; -import { npStart } from 'ui/new_platform'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { AppMountParameters } from 'kibana/public'; +import { AppPluginDependencies } from './types'; -export const AppWithTopNav = () => { - const { TopNavMenu } = npStart.plugins.navigation.ui; +export const renderApp = ( + depsStart: AppPluginDependencies, + { appBasePath, element }: AppMountParameters +) => { + const { TopNavMenu } = depsStart.navigation.ui; const config = [ { id: 'new', @@ -32,10 +36,12 @@ export const AppWithTopNav = () => { testId: 'demoNewButton', }, ]; - - return ( + render( Hey - + , + element ); + + return () => unmountComponentAtNode(element); }; diff --git a/src/plugins/ui_actions/scripts/storybook.js b/test/plugin_functional/plugins/kbn_top_nav/public/index.ts similarity index 75% rename from src/plugins/ui_actions/scripts/storybook.js rename to test/plugin_functional/plugins/kbn_top_nav/public/index.ts index cb2eda610170d..bd478f1dd3bdb 100644 --- a/src/plugins/ui_actions/scripts/storybook.js +++ b/test/plugin_functional/plugins/kbn_top_nav/public/index.ts @@ -17,10 +17,8 @@ * under the License. */ -import { join } from 'path'; +import { PluginInitializer } from 'kibana/public'; +import { TopNavTestPlugin, TopNavTestPluginSetup, TopNavTestPluginStart } from './plugin'; -// eslint-disable-next-line -require('@kbn/storybook').runStorybookCli({ - name: 'ui_actions', - storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.story.tsx')], -}); +export const plugin: PluginInitializer = () => + new TopNavTestPlugin(); diff --git a/test/plugin_functional/plugins/kbn_top_nav/public/plugin.tsx b/test/plugin_functional/plugins/kbn_top_nav/public/plugin.tsx new file mode 100644 index 0000000000000..a433de98357fb --- /dev/null +++ b/test/plugin_functional/plugins/kbn_top_nav/public/plugin.tsx @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, Plugin, AppMountParameters } from 'kibana/public'; +import { NavigationPublicPluginSetup } from '../../../../../src/plugins/navigation/public'; +import { AppPluginDependencies } from './types'; + +export class TopNavTestPlugin implements Plugin { + public setup(core: CoreSetup, { navigation }: { navigation: NavigationPublicPluginSetup }) { + const customExtension = { + id: 'registered-prop', + label: 'Registered Button', + description: 'Registered Demo', + run() {}, + testId: 'demoRegisteredNewButton', + }; + + navigation.registerMenuItem(customExtension); + + const customDiscoverExtension = { + id: 'registered-discover-prop', + label: 'Registered Discover Button', + description: 'Registered Discover Demo', + run() {}, + testId: 'demoDiscoverRegisteredNewButton', + appName: 'discover', + }; + + navigation.registerMenuItem(customDiscoverExtension); + + core.application.register({ + id: 'topNavMenu', + title: 'Top nav menu example', + async mount(params: AppMountParameters) { + const { renderApp } = await import('./application'); + const services = await core.getStartServices(); + return renderApp(services[1] as AppPluginDependencies, params); + }, + }); + + return {}; + } + + public start() {} + public stop() {} +} + +export type TopNavTestPluginSetup = ReturnType; +export type TopNavTestPluginStart = ReturnType; diff --git a/src/plugins/ui_actions/public/actions/types.ts b/test/plugin_functional/plugins/kbn_top_nav/public/types.ts similarity index 81% rename from src/plugins/ui_actions/public/actions/types.ts rename to test/plugin_functional/plugins/kbn_top_nav/public/types.ts index 465f091e45ef1..c70a78bedb54f 100644 --- a/src/plugins/ui_actions/public/actions/types.ts +++ b/test/plugin_functional/plugins/kbn_top_nav/public/types.ts @@ -17,8 +17,8 @@ * under the License. */ -export interface SerializedAction { - readonly factoryId: string; - readonly name: string; - readonly config: Config; +import { NavigationPublicPluginStart } from '../../../../../src/plugins/navigation/public'; + +export interface AppPluginDependencies { + navigation: NavigationPublicPluginStart; } diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json b/test/plugin_functional/plugins/kbn_top_nav/tsconfig.json similarity index 100% rename from test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json rename to test/plugin_functional/plugins/kbn_top_nav/tsconfig.json diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_vis.js b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_vis.js index 643d15c982792..7aa12ea7a1130 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_vis.js +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_vis.js @@ -20,9 +20,9 @@ import { SelfChangingEditor } from './self_changing_editor'; import { SelfChangingComponent } from './self_changing_components'; -import { setup as visualizations } from '../../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/legacy'; +import { npSetup } from '../../../../../../src/legacy/ui/public/new_platform'; -visualizations.createReactVisualization({ +npSetup.plugins.visualizations.createReactVisualization({ name: 'self_changing_vis', title: 'Self Changing Vis', icon: 'controlsHorizontal', diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx index 8ddb2e1a4803b..18ceec652392d 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx @@ -70,10 +70,11 @@ export class EmbeddableExplorerPublicPlugin const sayHelloAction = new SayHelloAction(alert); const sendMessageAction = createSendMessageAction(core.overlays); + plugins.uiActions.registerAction(helloWorldAction); plugins.uiActions.registerAction(sayHelloAction); plugins.uiActions.registerAction(sendMessageAction); - plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, helloWorldAction); + plugins.uiActions.attachAction(CONTEXT_MENU_TRIGGER, helloWorldAction); plugins.__LEGACY.onRenderComplete(() => { const root = document.getElementById(REACT_ROOT_ID); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/index.js b/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/index.js deleted file mode 100644 index ff4be4113eeb3..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/index.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function(kibana) { - return new kibana.Plugin({ - uiExports: { - app: { - title: 'Test Plugin App', - description: 'This is a sample plugin for the functional tests.', - main: 'plugins/kbn_tp_sample_app_plugin/app', - }, - }, - }); -} diff --git a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/package.json b/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/package.json deleted file mode 100644 index 2537bb9a7ed5c..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_sample_app_plugin/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "kbn_tp_sample_app_plugin", - "version": "1.0.0", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0" -} diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx index 7c7cc689d05e5..8395fddece2a4 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_action.tsx @@ -62,4 +62,5 @@ function createSamplePanelAction() { } const action = createSamplePanelAction(); -npSetup.plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, action); +npSetup.plugins.uiActions.registerAction(action); +npSetup.plugins.uiActions.attachAction(CONTEXT_MENU_TRIGGER, action); diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts index e034fbe320608..4b09be4db8a60 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/public/sample_panel_link.ts @@ -33,4 +33,5 @@ export const createSamplePanelLink = (): Action => }); const action = createSamplePanelLink(); -npStart.plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, action); +npStart.plugins.uiActions.registerAction(action); +npStart.plugins.uiActions.attachAction(CONTEXT_MENU_TRIGGER, action); diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/index.js b/test/plugin_functional/plugins/kbn_tp_top_nav/index.js deleted file mode 100644 index b4c3e05c28b66..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_top_nav/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function(kibana) { - return new kibana.Plugin({ - uiExports: { - app: { - title: 'Top Nav Menu test', - description: 'This is a sample plugin for the functional tests.', - main: 'plugins/kbn_tp_top_nav/app', - }, - hacks: ['plugins/kbn_tp_top_nav/initialize'], - }, - }); -} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/package.json b/test/plugin_functional/plugins/kbn_tp_top_nav/package.json deleted file mode 100644 index 7102d24d3292d..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_top_nav/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "kbn_tp_top_nav", - "version": "1.0.0", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0" -} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js b/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js deleted file mode 100644 index e7f97e68c086d..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; - -import { uiModules } from 'ui/modules'; -import chrome from 'ui/chrome'; - -// This is required so some default styles and required scripts/Angular modules are loaded, -// or the timezone setting is correctly applied. -import 'ui/autoload/all'; - -import { AppWithTopNav } from './top_nav'; - -const app = uiModules.get('apps/topnavDemoPlugin', ['kibana']); - -app.config($locationProvider => { - $locationProvider.html5Mode({ - enabled: false, - requireBase: false, - rewriteLinks: false, - }); -}); - -function RootController($scope, $element) { - const domNode = $element[0]; - - // render react to DOM - render(, domNode); - - // unmount react on controller destroy - $scope.$on('$destroy', () => { - unmountComponentAtNode(domNode); - }); -} - -chrome.setRootController('topnavDemoPlugin', RootController); diff --git a/test/plugin_functional/test_suites/app_plugins/index.js b/test/plugin_functional/test_suites/app_plugins/index.js deleted file mode 100644 index 83faa7377c7ac..0000000000000 --- a/test/plugin_functional/test_suites/app_plugins/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function({ loadTestFile }) { - describe('app plugins', () => { - loadTestFile(require.resolve('./app_navigation')); - }); -} diff --git a/test/plugin_functional/test_suites/core_plugins/ui_plugins.ts b/test/plugin_functional/test_suites/core_plugins/ui_plugins.ts index 82267d73782af..8ddd0ff96ba8f 100644 --- a/test/plugin_functional/test_suites/core_plugins/ui_plugins.ts +++ b/test/plugin_functional/test_suites/core_plugins/ui_plugins.ts @@ -25,6 +25,7 @@ import '../../../../test/plugin_functional/plugins/core_provider_plugin/types'; export default function({ getService, getPageObjects }: PluginFunctionalProviderContext) { const PageObjects = getPageObjects(['common']); const browser = getService('browser'); + const supertest = getService('supertest'); describe('ui plugins', function() { describe('loading', function describeIndexTests() { @@ -97,5 +98,47 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider ).to.be('/core_plugin_b/system_request says: "System request? false"'); }); }); + + describe('Plugin static assets', function() { + it('exposes static assets from "public/assets" folder', async () => { + await supertest.get('/plugins/corePluginStaticAssets/assets/chart.svg').expect(200); + }); + + it('returns 404 if not found', async function() { + await supertest.get('/plugins/corePluginStaticAssets/assets/not-a-chart.svg').expect(404); + }); + + it('does not expose folder content', async function() { + await supertest.get('/plugins/corePluginStaticAssets/assets/').expect(403); + }); + + it('does not allow file tree traversing', async function() { + await supertest.get('/plugins/corePluginStaticAssets/assets/../../kibana.json').expect(404); + }); + + it('generates "etag" & "last-modified" headers', async () => { + const response = await supertest + .get('/plugins/corePluginStaticAssets/assets/chart.svg') + .expect(200); + + expect(response.header).to.have.property('etag'); + expect(response.header).to.have.property('last-modified'); + }); + + it('generates the same "etag" & "last-modified" for the same asset', async () => { + const firstResponse = await supertest + .get('/plugins/corePluginStaticAssets/assets/chart.svg') + .expect(200); + + expect(firstResponse.header).to.have.property('etag'); + + const secondResponse = await supertest + .get('/plugins/corePluginStaticAssets/assets/chart.svg') + .expect(200); + + expect(secondResponse.header.etag).to.be(firstResponse.header.etag); + expect(secondResponse.header['last-modified']).to.be(firstResponse.header['last-modified']); + }); + }); }); } diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh index f3ac951cdc7b7..b233d99d26902 100755 --- a/test/scripts/jenkins_ci_group.sh +++ b/test/scripts/jenkins_ci_group.sh @@ -22,7 +22,7 @@ else echo " -> running tests from the clone folder" #yarn run grunt "run:functionalTests_ciGroup${CI_GROUP}"; - node scripts/functional_tests --debug --include-tag "ciGroup$CI_GROUP" --config test/functional/config.coverage.js; + node scripts/functional_tests --debug --include-tag "ciGroup$CI_GROUP" --config test/functional/config.coverage.js || true; if [[ -d target/kibana-coverage/functional ]]; then echo " -> replacing kibana${CI_GROUP} with kibana in json files" diff --git a/test/scripts/jenkins_xpack_ci_group.sh b/test/scripts/jenkins_xpack_ci_group.sh index 4c2b4194c52e2..01b13293c10ba 100755 --- a/test/scripts/jenkins_xpack_ci_group.sh +++ b/test/scripts/jenkins_xpack_ci_group.sh @@ -23,7 +23,7 @@ else cd "kibana${CI_GROUP}/x-pack" echo " -> running tests from the clone folder" - node scripts/functional_tests --debug --include-tag "ciGroup$CI_GROUP" --config test/functional/config.coverage.js; + node scripts/functional_tests --debug --include-tag "ciGroup$CI_GROUP" --config test/functional/config.coverage.js || true; if [[ -d ../target/kibana-coverage/functional ]]; then echo " -> replacing kibana${CI_GROUP} with kibana in json files" diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 784b5a5a42ace..2a28e349ace99 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -9,7 +9,6 @@ "xpack.beatsManagement": "legacy/plugins/beats_management", "xpack.canvas": "legacy/plugins/canvas", "xpack.crossClusterReplication": "legacy/plugins/cross_cluster_replication", - "xpack.dashboard": "plugins/dashboard_enhanced", "xpack.dashboardMode": "legacy/plugins/dashboard_mode", "xpack.data": "plugins/data_enhanced", "xpack.drilldowns": "plugins/drilldowns", diff --git a/x-pack/legacy/plugins/apm/e2e/.gitignore b/x-pack/legacy/plugins/apm/e2e/.gitignore index 10c769065fc28..a14856506bc6c 100644 --- a/x-pack/legacy/plugins/apm/e2e/.gitignore +++ b/x-pack/legacy/plugins/apm/e2e/.gitignore @@ -1,4 +1,3 @@ -cypress/ingest-data/events.json cypress/screenshots/* - cypress/test-results +tmp diff --git a/x-pack/legacy/plugins/apm/e2e/README.md b/x-pack/legacy/plugins/apm/e2e/README.md index 73a1e860f5564..a891d64539a3f 100644 --- a/x-pack/legacy/plugins/apm/e2e/README.md +++ b/x-pack/legacy/plugins/apm/e2e/README.md @@ -1,58 +1,16 @@ # End-To-End (e2e) Test for APM UI -## Ingest static data into Elasticsearch via APM Server +**Run E2E tests** -1. Start Elasticsearch and APM Server, using [apm-integration-testing](https://github.com/elastic/apm-integration-testing): - -```shell -$ git clone https://github.com/elastic/apm-integration-testing.git -$ cd apm-integration-testing -./scripts/compose.py start master --no-kibana --no-xpack-secure -``` - -2. Download [static data file](https://storage.googleapis.com/apm-ui-e2e-static-data/events.json) - -```shell -$ cd x-pack/legacy/plugins/apm/e2e/cypress/ingest-data -$ curl https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output events.json -``` - -3. Post to APM Server - -```shell -$ cd x-pack/legacy/plugins/apm/e2e/cypress/ingest-data -$ node replay.js --server-url http://localhost:8200 --secret-token abcd --events ./events.json -``` ->This process will take a few minutes to ingest all data - -4. Start Kibana - -```shell -$ yarn kbn bootstrap -$ yarn start --no-base-path --csp.strict=false -``` - -> Content Security Policy (CSP) Settings: Your Kibana instance must have the `csp.strict: false`. - -## How to run the tests - -_Note: Run the following commands from `kibana/x-pack/legacy/plugins/apm/e2e/cypress`._ - -### Interactive mode - -``` -yarn cypress open +```sh +x-pack/legacy/plugins/apm/e2e/run-e2e.sh ``` -### Headless mode - -``` -yarn cypress run -``` +_Starts Kibana, APM Server, Elasticsearch (with sample data) and runs the tests_ ## Reproducing CI builds ->This process is very slow compared to the local development described above. Consider that the CI must install and configure the build tools and create a Docker image for the project to run tests in a consistent manner. +> This process is very slow compared to the local development described above. Consider that the CI must install and configure the build tools and create a Docker image for the project to run tests in a consistent manner. The Jenkins CI uses a shell script to prepare Kibana: @@ -60,7 +18,7 @@ The Jenkins CI uses a shell script to prepare Kibana: # Prepare and run Kibana locally $ x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh # Build Docker image for Kibana -$ docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) x-pack/legacy/plugins/apm/e2e/ci +$ docker build --tag cypress --build-arg NODE_VERSION=$(cat .node-version) x-pack/legacy/plugins/apm/e2e/ci # Run Docker image $ docker run --rm -t --user "$(id -u):$(id -g)" \ -v `pwd`:/app --network="host" \ diff --git a/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh b/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh index f7226dca1d276..ae5155d966e58 100755 --- a/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh +++ b/x-pack/legacy/plugins/apm/e2e/ci/entrypoint.sh @@ -7,7 +7,7 @@ if [ -z "${kibana}" ] ; then kibana=127.0.0.1 fi -export CYPRESS_BASE_URL=http://${kibana}:5601 +export CYPRESS_BASE_URL=http://${kibana}:5701 ## To avoid issues with the home and caching artifacts export HOME=/tmp diff --git a/x-pack/legacy/plugins/apm/e2e/ci/kibana.dev.yml b/x-pack/legacy/plugins/apm/e2e/ci/kibana.dev.yml deleted file mode 100644 index db57db9a1abe9..0000000000000 --- a/x-pack/legacy/plugins/apm/e2e/ci/kibana.dev.yml +++ /dev/null @@ -1,7 +0,0 @@ -## -# Disabled plugins -######################## -logging.verbose: true -elasticsearch.username: "kibana_system_user" -elasticsearch.password: "changeme" -xpack.security.encryptionKey: "something_at_least_32_characters" diff --git a/x-pack/legacy/plugins/apm/e2e/ci/kibana.e2e.yml b/x-pack/legacy/plugins/apm/e2e/ci/kibana.e2e.yml new file mode 100644 index 0000000000000..19f3f7c8978fa --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/ci/kibana.e2e.yml @@ -0,0 +1,31 @@ +# Kibana +server.port: 5701 +xpack.security.encryptionKey: 'something_at_least_32_characters' +csp.strict: false +logging.verbose: true + +# Elasticsearch +# Started via apm-integration-testing +# ./scripts/compose.py start master --no-kibana --elasticsearch-port 9201 --apm-server-port 8201 +elasticsearch.hosts: http://localhost:9201 +elasticsearch.username: 'kibana_system_user' +elasticsearch.password: 'changeme' + +# APM index pattern +apm_oss.indexPattern: apm-* + +# APM Indices +apm_oss.errorIndices: apm-*-error* +apm_oss.sourcemapIndices: apm-*-sourcemap +apm_oss.transactionIndices: apm-*-transaction* +apm_oss.spanIndices: apm-*-span* +apm_oss.metricsIndices: apm-*-metric* +apm_oss.onboardingIndices: apm-*-onboarding* + +# APM options +xpack.apm.enabled: true +xpack.apm.serviceMapEnabled: false +xpack.apm.autocreateApmIndexPattern: true +xpack.apm.ui.enabled: true +xpack.apm.ui.transactionGroupBucketSize: 100 +xpack.apm.ui.maxTraceItems: 1000 diff --git a/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh b/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh index 4f176fd0070f5..6df17bd51e0e8 100755 --- a/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh +++ b/x-pack/legacy/plugins/apm/e2e/ci/prepare-kibana.sh @@ -1,24 +1,21 @@ #!/usr/bin/env bash set -e -CYPRESS_DIR="x-pack/legacy/plugins/apm/e2e" +E2E_DIR="x-pack/legacy/plugins/apm/e2e" echo "1/3 Install dependencies ..." # shellcheck disable=SC1091 source src/dev/ci_setup/setup_env.sh true yarn kbn bootstrap -cp ${CYPRESS_DIR}/ci/kibana.dev.yml config/kibana.dev.yml -echo 'elasticsearch:' >> config/kibana.dev.yml -cp ${CYPRESS_DIR}/ci/kibana.dev.yml config/kibana.yml echo "2/3 Ingest test data ..." -pushd ${CYPRESS_DIR} +pushd ${E2E_DIR} yarn install curl --silent https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output ingest-data/events.json -node ingest-data/replay.js --server-url http://localhost:8200 --secret-token abcd --events ./events.json > ingest-data.log +node ingest-data/replay.js --server-url http://localhost:8201 --secret-token abcd --events ./events.json > ingest-data.log echo "3/3 Start Kibana ..." popd ## Might help to avoid FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory export NODE_OPTIONS="--max-old-space-size=4096" -nohup node scripts/kibana --no-base-path --csp.strict=false --optimize.watch=false> kibana.log 2>&1 & +nohup node scripts/kibana --config "${E2E_DIR}/ci/kibana.e2e.yml" --no-base-path --optimize.watch=false> kibana.log 2>&1 & diff --git a/x-pack/legacy/plugins/apm/e2e/cypress.json b/x-pack/legacy/plugins/apm/e2e/cypress.json index 310964656f107..0894cfd13a197 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress.json +++ b/x-pack/legacy/plugins/apm/e2e/cypress.json @@ -1,5 +1,6 @@ { - "baseUrl": "http://localhost:5601", + "nodeVersion": "system", + "baseUrl": "http://localhost:5701", "video": false, "trashAssetsBeforeRuns": false, "fileServerFolder": "../", @@ -15,5 +16,9 @@ "mochaFile": "./cypress/test-results/[hash]-e2e-tests.xml", "toConsole": false }, - "testFiles": "**/*.{feature,features}" + "testFiles": "**/*.{feature,features}", + "env": { + "elasticsearch_username": "admin", + "elasticsearch_password": "changeme" + } } diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature index 01fee2bf68b09..285615108266b 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature +++ b/x-pack/legacy/plugins/apm/e2e/cypress/integration/apm.feature @@ -2,6 +2,6 @@ Feature: APM Scenario: Transaction duration charts Given a user browses the APM UI application - When the user inspects the opbeans-go service + When the user inspects the opbeans-node service Then should redirect to correct path with correct params - And should have correct y-axis ticks \ No newline at end of file + And should have correct y-axis ticks diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts b/x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts index 1239ef397e086..90d5c9eda632d 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts +++ b/x-pack/legacy/plugins/apm/e2e/cypress/integration/helpers.ts @@ -6,45 +6,26 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { safeLoad } from 'js-yaml'; - -const RANGE_FROM = '2019-09-04T18:00:00.000Z'; -const RANGE_TO = '2019-09-05T06:00:00.000Z'; +const RANGE_FROM = '2020-03-04T12:30:00.000Z'; +const RANGE_TO = '2020-03-04T13:00:00.000Z'; const BASE_URL = Cypress.config().baseUrl; -/** - * Credentials in the `kibana.dev.yml` config file will be used to authenticate with Kibana - */ -const KIBANA_DEV_YML_PATH = '../../../../../config/kibana.dev.yml'; - /** The default time in ms to wait for a Cypress command to complete */ -export const DEFAULT_TIMEOUT = 30 * 1000; +export const DEFAULT_TIMEOUT = 60 * 1000; export function loginAndWaitForPage(url: string) { - // read the login details from `kibana.dev.yml` - cy.readFile(KIBANA_DEV_YML_PATH).then(kibanaDevYml => { - const config = safeLoad(kibanaDevYml); - const username = config['elasticsearch.username']; - const password = config['elasticsearch.password']; - - const hasCredentials = username && password; - - cy.log( - `Authenticating via config credentials from "${KIBANA_DEV_YML_PATH}". username: ${username}, password: ${password}` - ); + const username = Cypress.env('elasticsearch_username'); + const password = Cypress.env('elasticsearch_password'); - const options = hasCredentials - ? { - auth: { username, password } - } - : {}; + cy.log(`Authenticating via ${username} / ${password}`); - const fullUrl = `${BASE_URL}${url}?rangeFrom=${RANGE_FROM}&rangeTo=${RANGE_TO}`; - cy.visit(fullUrl, options); - }); + const fullUrl = `${BASE_URL}${url}?rangeFrom=${RANGE_FROM}&rangeTo=${RANGE_TO}`; + cy.visit(fullUrl, { auth: { username, password } }); cy.viewport('macbook-15'); // wait for loading spinner to disappear - cy.get('.kibanaLoaderWrap', { timeout: DEFAULT_TIMEOUT }).should('not.exist'); + cy.get('#kbn_loading_message', { timeout: DEFAULT_TIMEOUT }).should( + 'not.exist' + ); } diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js b/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js index 0e4b91ab45a40..968c2675a62e7 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js +++ b/x-pack/legacy/plugins/apm/e2e/cypress/integration/snapshots.js @@ -1,19 +1,10 @@ module.exports = { - "When clicking opbeans-go service": { - "transaction duration charts": { - "should have correct y-axis ticks": { - "1": "3.7 min", - "2": "1.8 min", - "3": "0.0 min" - } - } - }, - "__version": "3.8.3", "APM": { "Transaction duration charts": { - "1": "3.7 min", - "2": "1.8 min", - "3": "0.0 min" + "1": "500 ms", + "2": "250 ms", + "3": "0 ms" } - } + }, + "__version": "4.2.0" } diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts b/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts index f2f1e515f967a..f58118f3352ea 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts +++ b/x-pack/legacy/plugins/apm/e2e/cypress/support/step_definitions/apm.ts @@ -12,15 +12,15 @@ Given(`a user browses the APM UI application`, () => { loginAndWaitForPage(`/app/apm#/services`); }); -When(`the user inspects the opbeans-go service`, () => { - // click opbeans-go service - cy.get(':contains(opbeans-go)') +When(`the user inspects the opbeans-node service`, () => { + // click opbeans-node service + cy.get(':contains(opbeans-node)') .last() .click({ force: true }); }); Then(`should redirect to correct path with correct params`, () => { - cy.url().should('contain', `/app/apm#/services/opbeans-go/transactions`); + cy.url().should('contain', `/app/apm#/services/opbeans-node/transactions`); cy.url().should('contain', `transactionType=request`); }); diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js b/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js index 823b23cfdffec..8db6a1ef83520 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js +++ b/x-pack/legacy/plugins/apm/e2e/cypress/webpack.config.js @@ -14,6 +14,7 @@ module.exports = { { test: /\.ts$/, exclude: [/node_modules/], + include: [/e2e\/cypress/], use: [ { loader: 'ts-loader' diff --git a/x-pack/legacy/plugins/apm/e2e/cypress/ingest-data/replay.js b/x-pack/legacy/plugins/apm/e2e/ingest-data/replay.js similarity index 50% rename from x-pack/legacy/plugins/apm/e2e/cypress/ingest-data/replay.js rename to x-pack/legacy/plugins/apm/e2e/ingest-data/replay.js index 990fc37bb7b2e..5301eafece06d 100644 --- a/x-pack/legacy/plugins/apm/e2e/cypress/ingest-data/replay.js +++ b/x-pack/legacy/plugins/apm/e2e/ingest-data/replay.js @@ -4,15 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable no-console */ +/* eslint-disable import/no-extraneous-dependencies */ + /** * This script is useful for ingesting previously generated APM data into Elasticsearch via APM Server * * You can either: * 1. Download a static test data file from: https://storage.googleapis.com/apm-ui-e2e-static-data/events.json - * 2. Or, generate the test data file yourself by following the steps in: https://github.com/elastic/kibana/blob/5207a0b68a66d4f513fe1b0cedb021b296641712/x-pack/legacy/plugins/apm/cypress/README.md#generate-static-data + * 2. Or, generate the test data file yourself: + * git clone https://github.com/elastic/apm-integration-testing.git + * ./scripts/compose.py start master --no-kibana --with-opbeans-node --apm-server-record + * docker cp localtesting_8.0.0_apm-server-2:/app/events.json . && cat events.json | wc -l + * + * * * Run the script: * @@ -26,7 +32,9 @@ const path = require('path'); const axios = require('axios'); const readFile = promisify(fs.readFile); const pLimit = require('p-limit'); +const pRetry = require('p-retry'); const { argv } = require('yargs'); +const ora = require('ora'); const APM_SERVER_URL = argv.serverUrl; const SECRET_TOKEN = argv.secretToken; @@ -42,12 +50,26 @@ if (!EVENTS_PATH) { process.exit(1); } -const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); +const requestProgress = { + succeeded: 0, + failed: 0, + total: 0 +}; + +const spinner = ora({ text: 'Warming up...', stream: process.stdout }); + +function incrementSpinnerCount({ success }) { + success ? requestProgress.succeeded++ : requestProgress.failed++; + const remaining = + requestProgress.total - + (requestProgress.succeeded + requestProgress.failed); + + spinner.text = `Remaining: ${remaining}. Succeeded: ${requestProgress.succeeded}. Failed: ${requestProgress.failed}.`; +} + async function insertItem(item) { try { const url = `${APM_SERVER_URL}${item.url}`; - console.log(Date.now(), url); - const headers = { 'content-type': 'application/x-ndjson' }; @@ -62,21 +84,16 @@ async function insertItem(item) { headers, data: item.body }); - - // add delay to avoid flooding the queue - return delay(500); } catch (e) { - console.log('an error occurred'); - if (e.response) { - console.log(e.response.data); - } else { - console.log('error', e); - } + console.error( + `${e.response ? JSON.stringify(e.response.data) : e.message}` + ); + throw e; } } async function init() { - const content = await readFile(path.resolve(__dirname, EVENTS_PATH)); + const content = await readFile(path.resolve(EVENTS_PATH)); const items = content .toString() .split('\n') @@ -84,10 +101,38 @@ async function init() { .map(item => JSON.parse(item)) .filter(item => item.url === '/intake/v2/events'); + spinner.start(); + requestProgress.total = items.length; + const limit = pLimit(20); // number of concurrent requests - await Promise.all(items.map(item => limit(() => insertItem(item)))); + await Promise.all( + items.map(async item => { + try { + // retry 5 times with exponential backoff + await pRetry(() => limit(() => insertItem(item)), { retries: 5 }); + incrementSpinnerCount({ success: true }); + } catch (e) { + incrementSpinnerCount({ success: false }); + } + }) + ); } -init().catch(e => { - console.log('An error occurred:', e); -}); +init() + .then(() => { + if (requestProgress.succeeded === requestProgress.total) { + spinner.succeed( + `Successfully ingested ${requestProgress.succeeded} of ${requestProgress.total} events` + ); + process.exit(0); + } else { + spinner.fail( + `Ingested ${requestProgress.succeeded} of ${requestProgress.total} events` + ); + process.exit(1); + } + }) + .catch(e => { + console.log('An error occurred:', e); + process.exit(1); + }); diff --git a/x-pack/legacy/plugins/apm/e2e/package.json b/x-pack/legacy/plugins/apm/e2e/package.json index c9026636e64fb..57500dfe3fdc8 100644 --- a/x-pack/legacy/plugins/apm/e2e/package.json +++ b/x-pack/legacy/plugins/apm/e2e/package.json @@ -9,16 +9,19 @@ }, "dependencies": { "@cypress/snapshot": "^2.1.3", - "@cypress/webpack-preprocessor": "^4.1.0", - "@types/cypress-cucumber-preprocessor": "^1.14.0", + "@cypress/webpack-preprocessor": "^4.1.3", + "@types/cypress-cucumber-preprocessor": "^1.14.1", "@types/js-yaml": "^3.12.1", "@types/node": "^10.12.11", - "cypress": "^3.5.0", + "cypress": "^4.2.0", "cypress-cucumber-preprocessor": "^2.0.1", "js-yaml": "^3.13.1", + "ora": "^4.0.3", "p-limit": "^2.2.1", - "ts-loader": "^6.1.0", - "typescript": "3.7.5", - "webpack": "^4.41.5" + "p-retry": "^4.2.0", + "ts-loader": "^6.2.2", + "typescript": "3.8.3", + "wait-on": "^4.0.1", + "webpack": "^4.42.1" } } diff --git a/x-pack/legacy/plugins/apm/e2e/run-e2e.sh b/x-pack/legacy/plugins/apm/e2e/run-e2e.sh new file mode 100755 index 0000000000000..5e55dc1eb834d --- /dev/null +++ b/x-pack/legacy/plugins/apm/e2e/run-e2e.sh @@ -0,0 +1,132 @@ +#!/bin/sh + +# variables +KIBANA_PORT=5701 +ELASTICSEARCH_PORT=9201 +APM_SERVER_PORT=8201 + +# ensure Docker is running +docker ps &> /dev/null +if [ $? -ne 0 ]; then + echo "⚠️ Please start Docker" + exit 1 +fi + +# formatting +bold=$(tput bold) +normal=$(tput sgr0) + +# paths +E2E_DIR="${0%/*}" +TMP_DIR="./tmp" +APM_IT_DIR="./tmp/apm-integration-testing" + +cd ${E2E_DIR} + +# +# Ask user to start Kibana +################################################## +echo "\n${bold}To start Kibana please run the following command:${normal} +node ./scripts/kibana --no-base-path --dev --no-dev-config --config x-pack/legacy/plugins/apm/e2e/ci/kibana.e2e.yml" + +# +# Create tmp folder +################################################## +echo "\n${bold}Temporary folder${normal}" +echo "Temporary files will be stored in: ${TMP_DIR}" +mkdir -p ${TMP_DIR} + +# +# apm-integration-testing +################################################## +printf "\n${bold}apm-integration-testing (logs: ${TMP_DIR}/apm-it.log)\n${normal}" + +# pull if folder already exists +if [ -d ${APM_IT_DIR} ]; then + echo "Pulling from master..." + git -C ${APM_IT_DIR} pull &> ${TMP_DIR}/apm-it.log + +# clone if folder does not exists +else + echo "Cloning repository" + git clone "https://github.com/elastic/apm-integration-testing.git" ${APM_IT_DIR} &> ${TMP_DIR}/apm-it.log +fi + +# Stop if clone/pull failed +if [ $? -ne 0 ]; then + printf "\n⚠️ Initializing apm-integration-testing failed. \n" + exit 1 +fi + +# Start apm-integration-testing +echo "Starting docker-compose" +${APM_IT_DIR}/scripts/compose.py start master \ + --no-kibana \ + --elasticsearch-port $ELASTICSEARCH_PORT \ + --apm-server-port=$APM_SERVER_PORT \ + --elasticsearch-heap 4g \ + &> ${TMP_DIR}/apm-it.log + +# Stop if apm-integration-testing failed to start correctly +if [ $? -ne 0 ]; then + printf "⚠️ apm-integration-testing could not be started.\n" + printf "Please see the logs in ${TMP_DIR}/apm-it.log\n\n" + printf "As a last resort, reset docker with:\n\n cd ${APM_IT_DIR} && scripts/compose.py stop && docker system prune --all --force --volumes\n" + exit 1 +fi + +# +# Static mock data +################################################## +printf "\n${bold}Static mock data (logs: ${TMP_DIR}/ingest-data.log)\n${normal}" + +# Download static data if not already done +if [ ! -e "${TMP_DIR}/events.json" ]; then + echo 'Downloading events.json...' + curl --silent https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output ${TMP_DIR}/events.json +fi + +# echo "Deleting existing indices (apm* and .apm*)" +curl --silent --user admin:changeme -XDELETE "localhost:${ELASTICSEARCH_PORT}/.apm*" > /dev/null +curl --silent --user admin:changeme -XDELETE "localhost:${ELASTICSEARCH_PORT}/apm*" > /dev/null + +# Ingest data into APM Server +node ingest-data/replay.js --server-url http://localhost:$APM_SERVER_PORT --events ${TMP_DIR}/events.json 2> ${TMP_DIR}/ingest-data.log + +# Stop if not all events were ingested correctly +if [ $? -ne 0 ]; then + printf "\n⚠️ Not all events were ingested correctly. This might affect test tests. \n" + exit 1 +fi + +# +# Cypress +################################################## +echo "\n${bold}Cypress (logs: ${TMP_DIR}/e2e-yarn.log)${normal}" +echo "Installing cypress dependencies " +yarn &> ${TMP_DIR}/e2e-yarn.log + +# +# Wait for Kibana to start +################################################## +echo "\n${bold}Waiting for Kibana to start...${normal}" +echo "Note: you need to start Kibana manually. Find the instructions at the top." +yarn wait-on -i 500 -w 500 http://localhost:$KIBANA_PORT > /dev/null + +echo "\n✅ Setup completed successfully. Running tests...\n" + +# +# run cypress tests +################################################## +yarn cypress run --config pageLoadTimeout=100000,watchForFileChanges=true + +# +# Run interactively +################################################## +echo " + +${bold}If you want to run the test interactively, run:${normal} + +yarn cypress open --config pageLoadTimeout=100000,watchForFileChanges=true +" + diff --git a/x-pack/legacy/plugins/apm/e2e/tsconfig.json b/x-pack/legacy/plugins/apm/e2e/tsconfig.json index de498816e30a4..a7091a20186b2 100644 --- a/x-pack/legacy/plugins/apm/e2e/tsconfig.json +++ b/x-pack/legacy/plugins/apm/e2e/tsconfig.json @@ -1,13 +1,8 @@ { "extends": "../../../../tsconfig.json", - "exclude": [], - "include": [ - "./**/*" - ], + "exclude": ["tmp"], + "include": ["./**/*"], "compilerOptions": { - "types": [ - "cypress", - "node" - ] + "types": ["cypress", "node"] } } diff --git a/x-pack/legacy/plugins/apm/e2e/yarn.lock b/x-pack/legacy/plugins/apm/e2e/yarn.lock index 48e6013fb6986..b7b531a9c73c0 100644 --- a/x-pack/legacy/plugins/apm/e2e/yarn.lock +++ b/x-pack/legacy/plugins/apm/e2e/yarn.lock @@ -932,10 +932,10 @@ snap-shot-compare "2.8.3" snap-shot-store "1.2.3" -"@cypress/webpack-preprocessor@^4.1.0": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-4.1.1.tgz#3c0b5b8de6eaac605dac3b1f1c3f5916c1c6eaea" - integrity sha512-SfzDqOvWBSlfGRm8ak/XHUXAnndwHU2qJIRr1LIC7j2UqWcZoJ+286CuNloJbkwfyEAO6tQggLd4E/WHUAcKZQ== +"@cypress/webpack-preprocessor@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-4.1.3.tgz#d5fad767a304c16ec05ca08034827c601f1c9c0c" + integrity sha512-VtTzStrKtwyftLkcgopwCHzgjefK3uHHL6FgbAQP1o5N1pa/zYUb0g7hH2skrMAlKOmLGdbySlISkUl18Y3wHg== dependencies: bluebird "3.7.1" debug "4.1.1" @@ -952,10 +952,62 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@types/cypress-cucumber-preprocessor@^1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@types/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.14.0.tgz#41d8ffb2b608d3ed4ab998a0c4394056f75af1e0" - integrity sha512-bOl4u6seZtxNIGa6J6xydroPntTxxWy8uqIrZ3OY10C96fUes4mZvJKY6NvOoe61/OVafG/UEFa+X2ZWKE6Ltw== +"@hapi/address@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.0.0.tgz#36affb4509b5a6adc628bcc394450f2a7d51d111" + integrity sha512-GDDpkCdSUfkQCznmWUHh9dDN85BWf/V8TFKQ2JLuHdGB4Yy3YTEGBzZxoBNxfNBEvreSR/o+ZxBBSNNEVzY+lQ== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@hapi/formula@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" + integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== + +"@hapi/hoek@^9.0.0": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.0.3.tgz#e49e637d5de8faa4f0d313c2590b455d7c00afd7" + integrity sha512-jKtjLLDiH95b002sJVc5c74PE6KKYftuyVdVmsuYId5stTaWcRFqE+5ukZI4gDUKjGn8wv2C3zPn3/nyjEI7gg== + +"@hapi/joi@^17.1.0": + version "17.1.0" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-17.1.0.tgz#cc4000b6c928a6a39b9bef092151b6bdee10ce55" + integrity sha512-ob67RcPlwRWxBzLCnWvcwx5qbwf88I3ykD7gcJLWOTRfLLgosK7r6aeChz4thA3XRvuBfI0KB1tPVl2EQFlPXw== + dependencies: + "@hapi/address" "^4.0.0" + "@hapi/formula" "^2.0.0" + "@hapi/hoek" "^9.0.0" + "@hapi/pinpoint" "^2.0.0" + "@hapi/topo" "^5.0.0" + +"@hapi/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" + integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== + +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" + integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg== + dependencies: + any-observable "^0.3.0" + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/cypress-cucumber-preprocessor@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@types/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.14.1.tgz#9787f4e89553ebc6359ce157a26ad51ed14aa98b" + integrity sha512-CpYsiQ49UrOmadhFg0G5RkokPUmGGctD01mOWjNxFxHw5VgIRv33L2RyFHL8klaAI4HaedGN3Tcj4HTQ65hn+A== "@types/js-yaml@^3.12.1": version "3.12.2" @@ -967,155 +1019,159 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.14.tgz#b6c60ebf2fb5e4229fdd751ff9ddfae0f5f31541" integrity sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw== +"@types/retry@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + "@types/sizzle@2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== - dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== - -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== - -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== - -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== - dependencies: - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== - -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== - dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" - -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== - -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== - -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" "@wildpeaks/snapshot-dom@1.6.0": @@ -1195,10 +1251,10 @@ am-i-a-dependency@1.1.2: resolved "https://registry.yarnpkg.com/am-i-a-dependency/-/am-i-a-dependency-1.1.2.tgz#f9d3422304d6f642f821e4c407565035f6167f1f" integrity sha1-+dNCIwTW9kL4IeTEB1ZQNfYWfx8= -ansi-escapes@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= +ansi-escapes@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-regex@^2.0.0: version "2.1.1" @@ -1215,6 +1271,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.0.1, ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1227,6 +1288,19 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== + any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -1240,7 +1314,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== @@ -1250,14 +1324,6 @@ arch@2.1.1: resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1338,12 +1404,10 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" +async@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== asynckit@^0.4.0: version "0.4.0" @@ -1447,11 +1511,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bluebird@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" - integrity sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw= - bluebird@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" @@ -1462,7 +1521,7 @@ bluebird@3.7.1: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== -bluebird@^3.4.1, bluebird@^3.5.5: +bluebird@3.7.2, bluebird@^3.4.1, bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -1781,12 +1840,10 @@ cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== -cachedir@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-1.3.0.tgz#5e01928bf2d95b5edd94b0942188246740e0dbc4" - integrity sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg== - dependencies: - os-homedir "^1.0.1" +cachedir@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" + integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== caniuse-lite@^1.0.30001023: version "1.0.30001027" @@ -1810,7 +1867,7 @@ chai@^4.1.2: pathval "^1.1.0" type-detect "^4.0.5" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1830,6 +1887,14 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -1871,10 +1936,10 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -1901,10 +1966,34 @@ cli-cursor@^1.0.2: dependencies: restore-cursor "^1.0.1" -cli-spinners@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" - integrity sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw= +cli-cursor@^2.0.0, cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" + integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== + +cli-table3@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" cli-table@^0.3.1: version "0.3.1" @@ -1921,6 +2010,11 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -1954,11 +2048,23 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -1986,10 +2092,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +commander@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.0.tgz#545983a0603fe425bc672d66c9e3c89c42121a83" + integrity sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw== commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: version "2.20.3" @@ -2039,11 +2145,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0, constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2242,42 +2343,45 @@ cypress-cucumber-preprocessor@^2.0.1: minimist "^1.2.0" through "^2.3.8" -cypress@^3.5.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.8.3.tgz#e921f5482f1cbe5814891c878f26e704bbffd8f4" - integrity sha512-I9L/d+ilTPPA4vq3NC1OPKmw7jJIpMKNdyfR8t1EXYzYCjyqbc59migOm1YSse/VRbISLJ+QGb5k4Y3bz2lkYw== +cypress@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.2.0.tgz#45673fb648b1a77b9a78d73e58b89ed05212d243" + integrity sha512-8LdreL91S/QiTCLYLNbIjLL8Ht4fJmu/4HGLxUI20Tc7JSfqEfCmXELrRfuPT0kjosJwJJZacdSji9XSRkPKUw== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" "@types/sizzle" "2.3.2" arch "2.1.1" - bluebird "3.5.0" - cachedir "1.3.0" + bluebird "3.7.2" + cachedir "2.3.0" chalk "2.4.2" check-more-types "2.24.0" - commander "2.15.1" + cli-table3 "0.5.1" + commander "4.1.0" common-tags "1.8.0" - debug "3.2.6" + debug "4.1.1" eventemitter2 "4.1.2" - execa "0.10.0" + execa "1.0.0" executable "4.1.1" extract-zip "1.6.7" - fs-extra "5.0.0" - getos "3.1.1" - is-ci "1.2.1" + fs-extra "8.1.0" + getos "3.1.4" + is-ci "2.0.0" is-installed-globally "0.1.0" lazy-ass "1.6.0" - listr "0.12.0" + listr "0.14.3" lodash "4.17.15" - log-symbols "2.2.0" - minimist "1.2.0" + log-symbols "3.0.0" + minimist "1.2.2" moment "2.24.0" - ramda "0.24.1" - request "2.88.0" + ospath "1.2.2" + pretty-bytes "5.3.0" + ramda "0.26.1" + request cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16 request-progress "3.0.0" - supports-color "5.5.0" + supports-color "7.1.0" tmp "0.1.0" - untildify "3.0.3" + untildify "4.0.0" url "0.11.0" yauzl "2.10.0" @@ -2320,13 +2424,6 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.1, debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@4.1.1, debug@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -2334,6 +2431,13 @@ debug@4.1.1, debug@^4.1.0: dependencies: ms "^2.1.1" +debug@^3.0.1, debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2346,10 +2450,12 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" define-properties@^1.1.2: version "1.1.3" @@ -2390,11 +2496,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - deps-sort@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" @@ -2413,11 +2514,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -2651,13 +2747,13 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== +execa@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: cross-spawn "^6.0.0" - get-stream "^3.0.0" + get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" @@ -2784,7 +2880,7 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== -figures@2.0.0: +figures@2.0.0, figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= @@ -2889,15 +2985,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -2907,12 +2994,14 @@ fs-extra@7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== +fs-extra@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== dependencies: - minipass "^2.6.0" + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" fs-write-stream-atomic@^1.0.8: version "1.0.10" @@ -2942,20 +3031,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - gensync@^1.0.0-beta.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" @@ -2971,22 +3046,24 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= -getos@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.1.tgz#967a813cceafee0156b0483f7cffa5b3eff029c5" - integrity sha512-oUP1rnEhAr97rkitiszGP9EgDVYnmchgFzfqRzSkgtfv7ai6tEi7Ko8GgjNXts7VLWEqrTWyhsOKLe5C5b/Zkg== +getos@3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.4.tgz#29cdf240ed10a70c049add7b6f8cb08c81876faf" + integrity sha512-UORPzguEB/7UG5hqiZai8f0vQ7hzynMQyJLxStoQ8dPGAcmgsfXOPA4iE/fGtweHYkK+z4zc9V0g+CIFRf5HYw== dependencies: - async "2.6.1" + async "^3.1.0" getpass@^0.1.1: version "0.1.7" @@ -3032,7 +3109,7 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== @@ -3042,7 +3119,7 @@ har-schema@^2.0.0: resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0: +har-validator@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== @@ -3062,16 +3139,16 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -3154,13 +3231,6 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -3171,25 +3241,11 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - indent-string@^3.0.0, indent-string@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" @@ -3223,7 +3279,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -3289,12 +3345,12 @@ is-buffer@^1.1.0, is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-ci@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== +is-ci@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== dependencies: - ci-info "^1.5.0" + ci-info "^2.0.0" is-data-descriptor@^0.1.4: version "0.1.4" @@ -3350,11 +3406,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -3394,6 +3445,11 @@ is-installed-globally@0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3406,6 +3462,13 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== + dependencies: + symbol-observable "^1.1.0" + is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -3655,10 +3718,10 @@ listr-silent-renderer@^1.1.1: resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= -listr-update-renderer@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" - integrity sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk= +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== dependencies: chalk "^1.1.3" cli-truncate "^0.2.1" @@ -3666,40 +3729,33 @@ listr-update-renderer@^0.2.0: figures "^1.7.0" indent-string "^3.0.0" log-symbols "^1.0.2" - log-update "^1.0.2" + log-update "^2.3.0" strip-ansi "^3.0.1" -listr-verbose-renderer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" - integrity sha1-ggb0z21S3cWCfl/RSYng6WWTOjU= +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== dependencies: - chalk "^1.1.3" - cli-cursor "^1.0.2" + chalk "^2.4.1" + cli-cursor "^2.1.0" date-fns "^1.27.2" - figures "^1.7.0" + figures "^2.0.0" -listr@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" - integrity sha1-a84sD1YD+klYDqF81qAMwOX6RRo= +listr@0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - figures "^1.7.0" - indent-string "^2.1.0" + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" is-promise "^2.1.0" is-stream "^1.1.0" listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.2.0" - listr-verbose-renderer "^0.4.0" - log-symbols "^1.0.2" - log-update "^1.0.2" - ora "^0.2.3" - p-map "^1.1.1" - rxjs "^5.0.0-beta.11" - stream-to-observable "^0.1.0" - strip-ansi "^3.0.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" loader-runner@^2.4.0: version "2.4.0" @@ -3738,17 +3794,17 @@ lodash.once@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash@4.17.15, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.4: +lodash@4.17.15, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== +log-symbols@3.0.0, log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: - chalk "^2.0.1" + chalk "^2.4.2" log-symbols@^1.0.2: version "1.0.2" @@ -3757,13 +3813,14 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-update@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" - integrity sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE= +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= dependencies: - ansi-escapes "^1.0.0" - cli-cursor "^1.0.2" + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" loose-envify@^1.0.0: version "1.4.0" @@ -3800,11 +3857,6 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -3889,6 +3941,16 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.43.0" +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -3911,25 +3973,20 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: +minimist@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.2.tgz#b00a00230a1108c48c169e69a291aafda3aacd63" + integrity sha512-rIqbOrKb8GJmx/5bc2M0QchhUouMXSpd1RTclXsB41JdL+VtnojfaJR+h7F9k18/4kHUsBFgk80Uk+q569vjPA== + +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== mississippi@^3.0.0: version "3.0.0" @@ -3962,6 +4019,13 @@ mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" +mkdirp@^0.5.3: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" + integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== + dependencies: + minimist "^1.2.5" + module-deps@^6.0.0: version "6.2.2" resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.2.tgz#d8a15c2265dfc119153c29bb47386987d0ee423b" @@ -4010,6 +4074,11 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mz@^2.4.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -4041,15 +4110,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -needle@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528" - integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" @@ -4101,22 +4161,6 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.1.47: version "1.1.48" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.48.tgz#7f647f0c453a0495bcd64cbd4778c26035c2f03a" @@ -4124,7 +4168,7 @@ node-releases@^1.1.47: dependencies: semver "^6.3.0" -nopt@^4.0.1, nopt@~4.0.1: +nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= @@ -4144,27 +4188,6 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.8" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" - integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-normalize-package-bin "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -4172,16 +4195,6 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -4247,22 +4260,40 @@ onetime@^1.0.0: resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= -ora@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" - integrity sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q= +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: - chalk "^1.1.1" - cli-cursor "^1.0.2" - cli-spinners "^0.1.2" - object-assign "^4.0.1" + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +ora@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.3.tgz#752a1b7b4be4825546a7a3d59256fa523b6b6d05" + integrity sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg== + dependencies: + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-spinners "^2.2.0" + is-interactive "^1.0.0" + log-symbols "^3.0.0" + mute-stream "0.0.8" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" os-browserify@^0.3.0, os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -4280,6 +4311,11 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +ospath@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" + integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= + outpipe@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/outpipe/-/outpipe-1.1.1.tgz#50cf8616365e87e031e29a5ec9339a3da4725fa2" @@ -4306,10 +4342,18 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-retry@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.2.0.tgz#ea9066c6b44f23cab4cd42f6147cdbbc6604da5d" + integrity sha512-jPH38/MRh263KKcq0wBNOGFJbm+U6784RilTmHjB/HM9kH9V8WlCpVUcdOmip9cjXOh6MxZ5yk1z2SjDUJfWmA== + dependencies: + "@types/retry" "^0.12.0" + retry "^0.12.0" p-try@^2.0.0: version "2.2.0" @@ -4462,6 +4506,11 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +pretty-bytes@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" + integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== + private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -4502,7 +4551,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24: +psl@^1.1.28: version "1.7.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== @@ -4549,12 +4598,12 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -4574,16 +4623,16 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -ramda@0.24.1: - version "0.24.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" - integrity sha1-w7d1UZfzW43DUCIoJixMkd22uFc= - ramda@0.25.0: version "0.25.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== +ramda@0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -4599,16 +4648,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - read-only-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" @@ -4616,7 +4655,7 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -4723,13 +4762,6 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-progress@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" @@ -4737,10 +4769,26 @@ request-progress@3.0.0: dependencies: throttleit "^1.0.0" -request@2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + +request-promise-native@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + dependencies: + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" @@ -4749,7 +4797,7 @@ request@2.88.0: extend "~3.0.2" forever-agent "~0.6.1" form-data "~2.3.2" - har-validator "~5.1.0" + har-validator "~5.1.3" http-signature "~1.2.0" is-typedarray "~1.0.0" isstream "~0.1.2" @@ -4759,7 +4807,32 @@ request@2.88.0: performance-now "^2.1.0" qs "~6.5.2" safe-buffer "^5.1.2" - tough-cookie "~2.4.3" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +request@cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16: + version "2.88.1" + resolved "https://codeload.github.com/cypress-io/request/tar.gz/b5af0d1fa47eec97ba980cde90a13e69a2afcd16" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" tunnel-agent "^0.6.0" uuid "^3.3.2" @@ -4793,12 +4866,33 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4820,12 +4914,12 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^5.0.0-beta.11: - version "5.5.12" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" - integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== +rxjs@^6.3.3, rxjs@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: - symbol-observable "1.0.1" + tslib "^1.9.0" safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" @@ -4844,16 +4938,11 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -4873,7 +4962,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -4893,11 +4982,6 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -4958,7 +5042,7 @@ sigmund@^1.0.1: resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= @@ -5147,6 +5231,11 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -5205,11 +5294,6 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" -stream-to-observable@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" - integrity sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4= - string-argv@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" @@ -5224,7 +5308,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2": +string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5267,16 +5351,18 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" @@ -5284,22 +5370,29 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@5.5.0, supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== +supports-color@7.1.0, supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: - has-flag "^3.0.0" + has-flag "^4.0.0" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== syntax-error@^1.1.1: version "1.4.0" @@ -5313,19 +5406,6 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - terser-webpack-plugin@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" @@ -5453,18 +5533,18 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: - psl "^1.1.24" - punycode "^1.4.1" + psl "^1.1.28" + punycode "^2.1.1" -ts-loader@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.1.tgz#67939d5772e8a8c6bdaf6277ca023a4812da02ef" - integrity sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g== +ts-loader@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" + integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" @@ -5519,10 +5599,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.7.5: - version "3.7.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" - integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== +typescript@3.8.3: + version "3.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" + integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== umd@^3.0.0: version "3.0.3" @@ -5600,10 +5680,10 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -untildify@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" - integrity sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA== +untildify@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== upath@^1.1.1: version "1.2.0" @@ -5698,6 +5778,18 @@ vm-browserify@^1.0.0, vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +wait-on@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-4.0.1.tgz#c49ca18b1ea60580404feed9df76ab3af2425a56" + integrity sha512-x83fmTH2X0KL7vXoGt9aV5x4SMCvO8A/NbwWpaYYh4NJ16d3KSgbHwBy9dVdHj0B30cEhOFRvDob4fnpUmZxvA== + dependencies: + "@hapi/joi" "^17.1.0" + lodash "^4.17.15" + minimist "^1.2.0" + request "^2.88.0" + request-promise-native "^1.0.8" + rxjs "^6.5.4" + watchify@3.11.1: version "3.11.1" resolved "https://registry.yarnpkg.com/watchify/-/watchify-3.11.1.tgz#8e4665871fff1ef64c0430d1a2c9d084d9721881" @@ -5720,6 +5812,13 @@ watchpack@^1.6.0: graceful-fs "^4.1.2" neo-async "^2.5.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + webpack-sources@^1.4.0, webpack-sources@^1.4.1: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" @@ -5728,15 +5827,15 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.40.2: - version "4.41.5" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" - integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== +webpack@^4.42.1: + version "4.42.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.1.tgz#ae707baf091f5ca3ef9c38b884287cfe8f1983ef" + integrity sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" acorn "^6.2.1" ajv "^6.10.2" ajv-keywords "^3.4.1" @@ -5748,7 +5847,7 @@ webpack@^4.40.2: loader-utils "^1.2.3" memory-fs "^0.4.1" micromatch "^3.1.10" - mkdirp "^0.5.1" + mkdirp "^0.5.3" neo-async "^2.6.1" node-libs-browser "^2.2.1" schema-utils "^1.0.0" @@ -5764,13 +5863,6 @@ which@^1.2.9: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - worker-farm@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" @@ -5778,6 +5870,14 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -5798,7 +5898,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== diff --git a/x-pack/legacy/plugins/apm/mappings.json b/x-pack/legacy/plugins/apm/mappings.json index ba4c7a89ceaa8..5d14ae03f9a33 100644 --- a/x-pack/legacy/plugins/apm/mappings.json +++ b/x-pack/legacy/plugins/apm/mappings.json @@ -136,7 +136,20 @@ "service": { "properties": { "framework": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } }, "language": { "properties": { @@ -187,18 +200,52 @@ "service": { "properties": { "framework": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } }, "language": { "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, "name": { "type": "keyword", "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 } } }, "runtime": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } } } } @@ -234,9 +281,17 @@ }, "language": { "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, "name": { "type": "keyword", "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 } } }, @@ -391,18 +446,62 @@ "rum-js": { "properties": { "agent": { - "type": "object" + "properties": { + "version": { + "type": "keyword", + "ignore_above": 256 + } + } }, "service": { "properties": { "framework": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } }, "language": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } }, "runtime": { - "type": "object" + "properties": { + "composite": { + "type": "keyword", + "ignore_above": 256 + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "version": { + "type": "keyword", + "ignore_above": 256 + } + } } } } diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Controls.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Controls.tsx index a2e7b2c76031e..eabd967e6efe9 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Controls.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Controls.tsx @@ -41,9 +41,17 @@ const steps = 5; function doZoom(cy: cytoscape.Core | undefined, increment: number) { if (cy) { const level = cy.zoom() + increment; + // @ts-ignore `.position()` _does_ work on a NodeCollection. It returns the position of the first element in the collection. + const primaryCenter = cy.nodes('.primary').position(); + const { x1, y1, w, h } = cy.nodes().boundingBox({}); + const graphCenter = { x: x1 + w / 2, y: y1 + h / 2 }; + cy.animate({ duration, - zoom: { level, position: cy.$('.primary').position() } + zoom: { + level, + position: primaryCenter || graphCenter + } }); } } diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index a4cd6f4ed09a9..7bdc6aebbd9a0 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -13,6 +13,7 @@ import React, { useRef, useState } from 'react'; +import { debounce } from 'lodash'; import { isRumAgentName } from '../../../../../../../plugins/apm/common/agent_name'; import { AGENT_NAME } from '../../../../../../../plugins/apm/common/elasticsearch_fieldnames'; import { @@ -20,6 +21,7 @@ import { cytoscapeOptions, nodeHeight } from './cytoscapeOptions'; +import { useUiTracker } from '../../../../../../../plugins/observability/public'; export const CytoscapeContext = createContext( undefined @@ -117,6 +119,8 @@ export function Cytoscape({ // is required and can trigger rendering when changed. const divStyle = { ...style, height }; + const trackApmEvent = useUiTracker({ app: 'apm' }); + // Trigger a custom "data" event when data changes useEffect(() => { if (cy && elements.length > 0) { @@ -168,7 +172,13 @@ export function Cytoscape({ } }); }; + // debounce hover tracking so it doesn't spam telemetry with redundant events + const trackNodeEdgeHover = debounce( + () => trackApmEvent({ metric: 'service_map_node_or_edge_hover' }), + 1000 + ); const mouseoverHandler: cytoscape.EventHandler = event => { + trackNodeEdgeHover(); event.target.addClass('hover'); event.target.connectedEdges().addClass('nodeHover'); }; @@ -177,6 +187,7 @@ export function Cytoscape({ event.target.connectedEdges().removeClass('nodeHover'); }; const selectHandler: cytoscape.EventHandler = event => { + trackApmEvent({ metric: 'service_map_node_select' }); resetConnectedEdgeStyle(event.target); }; const unselectHandler: cytoscape.EventHandler = event => { @@ -215,7 +226,7 @@ export function Cytoscape({ cy.removeListener('unselect', 'node', unselectHandler); } }; - }, [cy, height, serviceName, width]); + }, [cy, height, serviceName, trackApmEvent, width]); return ( diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts index 413458f336e6f..0438842f7af10 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts @@ -62,7 +62,7 @@ const style: cytoscape.Stylesheet[] = [ isService(el) ? el.data(SERVICE_NAME) : el.data(SPAN_DESTINATION_SERVICE_RESOURCE), - 'min-zoomed-font-size': theme.euiSizeL, + 'min-zoomed-font-size': parseInt(theme.euiSizeL, 10), 'overlay-opacity': 0, shape: (el: cytoscape.NodeSingular) => isService(el) ? 'ellipse' : 'diamond', @@ -70,7 +70,7 @@ const style: cytoscape.Stylesheet[] = [ 'text-background-opacity': 0, 'text-background-padding': theme.paddingSizes.xs, 'text-background-shape': 'roundrectangle', - 'text-margin-y': theme.paddingSizes.s, + 'text-margin-y': parseInt(theme.paddingSizes.s, 10), 'text-max-width': '200px', 'text-valign': 'bottom', 'text-wrap': 'ellipsis', @@ -105,8 +105,8 @@ const style: cytoscape.Stylesheet[] = [ 'source-arrow-color': lineColor, 'target-arrow-shape': 'triangle', // @ts-ignore - 'source-distance-from-node': theme.paddingSizes.xs, - 'target-distance-from-node': theme.paddingSizes.xs + 'source-distance-from-node': parseInt(theme.paddingSizes.xs, 10), + 'target-distance-from-node': parseInt(theme.paddingSizes.xs, 10) } }, // @ts-ignore DefinitelyTyped says visibility is "none" but it's diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx index 4974553f6ca93..0abaa9d76fc07 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx @@ -23,6 +23,7 @@ import { EmptyBanner } from './EmptyBanner'; import { Popover } from './Popover'; import { useRefDimensions } from './useRefDimensions'; import { BetaBadge } from './BetaBadge'; +import { useTrackPageview } from '../../../../../../../plugins/observability/public'; interface ServiceMapProps { serviceName?: string; @@ -30,7 +31,7 @@ interface ServiceMapProps { export function ServiceMap({ serviceName }: ServiceMapProps) { const license = useLicense(); - const { urlParams, uiFilters } = useUrlParams(); + const { urlParams } = useUrlParams(); const { data } = useFetcher(() => { const { start, end, environment } = urlParams; @@ -42,19 +43,18 @@ export function ServiceMap({ serviceName }: ServiceMapProps) { start, end, environment, - serviceName, - uiFilters: JSON.stringify({ - ...uiFilters, - environment: undefined - }) + serviceName } } }); } - }, [serviceName, uiFilters, urlParams]); + }, [serviceName, urlParams]); const { ref, height, width } = useRefDimensions(); + useTrackPageview({ app: 'apm', path: 'service_map' }); + useTrackPageview({ app: 'apm', path: 'service_map', delay: 15000 }); + if (!license) { return null; } diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx index de058d6ef973a..c1afa433cb614 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/NoServicesMessage.tsx @@ -58,7 +58,7 @@ export function NoServicesMessage({ historicalDataFound, status }: Props) {

{i18n.translate('xpack.apm.servicesTable.7xUpgradeServerMessage', { defaultMessage: `Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0.` + your APM Server instance(s) to at least 7.0.` })}

diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap index 209b88f73b9e2..227becb9a9c4f 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/NoServicesMessage.test.tsx.snap @@ -19,7 +19,7 @@ exports[`NoServicesMessage status: pending and historicalDataFound: false 1`] =

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. @@ -64,7 +64,7 @@ exports[`NoServicesMessage status: success and historicalDataFound: false 1`] =

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap index d85c83661ea49..dd0c50af2b03f 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap @@ -72,7 +72,7 @@ NodeList [ >

Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM server instance(s) to at least 7.0. + your APM Server instance(s) to at least 7.0.

You may also have old data that needs to be migrated. diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx index 1c253b2fa8bff..fdef9e1f5b7e7 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FiltersSection.tsx @@ -16,10 +16,12 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React from 'react'; -import { FilterOptions } from '../../../../../../../../../../plugins/apm/common/custom_link_filter_options'; +import { + Filter, + FilterKey +} from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { DEFAULT_OPTION, - FilterKeyValue, FILTER_SELECT_OPTIONS, getSelectOptions } from './helper'; @@ -28,12 +30,16 @@ export const FiltersSection = ({ filters, onChangeFilters }: { - filters: FilterKeyValue[]; - onChangeFilters: (filters: FilterKeyValue[]) => void; + filters: Filter[]; + onChangeFilters: (filters: Filter[]) => void; }) => { - const onChangeFilter = (filter: FilterKeyValue, idx: number) => { + const onChangeFilter = ( + key: Filter['key'], + value: Filter['value'], + idx: number + ) => { const newFilters = [...filters]; - newFilters[idx] = filter; + newFilters[idx] = { key, value }; onChangeFilters(newFilters); }; @@ -45,14 +51,14 @@ export const FiltersSection = ({ // if there is only one item left it should not be removed // but reset to empty if (isEmpty(newFilters)) { - onChangeFilters([['', '']]); + onChangeFilters([{ key: '', value: '' }]); } else { onChangeFilters(newFilters); } }; const handleAddFilter = () => { - onChangeFilters([...filters, ['', '']]); + onChangeFilters([...filters, { key: '', value: '' }]); }; return ( @@ -81,7 +87,7 @@ export const FiltersSection = ({ {filters.map((filter, idx) => { - const [key, value] = filter; + const { key, value } = filter; const filterId = `filter-${idx}`; const selectOptions = getSelectOptions(filters, key); return ( @@ -100,10 +106,7 @@ export const FiltersSection = ({ } )} onChange={e => - onChangeFilter( - [e.target.value as keyof FilterOptions, value], - idx - ) + onChangeFilter(e.target.value as FilterKey, value, idx) } isInvalid={ !isEmpty(value) && @@ -119,7 +122,7 @@ export const FiltersSection = ({ 'xpack.apm.settings.customizeUI.customLink.flyOut.filters.defaultOption.value', { defaultMessage: 'Value' } )} - onChange={e => onChangeFilter([key, e.target.value], idx)} + onChange={e => onChangeFilter(key, e.target.value, idx)} value={value} isInvalid={!isEmpty(key) && isEmpty(value)} /> diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx index 9b487cf916089..2f4d9a4c4016d 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.test.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; import { LinkPreview } from '../CustomLinkFlyout/LinkPreview'; -import { render, getNodeText, getByTestId } from '@testing-library/react'; +import { render, getNodeText, getByTestId, act } from '@testing-library/react'; describe('LinkPreview', () => { const getElementValue = (container: HTMLElement, id: string) => @@ -15,37 +15,47 @@ describe('LinkPreview', () => { ); it('shows label and url default values', () => { - const { container } = render( - - ); - expect(getElementValue(container, 'preview-label')).toEqual('Elastic.co'); - expect(getElementValue(container, 'preview-url')).toEqual( - 'https://www.elastic.co' - ); + act(() => { + const { container } = render( + + ); + expect(getElementValue(container, 'preview-label')).toEqual('Elastic.co'); + expect(getElementValue(container, 'preview-url')).toEqual( + 'https://www.elastic.co' + ); + }); }); it('shows label and url values', () => { - const { container } = render( - - ); - expect(getElementValue(container, 'preview-label')).toEqual('foo'); - expect( - (getByTestId(container, 'preview-link') as HTMLAnchorElement).text - ).toEqual('https://baz.co'); + act(() => { + const { container } = render( + + ); + expect(getElementValue(container, 'preview-label')).toEqual('foo'); + expect( + (getByTestId(container, 'preview-link') as HTMLAnchorElement).text + ).toEqual('https://baz.co'); + }); }); it('shows warning when couldnt replace context variables', () => { - const { container } = render( - - ); - expect(getElementValue(container, 'preview-label')).toEqual('foo'); - expect( - (getByTestId(container, 'preview-link') as HTMLAnchorElement).text - ).toEqual('https://baz.co?service.name={{invalid}'); - expect(getByTestId(container, 'preview-warning')).toBeInTheDocument(); + act(() => { + const { container } = render( + + ); + expect(getElementValue(container, 'preview-label')).toEqual('foo'); + expect( + (getByTestId(container, 'preview-link') as HTMLAnchorElement).text + ).toEqual('https://baz.co?service.name={{invalid}'); + expect(getByTestId(container, 'preview-warning')).toBeInTheDocument(); + }); }); }); diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx index 0ad3455ab271f..8edfb176a1af8 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkPreview.tsx @@ -17,28 +17,22 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; +import { Filter } from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; import { callApmApi } from '../../../../../../services/rest/createCallApmApi'; -import { - FilterKeyValue, - convertFiltersToObject, - replaceTemplateVariables -} from './helper'; +import { replaceTemplateVariables, convertFiltersToQuery } from './helper'; interface Props { label: string; url: string; - filters: FilterKeyValue[]; + filters: Filter[]; } const fetchTransaction = debounce( - async ( - filters: FilterKeyValue[], - callback: (transaction: Transaction) => void - ) => { + async (filters: Filter[], callback: (transaction: Transaction) => void) => { const transaction = await callApmApi({ pathname: '/api/apm/settings/custom_links/transaction', - params: { query: convertFiltersToObject(filters) } + params: { query: convertFiltersToQuery(filters) } }); callback(transaction); }, @@ -51,7 +45,20 @@ export const LinkPreview = ({ label, url, filters }: Props) => { const [transaction, setTransaction] = useState(); useEffect(() => { - fetchTransaction(filters, setTransaction); + /* + React throwns "Can't perform a React state update on an unmounted component" + It happens when the Custom Link flyout is closed before the return of the api request. + To avoid such case, sets the isUnmounted to true when component unmount and check its value before update the transaction. + */ + let isUnmounted = false; + fetchTransaction(filters, (_transaction: Transaction) => { + if (!isUnmounted) { + setTransaction(_transaction); + } + }); + return () => { + isUnmounted = true; + }; }, [filters]); const { formattedUrl, error } = replaceTemplateVariables(url, transaction); diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx index 8bcebc2aea09e..630f7148ad408 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/LinkSection.tsx @@ -12,7 +12,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; +import { CustomLink } from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Documentation } from './Documentation'; interface InputField { diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts index ac01ee48f2fe5..0a63cfcff9aa5 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.test.ts @@ -4,79 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ import { - convertFiltersToArray, - convertFiltersToObject, getSelectOptions, replaceTemplateVariables } from '../CustomLinkFlyout/helper'; -import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; describe('Custom link helper', () => { - describe('convertFiltersToArray', () => { - it('returns array of tuple when custom link not defined', () => { - expect(convertFiltersToArray()).toEqual([['', '']]); - }); - it('returns filters as array', () => { - expect( - convertFiltersToArray({ - 'service.name': 'foo', - 'transaction.type': 'bar' - } as CustomLink) - ).toEqual([ - ['service.name', 'foo'], - ['transaction.type', 'bar'] - ]); - }); - it('returns empty when no filter is added', () => { - expect( - convertFiltersToArray({ - label: 'foo', - url: 'bar' - } as CustomLink) - ).toEqual([['', '']]); - }); - }); - - describe('convertFiltersToObject', () => { - it('returns undefined when any filter is added', () => { - expect(convertFiltersToObject([['', '']])).toBeUndefined(); - }); - it('removes uncompleted filters', () => { - expect( - convertFiltersToObject([ - ['service.name', ''], - ['', 'foo'], - ['transaction.type', 'bar'] - ]) - ).toEqual({ 'transaction.type': ['bar'] }); - }); - it('splits the value by comma', () => { - expect( - convertFiltersToObject([ - ['service.name', 'foo'], - ['service.environment', 'foo, bar'], - ['transaction.type', 'foo, '], - ['transaction.name', 'foo,'] - ]) - ).toEqual({ - 'service.name': ['foo'], - 'service.environment': ['foo', 'bar'], - 'transaction.type': ['foo'], - 'transaction.name': ['foo'] - }); - }); - }); - describe('getSelectOptions', () => { it('returns all available options when no filters were selected', () => { expect( getSelectOptions( [ - ['', ''], - ['', ''], - ['', ''], - ['', ''] + { key: '', value: '' }, + { key: '', value: '' }, + { key: '', value: '' }, + { key: '', value: '' } ], '' ) @@ -92,10 +34,10 @@ describe('Custom link helper', () => { expect( getSelectOptions( [ - ['service.name', 'foo'], - ['', ''], - ['', ''], - ['', ''] + { key: 'service.name', value: 'foo' }, + { key: '', value: '' }, + { key: '', value: '' }, + { key: '', value: '' } ], '' ) @@ -110,10 +52,10 @@ describe('Custom link helper', () => { expect( getSelectOptions( [ - ['service.name', 'foo'], - ['transaction.name', 'bar'], - ['', ''], - ['', ''] + { key: 'service.name', value: 'foo' }, + { key: 'transaction.name', value: 'bar' }, + { key: '', value: '' }, + { key: '', value: '' } ], 'transaction.name' ) @@ -128,10 +70,10 @@ describe('Custom link helper', () => { expect( getSelectOptions( [ - ['service.name', 'foo'], - ['transaction.name', 'bar'], - ['service.environment', 'baz'], - ['transaction.type', 'qux'] + { key: 'service.name', value: 'foo' }, + { key: 'transaction.name', value: 'bar' }, + { key: 'service.environment', value: 'baz' }, + { key: 'transaction.type', value: 'qux' } ], '' ) diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts index df99c82c71b70..7bfdbf1655e0d 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper.ts @@ -5,80 +5,19 @@ */ import { i18n } from '@kbn/i18n'; import Mustache from 'mustache'; -import { isEmpty, pick, get } from 'lodash'; -import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; +import { isEmpty, get } from 'lodash'; +import { FILTER_OPTIONS } from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_filter_options'; import { - FilterOptions, - FILTER_OPTIONS -} from '../../../../../../../../../../plugins/apm/common/custom_link_filter_options'; -import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; - -type FilterKey = keyof FilterOptions | ''; -type FilterValue = string; -export type FilterKeyValue = [FilterKey, FilterValue]; + Filter, + FilterKey +} from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; +import { Transaction } from '../../../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; interface FilterSelectOption { - value: 'DEFAULT' | keyof FilterOptions; + value: 'DEFAULT' | FilterKey; text: string; } -/** - * Converts available filters from the Custom Link to Array of filters. - * e.g. - * customLink = { - * id: '1', - * label: 'foo', - * url: 'http://www.elastic.co', - * service.name: 'opbeans-java', - * transaction.type: 'request' - * } - * - * results: [['service.name', 'opbeans-java'],['transaction.type', 'request']] - * @param customLink - */ -export const convertFiltersToArray = ( - customLink?: CustomLink -): FilterKeyValue[] => { - if (customLink) { - const filters = Object.entries( - pick(customLink, FILTER_OPTIONS) - ) as FilterKeyValue[]; - if (!isEmpty(filters)) { - return filters; - } - } - return [['', '']]; -}; - -/** - * Converts array of filters into object. - * e.g. - * filters: [['service.name', 'opbeans-java'],['transaction.type', 'request']] - * - * results: { - * 'service.name': 'opbeans-java', - * 'transaction.type': 'request' - * } - * @param filters - */ -export const convertFiltersToObject = (filters: FilterKeyValue[]) => { - const convertedFilters = Object.fromEntries( - filters - .filter(([key, value]) => !isEmpty(key) && !isEmpty(value)) - .map(([key, value]) => [ - key, - // Splits the value by comma, removes whitespace from both ends and filters out empty values - value - .split(',') - .map(v => v.trim()) - .filter(v => v) - ]) - ); - if (!isEmpty(convertedFilters)) { - return convertedFilters; - } -}; - export const DEFAULT_OPTION: FilterSelectOption = { value: 'DEFAULT', text: i18n.translate( @@ -90,7 +29,7 @@ export const DEFAULT_OPTION: FilterSelectOption = { export const FILTER_SELECT_OPTIONS: FilterSelectOption[] = [ DEFAULT_OPTION, ...FILTER_OPTIONS.map(filter => ({ - value: filter as keyof FilterOptions, + value: filter, text: filter })) ]; @@ -102,14 +41,12 @@ export const FILTER_SELECT_OPTIONS: FilterSelectOption[] = [ * @param selectedKey */ export const getSelectOptions = ( - filters: FilterKeyValue[], - selectedKey: FilterKey + filters: Filter[], + selectedKey: Filter['key'] ) => { return FILTER_SELECT_OPTIONS.filter( ({ value }) => - !filters.some( - ([filterKey]) => filterKey === value && filterKey !== selectedKey - ) + !filters.some(({ key }) => key === value && key !== selectedKey) ); }; @@ -172,3 +109,12 @@ export const replaceTemplateVariables = ( return { formattedUrl: url, error }; } }; + +export const convertFiltersToQuery = (filters: Filter[]) => { + return filters.reduce((acc: Record, { key, value }) => { + if (key && value) { + acc[key] = value; + } + return acc; + }, {}); +}; diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx index 68755bad5f652..7412eb4577860 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/index.tsx @@ -14,13 +14,15 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; -import { CustomLink } from '../../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; +import { + CustomLink, + Filter +} from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { useApmPluginContext } from '../../../../../../hooks/useApmPluginContext'; import { FiltersSection } from './FiltersSection'; import { FlyoutFooter } from './FlyoutFooter'; import { LinkSection } from './LinkSection'; import { saveCustomLink } from './saveCustomLink'; -import { convertFiltersToArray, convertFiltersToObject } from './helper'; import { LinkPreview } from './LinkPreview'; import { Documentation } from './Documentation'; @@ -42,8 +44,11 @@ export const CustomLinkFlyout = ({ const [label, setLabel] = useState(customLinkSelected?.label || ''); const [url, setUrl] = useState(customLinkSelected?.url || ''); + const selectedFilters = customLinkSelected?.filters; const [filters, setFilters] = useState( - convertFiltersToArray(customLinkSelected) + selectedFilters?.length + ? selectedFilters + : ([{ key: '', value: '' }] as Filter[]) ); const isFormValid = !!label && !!url; @@ -59,7 +64,7 @@ export const CustomLinkFlyout = ({ id: customLinkSelected?.id, label, url, - filters: convertFiltersToObject(filters), + filters, toasts }); setIsSaving(false); diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/saveCustomLink.ts b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/saveCustomLink.ts index 815ce1d95c385..9cbaf16320a6b 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/saveCustomLink.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/saveCustomLink.ts @@ -6,6 +6,10 @@ import { i18n } from '@kbn/i18n'; import { NotificationsStart } from 'kibana/public'; +import { + Filter, + CustomLink +} from '../../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { callApmApi } from '../../../../../../services/rest/createCallApmApi'; export async function saveCustomLink({ @@ -18,15 +22,16 @@ export async function saveCustomLink({ id?: string; label: string; url: string; - filters?: { [key: string]: string[] }; + filters: Filter[]; toasts: NotificationsStart['toasts']; }) { try { - const customLink = { + const customLink: CustomLink = { label, url, - ...filters + filters: filters.filter(({ key, value }) => key && value) }; + if (id) { await callApmApi({ pathname: '/api/apm/settings/custom_links/{id}', diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkTable.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkTable.tsx index f7d8c4baa71e9..68e6ee52af0b0 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkTable.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkTable.tsx @@ -13,8 +13,8 @@ import { EuiSpacer } from '@elastic/eui'; import { isEmpty } from 'lodash'; +import { CustomLink } from '../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { units, px } from '../../../../../style/variables'; -import { CustomLink } from '../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { ManagedTable } from '../../../../shared/ManagedTable'; import { TimestampTooltip } from '../../../../shared/TimestampTooltip'; import { LoadingStatePrompt } from '../../../../shared/LoadingStatePrompt'; diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx index b5bee5a5a1ebb..0c04b7cccbd23 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fireEvent, render, wait } from '@testing-library/react'; +import { fireEvent, render, wait, RenderResult } from '@testing-library/react'; import React from 'react'; import { act } from 'react-dom/test-utils'; import * as apmApi from '../../../../../services/rest/createCallApmApi'; @@ -71,20 +71,6 @@ describe('CustomLink', () => { ); expectTextsInDocument(component, ['No links found.']); }); - it('opens flyout when click to create new link', () => { - const { queryByText, getByText } = render( - - - - - - ); - expect(queryByText('Create link')).not.toBeInTheDocument(); - act(() => { - fireEvent.click(getByText('Create custom link')); - }); - expect(queryByText('Create link')).toBeInTheDocument(); - }); }); describe('overview', () => { @@ -146,7 +132,7 @@ describe('CustomLink', () => { jest.resetAllMocks(); }); - const openFlyout = () => { + const openFlyout = async () => { const component = render( @@ -158,12 +144,13 @@ describe('CustomLink', () => { act(() => { fireEvent.click(component.getByText('Create custom link')); }); + await wait(() => component.queryByText('Create link')); expect(component.queryByText('Create link')).toBeInTheDocument(); return component; }; it('creates a custom link', async () => { - const component = openFlyout(); + const component = await openFlyout(); const labelInput = component.getByTestId('label'); act(() => { fireEvent.change(labelInput, { @@ -205,16 +192,13 @@ describe('CustomLink', () => { }); describe('Filters', () => { - const addFilterField = ( - component: ReturnType, - amount: number - ) => { + const addFilterField = (component: RenderResult, amount: number) => { for (let i = 1; i <= amount; i++) { fireEvent.click(component.getByText('Add another filter')); } }; - it('checks if add filter button is disabled after all elements have been added', () => { - const component = openFlyout(); + it('checks if add filter button is disabled after all elements have been added', async () => { + const component = await openFlyout(); expect(component.getAllByText('service.name').length).toEqual(1); addFilterField(component, 1); expect(component.getAllByText('service.name').length).toEqual(2); @@ -224,8 +208,8 @@ describe('CustomLink', () => { addFilterField(component, 2); expect(component.getAllByText('service.name').length).toEqual(4); }); - it('removes items already selected', () => { - const component = openFlyout(); + it('removes items already selected', async () => { + const component = await openFlyout(); const addFieldAndCheck = ( fieldName: string, diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx index a4985d4410699..47990bf9233f6 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx @@ -8,8 +8,8 @@ import { EuiPanel, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { isEmpty } from 'lodash'; import React, { useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; +import { CustomLink } from '../../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { useLicense } from '../../../../../hooks/useLicense'; -import { CustomLink } from '../../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { useFetcher, FETCH_STATUS } from '../../../../../hooks/useFetcher'; import { CustomLinkFlyout } from './CustomLinkFlyout'; import { CustomLinkTable } from './CustomLinkTable'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx index 99789ca2ecdf5..8df6d952cfacd 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.test.tsx @@ -5,10 +5,10 @@ */ import React from 'react'; import { render, act, fireEvent } from '@testing-library/react'; -import { CustomLink } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; import { CustomLinkPopover } from './CustomLinkPopover'; import { expectTextsInDocument } from '../../../../utils/testHelpers'; +import { CustomLink } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; describe('CustomLinkPopover', () => { const customLinks = [ diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx index ee4aa25606a0c..a20bc7e21cfc5 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx @@ -12,8 +12,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; +import { CustomLink } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; -import { CustomLink } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { CustomLinkSection } from './CustomLinkSection'; import { ManageCustomLink } from './ManageCustomLink'; import { px } from '../../../../style/variables'; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.test.tsx index 4e52c302c6025..d429fa56894eb 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.test.tsx @@ -5,13 +5,13 @@ */ import React from 'react'; import { render } from '@testing-library/react'; -import { CustomLink } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { CustomLinkSection } from './CustomLinkSection'; import { expectTextsInDocument, expectTextsNotInDocument } from '../../../../utils/testHelpers'; import { Transaction } from '../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; +import { CustomLink } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; describe('CustomLinkSection', () => { const customLinks = [ diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.tsx index 601405dda6ece..52befe37ffdae 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkSection.tsx @@ -5,8 +5,8 @@ */ import React from 'react'; import Mustache from 'mustache'; +import { CustomLink } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; -import { CustomLink } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { SectionLinks, SectionLink diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx index ba9c7eee8792b..2dab8d63f99b2 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.test.tsx @@ -13,7 +13,7 @@ import { expectTextsInDocument, expectTextsNotInDocument } from '../../../../utils/testHelpers'; -import { CustomLink as CustomLinkType } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; +import { CustomLink as CustomLinkType } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; describe('Custom links', () => { it('shows empty message when no custom link is available', () => { diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.tsx index 9280f8e71bf9e..b32d8f0d9582c 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/index.tsx @@ -15,8 +15,8 @@ import { import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; import { isEmpty } from 'lodash'; +import { CustomLink as CustomLinkType } from '../../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; -import { CustomLink as CustomLinkType } from '../../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; import { ActionMenuDivider, SectionSubtitle diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index e3c412f40ba3a..0c5359e446ab8 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -7,8 +7,10 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { FunctionComponent, useMemo, useState } from 'react'; -import { FilterOptions } from '../../../../../../../plugins/apm/common/custom_link_filter_options'; -import { CustomLink as CustomLinkType } from '../../../../../../../plugins/apm/server/lib/settings/custom_link/custom_link_types'; +import { + CustomLink as CustomLinkType, + Filter +} from '../../../../../../../plugins/apm/common/custom_link/custom_link_types'; import { Transaction } from '../../../../../../../plugins/apm/typings/es_schemas/ui/transaction'; import { ActionMenu, @@ -29,6 +31,7 @@ import { CustomLinkPopover } from './CustomLink/CustomLinkPopover'; import { getSections } from './sections'; import { useLicense } from '../../../hooks/useLicense'; import { px } from '../../../style/variables'; +import { convertFiltersToQuery } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper'; interface Props { readonly transaction: Transaction; @@ -58,20 +61,22 @@ export const TransactionActionMenu: FunctionComponent = ({ ); const [isCustomLinkFlyoutOpen, setIsCustomLinkFlyoutOpen] = useState(false); - const filters: FilterOptions = useMemo( - () => ({ - 'service.name': transaction?.service.name, - 'service.environment': transaction?.service.environment, - 'transaction.name': transaction?.transaction.name, - 'transaction.type': transaction?.transaction.type - }), + const filters = useMemo( + () => + [ + { key: 'service.name', value: transaction?.service.name }, + { key: 'service.environment', value: transaction?.service.environment }, + { key: 'transaction.name', value: transaction?.transaction.name }, + { key: 'transaction.type', value: transaction?.transaction.type } + ] as Filter[], [transaction] ); + const { data: customLinks = [], status, refetch } = useFetcher( callApmApi => callApmApi({ pathname: '/api/apm/settings/custom_links', - params: { query: filters } + params: { query: convertFiltersToQuery(filters) } }), [filters] ); @@ -95,7 +100,7 @@ export const TransactionActionMenu: FunctionComponent = ({ <> {isCustomLinkFlyoutOpen && ( { toggleCustomLinkFlyout(); diff --git a/x-pack/legacy/plugins/apm/public/new-platform/plugin.tsx b/x-pack/legacy/plugins/apm/public/new-platform/plugin.tsx index f95767492d85b..e30bed1810c1d 100644 --- a/x-pack/legacy/plugins/apm/public/new-platform/plugin.tsx +++ b/x-pack/legacy/plugins/apm/public/new-platform/plugin.tsx @@ -173,6 +173,7 @@ export class ApmPlugin +x-pack/legacy/plugins/apm/e2e/run-e2e.sh ``` -The users will be created with the password specified in kibana.dev.yml for `elasticsearch.password` - -### Debugging Elasticsearch queries - -All APM api endpoints accept `_debug=true` as a query param that will result in the underlying ES query being outputted in the Kibana backend process. - -Example: -`/api/apm/services/my_service?_debug=true` +_Starts Kibana (:5701), APM Server (:8201) and Elasticsearch (:9201). Ingests sample data into Elasticsearch via APM Server and runs the Cypress tests_ ### Unit testing @@ -74,11 +56,13 @@ node scripts/jest.js plugins/apm --updateSnapshot ### Functional tests **Start server** + ``` node scripts/functional_tests_server --config x-pack/test/functional/config.js ``` **Run tests** + ``` node scripts/functional_test_runner --config x-pack/test/functional/config.js --grep='APM specs' ``` @@ -89,11 +73,13 @@ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) ### API integration tests **Start server** + ``` node scripts/functional_tests_server --config x-pack/test/api_integration/config.js ``` **Run tests** + ``` node scripts/functional_test_runner --config x-pack/test/api_integration/config.js --grep='APM specs' ``` @@ -117,6 +103,32 @@ yarn prettier "./x-pack/legacy/plugins/apm/**/*.{tsx,ts,js}" --write yarn eslint ./x-pack/legacy/plugins/apm --fix ``` +### Setup default APM users + +APM behaves differently depending on which the role and permissions a logged in user has. +For testing purposes APM uses 3 custom users: + +**apm_read_user**: Apps: read. Indices: read (`apm-*`) + +**apm_write_user**: Apps: read/write. Indices: read (`apm-*`) + +**kibana_write_user** Apps: read/write. Indices: None + +To create the users with the correct roles run the following script: + +```sh +node x-pack/legacy/plugins/apm/scripts/setup-kibana-security.js --role-suffix +``` + +The users will be created with the password specified in kibana.dev.yml for `elasticsearch.password` + +### Debugging Elasticsearch queries + +All APM api endpoints accept `_debug=true` as a query param that will result in the underlying ES query being outputted in the Kibana backend process. + +Example: +`/api/apm/services/my_service?_debug=true` + #### Storybook Start the [Storybook](https://storybook.js.org/) development environment with diff --git a/x-pack/legacy/plugins/canvas/.storybook/middleware.js b/x-pack/legacy/plugins/canvas/.storybook/middleware.js index 46ae7ac90f364..8bbd2b6c1a22f 100644 --- a/x-pack/legacy/plugins/canvas/.storybook/middleware.js +++ b/x-pack/legacy/plugins/canvas/.storybook/middleware.js @@ -9,5 +9,5 @@ const path = require('path'); // Extend the Storybook Middleware to include a route to access Legacy UI assets module.exports = function(router) { - router.get('/ui', serve(path.resolve(__dirname, '../../../../../src/legacy/ui/public/assets'))); + router.get('/ui', serve(path.resolve(__dirname, '../../../../../src/core/server/core_app/assets'))); }; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts index 538aa9f74e2a6..f5836fe91e040 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore -import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/visualizations/public'; +import { MAP_SAVED_OBJECT_TYPE } from '../../../../../plugins/maps/public'; +import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/plugins/visualizations/public'; import { LENS_EMBEDDABLE_TYPE } from '../../../../../plugins/lens/common/constants'; import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/constants'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts index 9c3e80bc22af1..754a113b87554 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts @@ -5,7 +5,7 @@ */ jest.mock('ui/new_platform'); import { savedVisualization } from './saved_visualization'; -import { buildEmbeddableFilters } from '../../../public/lib/build_embeddable_filters'; +import { getQueryFilters } from '../../../public/lib/build_embeddable_filters'; const filterContext = { and: [ @@ -24,20 +24,21 @@ describe('savedVisualization', () => { const fn = savedVisualization().fn; const args = { id: 'some-id', + timerange: null, + colors: null, + hideLegend: null, }; it('accepts null context', () => { const expression = fn(null, args, {} as any); expect(expression.input.filters).toEqual([]); - expect(expression.input.timeRange).toBeUndefined(); }); it('accepts filter context', () => { const expression = fn(filterContext, args, {} as any); - const embeddableFilters = buildEmbeddableFilters(filterContext.and); + const embeddableFilters = getQueryFilters(filterContext.and); - expect(expression.input.filters).toEqual(embeddableFilters.filters); - expect(expression.input.timeRange).toEqual(embeddableFilters.timeRange); + expect(expression.input.filters).toEqual(embeddableFilters); }); }); diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts index 5b612b7cbd666..d98fea2ec1be8 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts @@ -5,22 +5,30 @@ */ import { ExpressionFunctionDefinition } from 'src/plugins/expressions'; -import { VisualizeInput } from 'src/legacy/core_plugins/visualizations/public'; +import { VisualizeInput } from 'src/plugins/visualizations/public'; import { EmbeddableTypes, EmbeddableExpressionType, EmbeddableExpression, } from '../../expression_types'; -import { buildEmbeddableFilters } from '../../../public/lib/build_embeddable_filters'; -import { Filter } from '../../../types'; +import { getQueryFilters } from '../../../public/lib/build_embeddable_filters'; +import { Filter, TimeRange as TimeRangeArg, SeriesStyle } from '../../../types'; import { getFunctionHelp } from '../../../i18n'; interface Arguments { id: string; + timerange: TimeRangeArg | null; + colors: SeriesStyle[] | null; + hideLegend: boolean | null; } type Output = EmbeddableExpression; +const defaultTimeRange = { + from: 'now-15m', + to: 'now', +}; + export function savedVisualization(): ExpressionFunctionDefinition< 'savedVisualization', Filter | null, @@ -37,17 +45,51 @@ export function savedVisualization(): ExpressionFunctionDefinition< required: false, help: argHelp.id, }, + timerange: { + types: ['timerange'], + help: argHelp.timerange, + required: false, + }, + colors: { + types: ['seriesStyle'], + help: argHelp.colors, + multi: true, + required: false, + }, + hideLegend: { + types: ['boolean'], + help: argHelp.hideLegend, + required: false, + }, }, type: EmbeddableExpressionType, - fn: (input, { id }) => { + fn: (input, { id, timerange, colors, hideLegend }) => { const filters = input ? input.and : []; + const visOptions: VisualizeInput['vis'] = {}; + + if (colors) { + visOptions.colors = colors.reduce((reduction, color) => { + if (color.label && color.color) { + reduction[color.label] = color.color; + } + return reduction; + }, {} as Record); + } + + if (hideLegend === true) { + // @ts-ignore LegendOpen missing on VisualizeInput + visOptions.legendOpen = false; + } + return { type: EmbeddableExpressionType, input: { id, disableTriggers: true, - ...buildEmbeddableFilters(filters), + timeRange: timerange || defaultTimeRange, + filters: getQueryFilters(filters), + vis: visOptions, }, embeddableType: EmbeddableTypes.visualization, }; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx index d91e70e43bfd5..3cdb6eb460224 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx @@ -82,8 +82,13 @@ const embeddable = () => ({ ReactDOM.unmountComponentAtNode(domNode); const subscription = embeddableObject.getInput$().subscribe(function(updatedInput) { - handlers.onEmbeddableInputChange(embeddableInputToExpression(updatedInput, embeddableType)); + const updatedExpression = embeddableInputToExpression(updatedInput, embeddableType); + + if (updatedExpression) { + handlers.onEmbeddableInputChange(updatedExpression); + } }); + ReactDOM.render(renderEmbeddable(embeddableObject, domNode), domNode, () => handlers.done()); handlers.onResize(() => { diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts index 4c622b0c247fa..9dee40c0f683b 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts @@ -4,119 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('ui/new_platform'); -import { embeddableInputToExpression } from './embeddable_input_to_expression'; -import { SavedMapInput } from '../../functions/common/saved_map'; -import { SavedLensInput } from '../../functions/common/saved_lens'; -import { EmbeddableTypes } from '../../expression_types'; -import { fromExpression, Ast } from '@kbn/interpreter/common'; +import { + embeddableInputToExpression, + inputToExpressionTypeMap, +} from './embeddable_input_to_expression'; -const baseEmbeddableInput = { +const input = { id: 'embeddableId', filters: [], -}; - -const baseSavedMapInput = { - ...baseEmbeddableInput, - isLayerTOCOpen: false, - refreshConfig: { - isPaused: true, - interval: 0, - }, hideFilterActions: true as true, }; describe('input to expression', () => { - describe('Map Embeddable', () => { - it('converts to a savedMap expression', () => { - const input: SavedMapInput = { - ...baseSavedMapInput, - }; - - const expression = embeddableInputToExpression(input, EmbeddableTypes.map); - const ast = fromExpression(expression); - - expect(ast.type).toBe('expression'); - expect(ast.chain[0].function).toBe('savedMap'); - - expect(ast.chain[0].arguments.id).toStrictEqual([input.id]); - - expect(ast.chain[0].arguments).not.toHaveProperty('title'); - expect(ast.chain[0].arguments).not.toHaveProperty('center'); - expect(ast.chain[0].arguments).not.toHaveProperty('timerange'); - }); - - it('includes optional input values', () => { - const input: SavedMapInput = { - ...baseSavedMapInput, - mapCenter: { - lat: 1, - lon: 2, - zoom: 3, - }, - title: 'title', - timeRange: { - from: 'now-1h', - to: 'now', - }, - }; - - const expression = embeddableInputToExpression(input, EmbeddableTypes.map); - const ast = fromExpression(expression); - - const centerExpression = ast.chain[0].arguments.center[0] as Ast; - - expect(centerExpression.chain[0].function).toBe('mapCenter'); - expect(centerExpression.chain[0].arguments.lat[0]).toEqual(input.mapCenter?.lat); - expect(centerExpression.chain[0].arguments.lon[0]).toEqual(input.mapCenter?.lon); - expect(centerExpression.chain[0].arguments.zoom[0]).toEqual(input.mapCenter?.zoom); - - const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast; - - expect(timerangeExpression.chain[0].function).toBe('timerange'); - expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); - expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); - }); - }); - - describe('Lens Embeddable', () => { - it('converts to a savedLens expression', () => { - const input: SavedLensInput = { - ...baseEmbeddableInput, - }; - - const expression = embeddableInputToExpression(input, EmbeddableTypes.lens); - const ast = fromExpression(expression); - - expect(ast.type).toBe('expression'); - expect(ast.chain[0].function).toBe('savedLens'); - - expect(ast.chain[0].arguments.id).toStrictEqual([input.id]); - - expect(ast.chain[0].arguments).not.toHaveProperty('title'); - expect(ast.chain[0].arguments).not.toHaveProperty('timerange'); - }); - - it('includes optional input values', () => { - const input: SavedLensInput = { - ...baseEmbeddableInput, - title: 'title', - timeRange: { - from: 'now-1h', - to: 'now', - }, - }; - - const expression = embeddableInputToExpression(input, EmbeddableTypes.map); - const ast = fromExpression(expression); + it('converts to expression if method is available', () => { + const newType = 'newType'; + const mockReturn = 'expression'; + inputToExpressionTypeMap[newType] = jest.fn().mockReturnValue(mockReturn); - expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]); - expect(ast.chain[0].arguments).toHaveProperty('timerange'); + const expression = embeddableInputToExpression(input, newType); - const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast; - expect(timerangeExpression.chain[0].function).toBe('timerange'); - expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); - expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); - }); + expect(expression).toBe(mockReturn); }); }); diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts index 6428507b16a0c..5cba012fcb8e3 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts @@ -5,8 +5,15 @@ */ import { EmbeddableTypes, EmbeddableInput } from '../../expression_types'; -import { SavedMapInput } from '../../functions/common/saved_map'; -import { SavedLensInput } from '../../functions/common/saved_lens'; +import { toExpression as mapToExpression } from './input_type_to_expression/map'; +import { toExpression as visualizationToExpression } from './input_type_to_expression/visualization'; +import { toExpression as lensToExpression } from './input_type_to_expression/lens'; + +export const inputToExpressionTypeMap = { + [EmbeddableTypes.map]: mapToExpression, + [EmbeddableTypes.visualization]: visualizationToExpression, + [EmbeddableTypes.lens]: lensToExpression, +}; /* Take the input from an embeddable and the type of embeddable and convert it into an expression @@ -14,56 +21,8 @@ import { SavedLensInput } from '../../functions/common/saved_lens'; export function embeddableInputToExpression( input: EmbeddableInput, embeddableType: string -): string { - const expressionParts: string[] = []; - - if (embeddableType === EmbeddableTypes.map) { - const mapInput = input as SavedMapInput; - - expressionParts.push('savedMap'); - - expressionParts.push(`id="${input.id}"`); - - if (input.title) { - expressionParts.push(`title="${input.title}"`); - } - - if (mapInput.mapCenter) { - expressionParts.push( - `center={mapCenter lat=${mapInput.mapCenter.lat} lon=${mapInput.mapCenter.lon} zoom=${mapInput.mapCenter.zoom}}` - ); - } - - if (mapInput.timeRange) { - expressionParts.push( - `timerange={timerange from="${mapInput.timeRange.from}" to="${mapInput.timeRange.to}"}` - ); - } - - if (mapInput.hiddenLayers && mapInput.hiddenLayers.length) { - for (const layerId of mapInput.hiddenLayers) { - expressionParts.push(`hideLayer="${layerId}"`); - } - } +): string | undefined { + if (inputToExpressionTypeMap[embeddableType]) { + return inputToExpressionTypeMap[embeddableType](input as any); } - - if (embeddableType === EmbeddableTypes.lens) { - const lensInput = input as SavedLensInput; - - expressionParts.push('savedLens'); - - expressionParts.push(`id="${input.id}"`); - - if (input.title) { - expressionParts.push(`title="${input.title}"`); - } - - if (lensInput.timeRange) { - expressionParts.push( - `timerange={timerange from="${lensInput.timeRange.from}" to="${lensInput.timeRange.to}"}` - ); - } - } - - return expressionParts.join(' '); } diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts new file mode 100644 index 0000000000000..c4a9a22be3202 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { toExpression } from './lens'; +import { SavedLensInput } from '../../../functions/common/saved_lens'; +import { fromExpression, Ast } from '@kbn/interpreter/common'; + +const baseEmbeddableInput = { + id: 'embeddableId', + filters: [], +}; + +describe('toExpression', () => { + it('converts to a savedLens expression', () => { + const input: SavedLensInput = { + ...baseEmbeddableInput, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.type).toBe('expression'); + expect(ast.chain[0].function).toBe('savedLens'); + + expect(ast.chain[0].arguments.id).toStrictEqual([input.id]); + + expect(ast.chain[0].arguments).not.toHaveProperty('title'); + expect(ast.chain[0].arguments).not.toHaveProperty('timerange'); + }); + + it('includes optional input values', () => { + const input: SavedLensInput = { + ...baseEmbeddableInput, + title: 'title', + timeRange: { + from: 'now-1h', + to: 'now', + }, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]); + expect(ast.chain[0].arguments).toHaveProperty('timerange'); + + const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast; + expect(timerangeExpression.chain[0].function).toBe('timerange'); + expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); + expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); + }); +}); diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts new file mode 100644 index 0000000000000..445cb7480ff80 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedLensInput } from '../../../functions/common/saved_lens'; + +export function toExpression(input: SavedLensInput): string { + const expressionParts = [] as string[]; + + expressionParts.push('savedLens'); + + expressionParts.push(`id="${input.id}"`); + + if (input.title) { + expressionParts.push(`title="${input.title}"`); + } + + if (input.timeRange) { + expressionParts.push( + `timerange={timerange from="${input.timeRange.from}" to="${input.timeRange.to}"}` + ); + } + + return expressionParts.join(' '); +} diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts new file mode 100644 index 0000000000000..4c294fb37c2db --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts @@ -0,0 +1,72 @@ +/* + * 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 { toExpression } from './map'; +import { SavedMapInput } from '../../../functions/common/saved_map'; +import { fromExpression, Ast } from '@kbn/interpreter/common'; + +const baseSavedMapInput = { + id: 'embeddableId', + filters: [], + isLayerTOCOpen: false, + refreshConfig: { + isPaused: true, + interval: 0, + }, + hideFilterActions: true as true, +}; + +describe('toExpression', () => { + it('converts to a savedMap expression', () => { + const input: SavedMapInput = { + ...baseSavedMapInput, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.type).toBe('expression'); + expect(ast.chain[0].function).toBe('savedMap'); + + expect(ast.chain[0].arguments.id).toStrictEqual([input.id]); + + expect(ast.chain[0].arguments).not.toHaveProperty('title'); + expect(ast.chain[0].arguments).not.toHaveProperty('center'); + expect(ast.chain[0].arguments).not.toHaveProperty('timerange'); + }); + + it('includes optional input values', () => { + const input: SavedMapInput = { + ...baseSavedMapInput, + mapCenter: { + lat: 1, + lon: 2, + zoom: 3, + }, + title: 'title', + timeRange: { + from: 'now-1h', + to: 'now', + }, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + const centerExpression = ast.chain[0].arguments.center[0] as Ast; + + expect(centerExpression.chain[0].function).toBe('mapCenter'); + expect(centerExpression.chain[0].arguments.lat[0]).toEqual(input.mapCenter?.lat); + expect(centerExpression.chain[0].arguments.lon[0]).toEqual(input.mapCenter?.lon); + expect(centerExpression.chain[0].arguments.zoom[0]).toEqual(input.mapCenter?.zoom); + + const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast; + + expect(timerangeExpression.chain[0].function).toBe('timerange'); + expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); + expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); + }); +}); diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts new file mode 100644 index 0000000000000..e3f9eca61ae28 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedMapInput } from '../../../functions/common/saved_map'; + +export function toExpression(input: SavedMapInput): string { + const expressionParts = [] as string[]; + + expressionParts.push('savedMap'); + expressionParts.push(`id="${input.id}"`); + + if (input.title) { + expressionParts.push(`title="${input.title}"`); + } + + if (input.mapCenter) { + expressionParts.push( + `center={mapCenter lat=${input.mapCenter.lat} lon=${input.mapCenter.lon} zoom=${input.mapCenter.zoom}}` + ); + } + + if (input.timeRange) { + expressionParts.push( + `timerange={timerange from="${input.timeRange.from}" to="${input.timeRange.to}"}` + ); + } + + if (input.hiddenLayers && input.hiddenLayers.length) { + for (const layerId of input.hiddenLayers) { + expressionParts.push(`hideLayer="${layerId}"`); + } + } + + return expressionParts.join(' '); +} diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts new file mode 100644 index 0000000000000..306020293abe6 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts @@ -0,0 +1,72 @@ +/* + * 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 { toExpression } from './visualization'; +import { fromExpression, Ast } from '@kbn/interpreter/common'; + +const baseInput = { + id: 'embeddableId', +}; + +describe('toExpression', () => { + it('converts to a savedVisualization expression', () => { + const input = { + ...baseInput, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + expect(ast.type).toBe('expression'); + expect(ast.chain[0].function).toBe('savedVisualization'); + + expect(ast.chain[0].arguments.id).toStrictEqual([input.id]); + }); + + it('includes timerange if given', () => { + const input = { + ...baseInput, + timeRange: { + from: 'now-1h', + to: 'now', + }, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast; + + expect(timerangeExpression.chain[0].function).toBe('timerange'); + expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from); + expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to); + }); + + it('includes colors if given', () => { + const colorMap = { a: 'red', b: 'blue' }; + + const input = { + ...baseInput, + vis: { + colors: { + a: 'red', + b: 'blue', + }, + }, + }; + + const expression = toExpression(input); + const ast = fromExpression(expression); + + const colors = ast.chain[0].arguments.colors as Ast[]; + + const aColor = colors.find(color => color.chain[0].arguments.label[0] === 'a'); + const bColor = colors.find(color => color.chain[0].arguments.label[0] === 'b'); + + expect(aColor?.chain[0].arguments.color[0]).toBe(colorMap.a); + expect(bColor?.chain[0].arguments.color[0]).toBe(colorMap.b); + }); +}); diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts new file mode 100644 index 0000000000000..4c8de2afd81ad --- /dev/null +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { VisualizeInput } from 'src/plugins/visualizations/public'; + +export function toExpression(input: VisualizeInput): string { + const expressionParts = [] as string[]; + + expressionParts.push('savedVisualization'); + expressionParts.push(`id="${input.id}"`); + + if (input.timeRange) { + expressionParts.push( + `timerange={timerange from="${input.timeRange.from}" to="${input.timeRange.to}"}` + ); + } + + if (input.vis?.colors) { + Object.entries(input.vis.colors) + .map(([label, color]) => { + return `colors={seriesStyle label="${label}" color="${color}"}`; + }) + .reduce((_, part) => expressionParts.push(part), 0); + } + + // @ts-ignore LegendOpen missing on VisualizeInput type + if (input.vis?.legendOpen !== undefined && input.vis.legendOpen === false) { + expressionParts.push(`hideLegend=true`); + } + + return expressionParts.join(' '); +} diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts b/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts index e3b412284442d..21a2e1c1b8800 100644 --- a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts +++ b/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts @@ -14,6 +14,20 @@ export const help: FunctionHelp> = { defaultMessage: `Returns an embeddable for a saved visualization object`, }), args: { - id: 'The id of the saved visualization object', + id: i18n.translate('xpack.canvas.functions.savedVisualization.args.idHelpText', { + defaultMessage: `The ID of the Saved Visualization Object`, + }), + timerange: i18n.translate('xpack.canvas.functions.savedVisualization.args.timerangeHelpText', { + defaultMessage: `The timerange of data that should be included`, + }), + colors: i18n.translate('xpack.canvas.functions.savedVisualization.args.colorsHelpText', { + defaultMessage: `Define the color to use for a specific series`, + }), + hideLegend: i18n.translate( + 'xpack.canvas.functions.savedVisualization.args.hideLegendHelpText', + { + defaultMessage: `Should the legend be hidden`, + } + ), }, }; diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js b/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js index 9b198cee34aae..7537f8eaa9039 100644 --- a/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js +++ b/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js @@ -28,6 +28,7 @@ export class ExportApp extends React.PureComponent { const { workpad, selectedPageId } = this.props; const { pages, height, width } = workpad; const activePage = pages.find(page => page.id === selectedPageId); + const pageElementCount = activePage.elements.length; return (

@@ -39,7 +40,7 @@ export class ExportApp extends React.PureComponent {
{Style.it( workpad.css, -
+
+ +
+      {
+  "datatable": {
+    "type": "datatable",
+    "columns": [
+      {
+        "name": "@timestamp",
+        "type": "date"
+      },
+      {
+        "name": "time",
+        "type": "date"
+      },
+      {
+        "name": "cost",
+        "type": "number"
+      },
+      {
+        "name": "username",
+        "type": "string"
+      },
+      {
+        "name": "price",
+        "type": "number"
+      },
+      {
+        "name": "age",
+        "type": "number"
+      },
+      {
+        "name": "country",
+        "type": "string"
+      },
+      {
+        "name": "state",
+        "type": "string"
+      },
+      {
+        "name": "project",
+        "type": "string"
+      },
+      {
+        "name": "percent_uptime",
+        "type": "number"
+      }
+    ],
+    "rows": [
+      {
+        "age": 63,
+        "cost": 32.15,
+        "country": "US",
+        "price": 53,
+        "project": "elasticsearch",
+        "state": "running",
+        "time": 1546334211208,
+        "@timestamp": 1546334211208,
+        "username": "aevans2e",
+        "percent_uptime": 0.83
+      },
+      {
+        "age": 68,
+        "cost": 20.52,
+        "country": "JP",
+        "price": 33,
+        "project": "beats",
+        "state": "done",
+        "time": 1546351551031,
+        "@timestamp": 1546351551031,
+        "username": "aking2c",
+        "percent_uptime": 0.9
+      },
+      {
+        "age": 57,
+        "cost": 21.15,
+        "country": "UK",
+        "price": 59,
+        "project": "apm",
+        "state": "running",
+        "time": 1546352631083,
+        "@timestamp": 1546352631083,
+        "username": "mmoore2o",
+        "percent_uptime": 0.96
+      },
+      {
+        "age": 73,
+        "cost": 35.64,
+        "country": "CN",
+        "price": 71,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1546402490956,
+        "@timestamp": 1546402490956,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.61
+      },
+      {
+        "age": 38,
+        "cost": 27.19,
+        "country": "TZ",
+        "price": 36,
+        "project": "kibana",
+        "state": "done",
+        "time": 1546467111351,
+        "@timestamp": 1546467111351,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 61,
+        "cost": 49.95,
+        "country": "NL",
+        "price": 65,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1546473771019,
+        "@timestamp": 1546473771019,
+        "username": "mmoore2o",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 53,
+        "cost": 27.36,
+        "country": "JP",
+        "price": 60,
+        "project": "x-pack",
+        "state": "running",
+        "time": 1546482171310,
+        "@timestamp": 1546482171310,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.65
+      },
+      {
+        "age": 31,
+        "cost": 33.77,
+        "country": "AZ",
+        "price": 77,
+        "project": "kibana",
+        "state": "start",
+        "time": 1546493451206,
+        "@timestamp": 1546493451206,
+        "username": "aking2c",
+        "percent_uptime": 0.92
+      },
+      {
+        "age": 71,
+        "cost": 20.2,
+        "country": "TZ",
+        "price": 57,
+        "project": "swiftype",
+        "state": "running",
+        "time": 1546494651235,
+        "@timestamp": 1546494651235,
+        "username": "jlawson2p",
+        "percent_uptime": 0.59
+      },
+      {
+        "age": 54,
+        "cost": 36.65,
+        "country": "TZ",
+        "price": 72,
+        "project": "apm",
+        "state": "done",
+        "time": 1546498431195,
+        "@timestamp": 1546498431195,
+        "username": "aking2c",
+        "percent_uptime": 1
+      },
+      {
+        "age": 31,
+        "cost": 26.57,
+        "country": "BR",
+        "price": 48,
+        "project": "logstash",
+        "state": "done",
+        "time": 1546509170962,
+        "@timestamp": 1546509170962,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.86
+      },
+      {
+        "age": 99,
+        "cost": 22.46,
+        "country": "TZ",
+        "price": 66,
+        "project": "swiftype",
+        "state": "done",
+        "time": 1546552371305,
+        "@timestamp": 1546552371305,
+        "username": "bmorris2n",
+        "percent_uptime": 0.76
+      },
+      {
+        "age": 87,
+        "cost": 21.54,
+        "country": "US",
+        "price": 43,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1546575231270,
+        "@timestamp": 1546575231270,
+        "username": "sadams1v",
+        "percent_uptime": 0.58
+      },
+      {
+        "age": 10,
+        "cost": 37.68,
+        "country": "CN",
+        "price": 36,
+        "project": "x-pack",
+        "state": "done",
+        "time": 1546678071026,
+        "@timestamp": 1546678071026,
+        "username": "jchavez2a",
+        "percent_uptime": 0.5
+      },
+      {
+        "age": 30,
+        "cost": 21.62,
+        "country": "DE",
+        "price": 78,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1546678911351,
+        "@timestamp": 1546678911351,
+        "username": "kbrooks23",
+        "percent_uptime": 1
+      },
+      {
+        "age": 49,
+        "cost": 26.46,
+        "country": "BR",
+        "price": 76,
+        "project": "swiftype",
+        "state": "start",
+        "time": 1546701050984,
+        "@timestamp": 1546701050984,
+        "username": "sadams1v",
+        "percent_uptime": 0.97
+      },
+      {
+        "age": 81,
+        "cost": 36.69,
+        "country": "TZ",
+        "price": 80,
+        "project": "logstash",
+        "state": "done",
+        "time": 1546702851232,
+        "@timestamp": 1546702851232,
+        "username": "smurphy1y",
+        "percent_uptime": 0.92
+      },
+      {
+        "age": 68,
+        "cost": 28.74,
+        "country": "DE",
+        "price": 56,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1546712451326,
+        "@timestamp": 1546712451326,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.85
+      },
+      {
+        "age": 28,
+        "cost": 21.3,
+        "country": "SA",
+        "price": 72,
+        "project": "apm",
+        "state": "start",
+        "time": 1546728771027,
+        "@timestamp": 1546728771027,
+        "username": "hbowman1s",
+        "percent_uptime": 0.79
+      },
+      {
+        "age": 57,
+        "cost": 28.72,
+        "country": "UK",
+        "price": 34,
+        "project": "machine-learning",
+        "state": "done",
+        "time": 1546738610972,
+        "@timestamp": 1546738610972,
+        "username": "pjohnston2l",
+        "percent_uptime": 0.6
+      },
+      {
+        "age": 35,
+        "cost": 48.87,
+        "country": "US",
+        "price": 78,
+        "project": "apm",
+        "state": "running",
+        "time": 1546761591244,
+        "@timestamp": 1546761591244,
+        "username": "bfranklin27",
+        "percent_uptime": 0.52
+      },
+      {
+        "age": 89,
+        "cost": 29.48,
+        "country": "TZ",
+        "price": 69,
+        "project": "beats",
+        "state": "done",
+        "time": 1546791771183,
+        "@timestamp": 1546791771183,
+        "username": "ccarpenter2m",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 14,
+        "cost": 28.94,
+        "country": "BR",
+        "price": 49,
+        "project": "elasticsearch",
+        "state": "running",
+        "time": 1546886211287,
+        "@timestamp": 1546886211287,
+        "username": "pjohnston2l",
+        "percent_uptime": 0.75
+      },
+      {
+        "age": 39,
+        "cost": 27.16,
+        "country": "CN",
+        "price": 49,
+        "project": "elasticsearch",
+        "state": "start",
+        "time": 1546934631129,
+        "@timestamp": 1546934631129,
+        "username": "jlawson2p",
+        "percent_uptime": 0.7
+      },
+      {
+        "age": 84,
+        "cost": 35.6,
+        "country": "NL",
+        "price": 76,
+        "project": "swiftype",
+        "state": "running",
+        "time": 1546948431271,
+        "@timestamp": 1546948431271,
+        "username": "hbowman1s",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 54,
+        "cost": 27.08,
+        "country": "AZ",
+        "price": 49,
+        "project": "x-pack",
+        "state": "start",
+        "time": 1546986231297,
+        "@timestamp": 1546986231297,
+        "username": "krobinson2b",
+        "percent_uptime": 0.89
+      },
+      {
+        "age": 58,
+        "cost": 26.9,
+        "country": "DE",
+        "price": 43,
+        "project": "apm",
+        "state": "start",
+        "time": 1547041191338,
+        "@timestamp": 1547041191338,
+        "username": "hperez29",
+        "percent_uptime": 0.63
+      },
+      {
+        "age": 26,
+        "cost": 48.27,
+        "country": "DE",
+        "price": 36,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1547118111126,
+        "@timestamp": 1547118111126,
+        "username": "sadams1v",
+        "percent_uptime": 0.56
+      },
+      {
+        "age": 82,
+        "cost": 32.13,
+        "country": "SA",
+        "price": 79,
+        "project": "elasticsearch",
+        "state": "done",
+        "time": 1547159331136,
+        "@timestamp": 1547159331136,
+        "username": "dhicks28",
+        "percent_uptime": 0.71
+      },
+      {
+        "age": 26,
+        "cost": 20.59,
+        "country": "UK",
+        "price": 52,
+        "project": "kibana",
+        "state": "done",
+        "time": 1547174150962,
+        "@timestamp": 1547174150962,
+        "username": "greynolds2j",
+        "percent_uptime": 0.94
+      },
+      {
+        "age": 19,
+        "cost": 25.73,
+        "country": "RU",
+        "price": 45,
+        "project": "beats",
+        "state": "start",
+        "time": 1547205411225,
+        "@timestamp": 1547205411225,
+        "username": "sadams1v",
+        "percent_uptime": 0.6
+      },
+      {
+        "age": 53,
+        "cost": 46.19,
+        "country": "JP",
+        "price": 30,
+        "project": "apm",
+        "state": "done",
+        "time": 1547217171103,
+        "@timestamp": 1547217171103,
+        "username": "jlawson2p",
+        "percent_uptime": 0.54
+      },
+      {
+        "age": 76,
+        "cost": 40.52,
+        "country": "DE",
+        "price": 43,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1547261271103,
+        "@timestamp": 1547261271103,
+        "username": "athomas1w",
+        "percent_uptime": 0.86
+      },
+      {
+        "age": 31,
+        "cost": 27.62,
+        "country": "BR",
+        "price": 71,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1547262771238,
+        "@timestamp": 1547262771238,
+        "username": "jhanson1x",
+        "percent_uptime": 0.79
+      },
+      {
+        "age": 42,
+        "cost": 30.91,
+        "country": "US",
+        "price": 58,
+        "project": "beats",
+        "state": "running",
+        "time": 1547274291106,
+        "@timestamp": 1547274291106,
+        "username": "amartinez26",
+        "percent_uptime": 0.82
+      },
+      {
+        "age": 43,
+        "cost": 23.29,
+        "country": "UK",
+        "price": 41,
+        "project": "kibana",
+        "state": "start",
+        "time": 1547293010955,
+        "@timestamp": 1547293010955,
+        "username": "ediaz2d",
+        "percent_uptime": 0.93
+      },
+      {
+        "age": 45,
+        "cost": 21.18,
+        "country": "AZ",
+        "price": 62,
+        "project": "logstash",
+        "state": "done",
+        "time": 1547316050970,
+        "@timestamp": 1547316050970,
+        "username": "hperez29",
+        "percent_uptime": 0.75
+      },
+      {
+        "age": 39,
+        "cost": 29.66,
+        "country": "IN",
+        "price": 40,
+        "project": "swiftype",
+        "state": "start",
+        "time": 1547320011249,
+        "@timestamp": 1547320011249,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.99
+      },
+      {
+        "age": 98,
+        "cost": 37.42,
+        "country": "US",
+        "price": 58,
+        "project": "beats",
+        "state": "done",
+        "time": 1547331051346,
+        "@timestamp": 1547331051346,
+        "username": "jmills21",
+        "percent_uptime": 0.51
+      },
+      {
+        "age": 96,
+        "cost": 40,
+        "country": "DE",
+        "price": 58,
+        "project": "apm",
+        "state": "start",
+        "time": 1547425371273,
+        "@timestamp": 1547425371273,
+        "username": "rsmith25",
+        "percent_uptime": 0.87
+      },
+      {
+        "age": 13,
+        "cost": 47.45,
+        "country": "AZ",
+        "price": 30,
+        "project": "apm",
+        "state": "done",
+        "time": 1547482911215,
+        "@timestamp": 1547482911215,
+        "username": "smurphy1y",
+        "percent_uptime": 0.83
+      },
+      {
+        "age": 100,
+        "cost": 24.36,
+        "country": "IN",
+        "price": 59,
+        "project": "apm",
+        "state": "done",
+        "time": 1547485611233,
+        "@timestamp": 1547485611233,
+        "username": "jlawson2p",
+        "percent_uptime": 0.64
+      },
+      {
+        "age": 10,
+        "cost": 27.59,
+        "country": "US",
+        "price": 53,
+        "project": "apm",
+        "state": "start",
+        "time": 1547518911272,
+        "@timestamp": 1547518911272,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.93
+      },
+      {
+        "age": 83,
+        "cost": 37.05,
+        "country": "BR",
+        "price": 77,
+        "project": "logstash",
+        "state": "running",
+        "time": 1547521971300,
+        "@timestamp": 1547521971300,
+        "username": "hperez29",
+        "percent_uptime": 0.53
+      },
+      {
+        "age": 60,
+        "cost": 31.19,
+        "country": "CN",
+        "price": 69,
+        "project": "kibana",
+        "state": "running",
+        "time": 1547555751264,
+        "@timestamp": 1547555751264,
+        "username": "aevans2e",
+        "percent_uptime": 0.99
+      },
+      {
+        "age": 61,
+        "cost": 27.69,
+        "country": "JP",
+        "price": 39,
+        "project": "elasticsearch",
+        "state": "start",
+        "time": 1547564691226,
+        "@timestamp": 1547564691226,
+        "username": "greynolds2j",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 89,
+        "cost": 33.03,
+        "country": "JP",
+        "price": 75,
+        "project": "machine-learning",
+        "state": "done",
+        "time": 1547581671013,
+        "@timestamp": 1547581671013,
+        "username": "aevans2e",
+        "percent_uptime": 0.88
+      },
+      {
+        "age": 45,
+        "cost": 40.38,
+        "country": "JP",
+        "price": 76,
+        "project": "x-pack",
+        "state": "start",
+        "time": 1547582451365,
+        "@timestamp": 1547582451365,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.65
+      },
+      {
+        "age": 62,
+        "cost": 29.53,
+        "country": "AZ",
+        "price": 46,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1547598471186,
+        "@timestamp": 1547598471186,
+        "username": "aking2c",
+        "percent_uptime": 0.93
+      },
+      {
+        "age": 69,
+        "cost": 45.37,
+        "country": "AZ",
+        "price": 35,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1547599370965,
+        "@timestamp": 1547599370965,
+        "username": "jlawson2p",
+        "percent_uptime": 0.82
+      },
+      {
+        "age": 46,
+        "cost": 39.71,
+        "country": "UK",
+        "price": 39,
+        "project": "machine-learning",
+        "state": "done",
+        "time": 1547650491235,
+        "@timestamp": 1547650491235,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.99
+      },
+      {
+        "age": 62,
+        "cost": 38.21,
+        "country": "SA",
+        "price": 31,
+        "project": "x-pack",
+        "state": "start",
+        "time": 1547667891326,
+        "@timestamp": 1547667891326,
+        "username": "greynolds2j",
+        "percent_uptime": 0.73
+      },
+      {
+        "age": 46,
+        "cost": 28.44,
+        "country": "TZ",
+        "price": 75,
+        "project": "apm",
+        "state": "running",
+        "time": 1547685471027,
+        "@timestamp": 1547685471027,
+        "username": "aking2c",
+        "percent_uptime": 0.7
+      },
+      {
+        "age": 85,
+        "cost": 30.5,
+        "country": "JP",
+        "price": 30,
+        "project": "beats",
+        "state": "running",
+        "time": 1547694951230,
+        "@timestamp": 1547694951230,
+        "username": "sjordan2k",
+        "percent_uptime": 0.5
+      },
+      {
+        "age": 51,
+        "cost": 27.1,
+        "country": "DE",
+        "price": 37,
+        "project": "kibana",
+        "state": "done",
+        "time": 1547699331145,
+        "@timestamp": 1547699331145,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.79
+      },
+      {
+        "age": 84,
+        "cost": 36.47,
+        "country": "TZ",
+        "price": 43,
+        "project": "logstash",
+        "state": "start",
+        "time": 1547729571155,
+        "@timestamp": 1547729571155,
+        "username": "jchavez2a",
+        "percent_uptime": 0.67
+      },
+      {
+        "age": 66,
+        "cost": 37.74,
+        "country": "PH",
+        "price": 63,
+        "project": "x-pack",
+        "state": "start",
+        "time": 1547738331360,
+        "@timestamp": 1547738331360,
+        "username": "ccarpenter2m",
+        "percent_uptime": 0.74
+      },
+      {
+        "age": 87,
+        "cost": 49.07,
+        "country": "BR",
+        "price": 72,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1547742291143,
+        "@timestamp": 1547742291143,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.99
+      },
+      {
+        "age": 92,
+        "cost": 31.7,
+        "country": "TZ",
+        "price": 55,
+        "project": "apm",
+        "state": "done",
+        "time": 1547772651030,
+        "@timestamp": 1547772651030,
+        "username": "jhanson1x",
+        "percent_uptime": 0.89
+      },
+      {
+        "age": 98,
+        "cost": 29.77,
+        "country": "US",
+        "price": 72,
+        "project": "logstash",
+        "state": "start",
+        "time": 1547786271226,
+        "@timestamp": 1547786271226,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.66
+      },
+      {
+        "age": 10,
+        "cost": 20.49,
+        "country": "DE",
+        "price": 64,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1547871831230,
+        "@timestamp": 1547871831230,
+        "username": "dmarshall24",
+        "percent_uptime": 0.54
+      },
+      {
+        "age": 69,
+        "cost": 42.89,
+        "country": "AZ",
+        "price": 61,
+        "project": "kibana",
+        "state": "start",
+        "time": 1547902191247,
+        "@timestamp": 1547902191247,
+        "username": "sadams1v",
+        "percent_uptime": 0.8
+      },
+      {
+        "age": 42,
+        "cost": 32.31,
+        "country": "SA",
+        "price": 47,
+        "project": "swiftype",
+        "state": "running",
+        "time": 1547922591339,
+        "@timestamp": 1547922591339,
+        "username": "bmorris2n",
+        "percent_uptime": 0.65
+      },
+      {
+        "age": 100,
+        "cost": 30.42,
+        "country": "BR",
+        "price": 42,
+        "project": "kibana",
+        "state": "done",
+        "time": 1547926491261,
+        "@timestamp": 1547926491261,
+        "username": "jaustin1z",
+        "percent_uptime": 0.66
+      },
+      {
+        "age": 34,
+        "cost": 48.98,
+        "country": "DE",
+        "price": 70,
+        "project": "beats",
+        "state": "running",
+        "time": 1547958651364,
+        "@timestamp": 1547958651364,
+        "username": "jlawson2p",
+        "percent_uptime": 0.9
+      },
+      {
+        "age": 68,
+        "cost": 31.64,
+        "country": "NL",
+        "price": 47,
+        "project": "machine-learning",
+        "state": "done",
+        "time": 1547967231273,
+        "@timestamp": 1547967231273,
+        "username": "hbowman1s",
+        "percent_uptime": 0.55
+      },
+      {
+        "age": 91,
+        "cost": 46.82,
+        "country": "RU",
+        "price": 62,
+        "project": "swiftype",
+        "state": "done",
+        "time": 1547969691305,
+        "@timestamp": 1547969691305,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.89
+      },
+      {
+        "age": 17,
+        "cost": 42.19,
+        "country": "IN",
+        "price": 79,
+        "project": "apm",
+        "state": "running",
+        "time": 1547974551309,
+        "@timestamp": 1547974551309,
+        "username": "hperez29",
+        "percent_uptime": 0.58
+      },
+      {
+        "age": 83,
+        "cost": 25.61,
+        "country": "CN",
+        "price": 54,
+        "project": "swiftype",
+        "state": "running",
+        "time": 1547977911240,
+        "@timestamp": 1547977911240,
+        "username": "aking2c",
+        "percent_uptime": 0.96
+      },
+      {
+        "age": 31,
+        "cost": 49.49,
+        "country": "JP",
+        "price": 58,
+        "project": "elasticsearch",
+        "state": "done",
+        "time": 1547984271197,
+        "@timestamp": 1547984271197,
+        "username": "dmarshall24",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 97,
+        "cost": 33.33,
+        "country": "PH",
+        "price": 34,
+        "project": "logstash",
+        "state": "start",
+        "time": 1547984631153,
+        "@timestamp": 1547984631153,
+        "username": "hbowman1s",
+        "percent_uptime": 0.56
+      },
+      {
+        "age": 67,
+        "cost": 31.1,
+        "country": "US",
+        "price": 73,
+        "project": "x-pack",
+        "state": "done",
+        "time": 1548001430974,
+        "@timestamp": 1548001430974,
+        "username": "ccarpenter2m",
+        "percent_uptime": 0.78
+      },
+      {
+        "age": 31,
+        "cost": 21.6,
+        "country": "PH",
+        "price": 73,
+        "project": "kibana",
+        "state": "running",
+        "time": 1548014391252,
+        "@timestamp": 1548014391252,
+        "username": "jmills21",
+        "percent_uptime": 0.59
+      },
+      {
+        "age": 57,
+        "cost": 25.84,
+        "country": "NL",
+        "price": 53,
+        "project": "swiftype",
+        "state": "start",
+        "time": 1548039051145,
+        "@timestamp": 1548039051145,
+        "username": "dhicks28",
+        "percent_uptime": 0.63
+      },
+      {
+        "age": 92,
+        "cost": 27.09,
+        "country": "CN",
+        "price": 34,
+        "project": "apm",
+        "state": "done",
+        "time": 1548052791195,
+        "@timestamp": 1548052791195,
+        "username": "dramirez2i",
+        "percent_uptime": 0.98
+      },
+      {
+        "age": 43,
+        "cost": 36.39,
+        "country": "US",
+        "price": 68,
+        "project": "elasticsearch",
+        "state": "done",
+        "time": 1548058071369,
+        "@timestamp": 1548058071369,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.55
+      },
+      {
+        "age": 68,
+        "cost": 44.69,
+        "country": "JP",
+        "price": 66,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1548072471282,
+        "@timestamp": 1548072471282,
+        "username": "jmills21",
+        "percent_uptime": 0.68
+      },
+      {
+        "age": 47,
+        "cost": 25.34,
+        "country": "NL",
+        "price": 32,
+        "project": "kibana",
+        "state": "running",
+        "time": 1548075171245,
+        "@timestamp": 1548075171245,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.95
+      },
+      {
+        "age": 19,
+        "cost": 25.4,
+        "country": "SA",
+        "price": 42,
+        "project": "kibana",
+        "state": "start",
+        "time": 1548125331273,
+        "@timestamp": 1548125331273,
+        "username": "dhicks28",
+        "percent_uptime": 0.95
+      },
+      {
+        "age": 88,
+        "cost": 36.38,
+        "country": "TZ",
+        "price": 77,
+        "project": "x-pack",
+        "state": "start",
+        "time": 1548126771234,
+        "@timestamp": 1548126771234,
+        "username": "sjordan2k",
+        "percent_uptime": 0.84
+      },
+      {
+        "age": 36,
+        "cost": 28.62,
+        "country": "DE",
+        "price": 34,
+        "project": "kibana",
+        "state": "start",
+        "time": 1548128331153,
+        "@timestamp": 1548128331153,
+        "username": "dramirez2i",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 32,
+        "cost": 48.69,
+        "country": "AZ",
+        "price": 40,
+        "project": "swiftype",
+        "state": "start",
+        "time": 1548161391285,
+        "@timestamp": 1548161391285,
+        "username": "dramirez2i",
+        "percent_uptime": 0.69
+      },
+      {
+        "age": 53,
+        "cost": 44.25,
+        "country": "UK",
+        "price": 35,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1548192651185,
+        "@timestamp": 1548192651185,
+        "username": "wmontgomery22",
+        "percent_uptime": 0.68
+      },
+      {
+        "age": 37,
+        "cost": 32.67,
+        "country": "DE",
+        "price": 31,
+        "project": "kibana",
+        "state": "running",
+        "time": 1548218751137,
+        "@timestamp": 1548218751137,
+        "username": "ccarpenter2m",
+        "percent_uptime": 0.77
+      },
+      {
+        "age": 58,
+        "cost": 40.83,
+        "country": "PH",
+        "price": 61,
+        "project": "logstash",
+        "state": "running",
+        "time": 1548221151061,
+        "@timestamp": 1548221151061,
+        "username": "dmarshall24",
+        "percent_uptime": 0.88
+      },
+      {
+        "age": 45,
+        "cost": 42.97,
+        "country": "AZ",
+        "price": 44,
+        "project": "machine-learning",
+        "state": "running",
+        "time": 1548262131313,
+        "@timestamp": 1548262131313,
+        "username": "dmarshall24",
+        "percent_uptime": 0.64
+      },
+      {
+        "age": 21,
+        "cost": 23.16,
+        "country": "NL",
+        "price": 78,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1548265611336,
+        "@timestamp": 1548265611336,
+        "username": "jlawson2p",
+        "percent_uptime": 0.88
+      },
+      {
+        "age": 77,
+        "cost": 31.37,
+        "country": "RU",
+        "price": 52,
+        "project": "kibana",
+        "state": "start",
+        "time": 1548274611337,
+        "@timestamp": 1548274611337,
+        "username": "jhanson1x",
+        "percent_uptime": 0.68
+      },
+      {
+        "age": 34,
+        "cost": 41.41,
+        "country": "AZ",
+        "price": 52,
+        "project": "elasticsearch",
+        "state": "start",
+        "time": 1548276411368,
+        "@timestamp": 1548276411368,
+        "username": "agonzales1t",
+        "percent_uptime": 0.75
+      },
+      {
+        "age": 95,
+        "cost": 24.93,
+        "country": "AZ",
+        "price": 66,
+        "project": "logstash",
+        "state": "running",
+        "time": 1548301071035,
+        "@timestamp": 1548301071035,
+        "username": "phansen1q",
+        "percent_uptime": 0.75
+      },
+      {
+        "age": 12,
+        "cost": 32.33,
+        "country": "PH",
+        "price": 31,
+        "project": "elasticsearch",
+        "state": "start",
+        "time": 1548342711164,
+        "@timestamp": 1548342711164,
+        "username": "amartinez26",
+        "percent_uptime": 0.96
+      },
+      {
+        "age": 15,
+        "cost": 44.74,
+        "country": "IN",
+        "price": 41,
+        "project": "x-pack",
+        "state": "done",
+        "time": 1548372111228,
+        "@timestamp": 1548372111228,
+        "username": "rmartinez2g",
+        "percent_uptime": 0.51
+      },
+      {
+        "age": 83,
+        "cost": 29.03,
+        "country": "DE",
+        "price": 66,
+        "project": "machine-learning",
+        "state": "done",
+        "time": 1548417590970,
+        "@timestamp": 1548417590970,
+        "username": "agonzales1t",
+        "percent_uptime": 0.84
+      },
+      {
+        "age": 31,
+        "cost": 38.12,
+        "country": "PH",
+        "price": 35,
+        "project": "logstash",
+        "state": "done",
+        "time": 1548419931271,
+        "@timestamp": 1548419931271,
+        "username": "lperez2f",
+        "percent_uptime": 0.69
+      },
+      {
+        "age": 97,
+        "cost": 38.24,
+        "country": "RU",
+        "price": 32,
+        "project": "apm",
+        "state": "done",
+        "time": 1548474651117,
+        "@timestamp": 1548474651117,
+        "username": "sadams1v",
+        "percent_uptime": 0.77
+      },
+      {
+        "age": 87,
+        "cost": 34.16,
+        "country": "TZ",
+        "price": 38,
+        "project": "beats",
+        "state": "start",
+        "time": 1548575991155,
+        "@timestamp": 1548575991155,
+        "username": "bmorris2n",
+        "percent_uptime": 0.65
+      },
+      {
+        "age": 74,
+        "cost": 45.69,
+        "country": "AZ",
+        "price": 66,
+        "project": "elasticsearch",
+        "state": "start",
+        "time": 1548599391338,
+        "@timestamp": 1548599391338,
+        "username": "greynolds2j",
+        "percent_uptime": 0.98
+      },
+      {
+        "age": 83,
+        "cost": 33.43,
+        "country": "BR",
+        "price": 79,
+        "project": "elasticsearch",
+        "state": "done",
+        "time": 1548648171078,
+        "@timestamp": 1548648171078,
+        "username": "kbrooks23",
+        "percent_uptime": 0.57
+      },
+      {
+        "age": 89,
+        "cost": 41.87,
+        "country": "SA",
+        "price": 44,
+        "project": "apm",
+        "state": "start",
+        "time": 1548666111256,
+        "@timestamp": 1548666111256,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.91
+      }
+    ]
+  },
+  "paginate": true,
+  "perPage": 10,
+  "showHeader": true
+}
+    
+
+ +`; + +exports[`Storyshots components/Elements/Debug small payload 1`] = ` + + +
+      {
+  "datatable": {
+    "type": "datatable",
+    "columns": [
+      {
+        "name": "@timestamp",
+        "type": "date"
+      },
+      {
+        "name": "time",
+        "type": "date"
+      },
+      {
+        "name": "cost",
+        "type": "number"
+      },
+      {
+        "name": "username",
+        "type": "string"
+      },
+      {
+        "name": "price",
+        "type": "number"
+      },
+      {
+        "name": "age",
+        "type": "number"
+      },
+      {
+        "name": "country",
+        "type": "string"
+      },
+      {
+        "name": "state",
+        "type": "string"
+      },
+      {
+        "name": "project",
+        "type": "string"
+      },
+      {
+        "name": "percent_uptime",
+        "type": "number"
+      }
+    ],
+    "rows": [
+      {
+        "age": 63,
+        "cost": 32.15,
+        "country": "US",
+        "price": 53,
+        "project": "elasticsearch",
+        "state": "running",
+        "time": 1546334211208,
+        "@timestamp": 1546334211208,
+        "username": "aevans2e",
+        "percent_uptime": 0.83
+      },
+      {
+        "age": 68,
+        "cost": 20.52,
+        "country": "JP",
+        "price": 33,
+        "project": "beats",
+        "state": "done",
+        "time": 1546351551031,
+        "@timestamp": 1546351551031,
+        "username": "aking2c",
+        "percent_uptime": 0.9
+      },
+      {
+        "age": 57,
+        "cost": 21.15,
+        "country": "UK",
+        "price": 59,
+        "project": "apm",
+        "state": "running",
+        "time": 1546352631083,
+        "@timestamp": 1546352631083,
+        "username": "mmoore2o",
+        "percent_uptime": 0.96
+      },
+      {
+        "age": 73,
+        "cost": 35.64,
+        "country": "CN",
+        "price": 71,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1546402490956,
+        "@timestamp": 1546402490956,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.61
+      },
+      {
+        "age": 38,
+        "cost": 27.19,
+        "country": "TZ",
+        "price": 36,
+        "project": "kibana",
+        "state": "done",
+        "time": 1546467111351,
+        "@timestamp": 1546467111351,
+        "username": "wrodriguez1r",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 61,
+        "cost": 49.95,
+        "country": "NL",
+        "price": 65,
+        "project": "machine-learning",
+        "state": "start",
+        "time": 1546473771019,
+        "@timestamp": 1546473771019,
+        "username": "mmoore2o",
+        "percent_uptime": 0.72
+      },
+      {
+        "age": 53,
+        "cost": 27.36,
+        "country": "JP",
+        "price": 60,
+        "project": "x-pack",
+        "state": "running",
+        "time": 1546482171310,
+        "@timestamp": 1546482171310,
+        "username": "hcrawford2h",
+        "percent_uptime": 0.65
+      },
+      {
+        "age": 31,
+        "cost": 33.77,
+        "country": "AZ",
+        "price": 77,
+        "project": "kibana",
+        "state": "start",
+        "time": 1546493451206,
+        "@timestamp": 1546493451206,
+        "username": "aking2c",
+        "percent_uptime": 0.92
+      },
+      {
+        "age": 71,
+        "cost": 20.2,
+        "country": "TZ",
+        "price": 57,
+        "project": "swiftype",
+        "state": "running",
+        "time": 1546494651235,
+        "@timestamp": 1546494651235,
+        "username": "jlawson2p",
+        "percent_uptime": 0.59
+      },
+      {
+        "age": 54,
+        "cost": 36.65,
+        "country": "TZ",
+        "price": 72,
+        "project": "apm",
+        "state": "done",
+        "time": 1546498431195,
+        "@timestamp": 1546498431195,
+        "username": "aking2c",
+        "percent_uptime": 1
+      }
+    ]
+  },
+  "paginate": true,
+  "perPage": 10,
+  "showHeader": true
+}
+    
+
+
+`; diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx b/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx new file mode 100644 index 0000000000000..ade133a2e2d04 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { Debug } from '../debug'; +import { largePayload, smallPayload } from './helpers'; + +storiesOf('components/Elements/Debug', module) + .add('small payload', () => ) + .add('large payload', () => ); diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/helpers.tsx b/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/helpers.tsx new file mode 100644 index 0000000000000..d9c45d0fb7bf1 --- /dev/null +++ b/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/helpers.tsx @@ -0,0 +1,1443 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const largePayload = { + datatable: { + type: 'datatable', + columns: [ + { + name: '@timestamp', + type: 'date', + }, + { + name: 'time', + type: 'date', + }, + { + name: 'cost', + type: 'number', + }, + { + name: 'username', + type: 'string', + }, + { + name: 'price', + type: 'number', + }, + { + name: 'age', + type: 'number', + }, + { + name: 'country', + type: 'string', + }, + { + name: 'state', + type: 'string', + }, + { + name: 'project', + type: 'string', + }, + { + name: 'percent_uptime', + type: 'number', + }, + ], + rows: [ + { + age: 63, + cost: 32.15, + country: 'US', + price: 53, + project: 'elasticsearch', + state: 'running', + time: 1546334211208, + '@timestamp': 1546334211208, + username: 'aevans2e', + percent_uptime: 0.83, + }, + { + age: 68, + cost: 20.52, + country: 'JP', + price: 33, + project: 'beats', + state: 'done', + time: 1546351551031, + '@timestamp': 1546351551031, + username: 'aking2c', + percent_uptime: 0.9, + }, + { + age: 57, + cost: 21.15, + country: 'UK', + price: 59, + project: 'apm', + state: 'running', + time: 1546352631083, + '@timestamp': 1546352631083, + username: 'mmoore2o', + percent_uptime: 0.96, + }, + { + age: 73, + cost: 35.64, + country: 'CN', + price: 71, + project: 'machine-learning', + state: 'start', + time: 1546402490956, + '@timestamp': 1546402490956, + username: 'wrodriguez1r', + percent_uptime: 0.61, + }, + { + age: 38, + cost: 27.19, + country: 'TZ', + price: 36, + project: 'kibana', + state: 'done', + time: 1546467111351, + '@timestamp': 1546467111351, + username: 'wrodriguez1r', + percent_uptime: 0.72, + }, + { + age: 61, + cost: 49.95, + country: 'NL', + price: 65, + project: 'machine-learning', + state: 'start', + time: 1546473771019, + '@timestamp': 1546473771019, + username: 'mmoore2o', + percent_uptime: 0.72, + }, + { + age: 53, + cost: 27.36, + country: 'JP', + price: 60, + project: 'x-pack', + state: 'running', + time: 1546482171310, + '@timestamp': 1546482171310, + username: 'hcrawford2h', + percent_uptime: 0.65, + }, + { + age: 31, + cost: 33.77, + country: 'AZ', + price: 77, + project: 'kibana', + state: 'start', + time: 1546493451206, + '@timestamp': 1546493451206, + username: 'aking2c', + percent_uptime: 0.92, + }, + { + age: 71, + cost: 20.2, + country: 'TZ', + price: 57, + project: 'swiftype', + state: 'running', + time: 1546494651235, + '@timestamp': 1546494651235, + username: 'jlawson2p', + percent_uptime: 0.59, + }, + { + age: 54, + cost: 36.65, + country: 'TZ', + price: 72, + project: 'apm', + state: 'done', + time: 1546498431195, + '@timestamp': 1546498431195, + username: 'aking2c', + percent_uptime: 1, + }, + { + age: 31, + cost: 26.57, + country: 'BR', + price: 48, + project: 'logstash', + state: 'done', + time: 1546509170962, + '@timestamp': 1546509170962, + username: 'hcrawford2h', + percent_uptime: 0.86, + }, + { + age: 99, + cost: 22.46, + country: 'TZ', + price: 66, + project: 'swiftype', + state: 'done', + time: 1546552371305, + '@timestamp': 1546552371305, + username: 'bmorris2n', + percent_uptime: 0.76, + }, + { + age: 87, + cost: 21.54, + country: 'US', + price: 43, + project: 'machine-learning', + state: 'start', + time: 1546575231270, + '@timestamp': 1546575231270, + username: 'sadams1v', + percent_uptime: 0.58, + }, + { + age: 10, + cost: 37.68, + country: 'CN', + price: 36, + project: 'x-pack', + state: 'done', + time: 1546678071026, + '@timestamp': 1546678071026, + username: 'jchavez2a', + percent_uptime: 0.5, + }, + { + age: 30, + cost: 21.62, + country: 'DE', + price: 78, + project: 'machine-learning', + state: 'running', + time: 1546678911351, + '@timestamp': 1546678911351, + username: 'kbrooks23', + percent_uptime: 1, + }, + { + age: 49, + cost: 26.46, + country: 'BR', + price: 76, + project: 'swiftype', + state: 'start', + time: 1546701050984, + '@timestamp': 1546701050984, + username: 'sadams1v', + percent_uptime: 0.97, + }, + { + age: 81, + cost: 36.69, + country: 'TZ', + price: 80, + project: 'logstash', + state: 'done', + time: 1546702851232, + '@timestamp': 1546702851232, + username: 'smurphy1y', + percent_uptime: 0.92, + }, + { + age: 68, + cost: 28.74, + country: 'DE', + price: 56, + project: 'machine-learning', + state: 'running', + time: 1546712451326, + '@timestamp': 1546712451326, + username: 'wmontgomery22', + percent_uptime: 0.85, + }, + { + age: 28, + cost: 21.3, + country: 'SA', + price: 72, + project: 'apm', + state: 'start', + time: 1546728771027, + '@timestamp': 1546728771027, + username: 'hbowman1s', + percent_uptime: 0.79, + }, + { + age: 57, + cost: 28.72, + country: 'UK', + price: 34, + project: 'machine-learning', + state: 'done', + time: 1546738610972, + '@timestamp': 1546738610972, + username: 'pjohnston2l', + percent_uptime: 0.6, + }, + { + age: 35, + cost: 48.87, + country: 'US', + price: 78, + project: 'apm', + state: 'running', + time: 1546761591244, + '@timestamp': 1546761591244, + username: 'bfranklin27', + percent_uptime: 0.52, + }, + { + age: 89, + cost: 29.48, + country: 'TZ', + price: 69, + project: 'beats', + state: 'done', + time: 1546791771183, + '@timestamp': 1546791771183, + username: 'ccarpenter2m', + percent_uptime: 0.72, + }, + { + age: 14, + cost: 28.94, + country: 'BR', + price: 49, + project: 'elasticsearch', + state: 'running', + time: 1546886211287, + '@timestamp': 1546886211287, + username: 'pjohnston2l', + percent_uptime: 0.75, + }, + { + age: 39, + cost: 27.16, + country: 'CN', + price: 49, + project: 'elasticsearch', + state: 'start', + time: 1546934631129, + '@timestamp': 1546934631129, + username: 'jlawson2p', + percent_uptime: 0.7, + }, + { + age: 84, + cost: 35.6, + country: 'NL', + price: 76, + project: 'swiftype', + state: 'running', + time: 1546948431271, + '@timestamp': 1546948431271, + username: 'hbowman1s', + percent_uptime: 0.72, + }, + { + age: 54, + cost: 27.08, + country: 'AZ', + price: 49, + project: 'x-pack', + state: 'start', + time: 1546986231297, + '@timestamp': 1546986231297, + username: 'krobinson2b', + percent_uptime: 0.89, + }, + { + age: 58, + cost: 26.9, + country: 'DE', + price: 43, + project: 'apm', + state: 'start', + time: 1547041191338, + '@timestamp': 1547041191338, + username: 'hperez29', + percent_uptime: 0.63, + }, + { + age: 26, + cost: 48.27, + country: 'DE', + price: 36, + project: 'machine-learning', + state: 'start', + time: 1547118111126, + '@timestamp': 1547118111126, + username: 'sadams1v', + percent_uptime: 0.56, + }, + { + age: 82, + cost: 32.13, + country: 'SA', + price: 79, + project: 'elasticsearch', + state: 'done', + time: 1547159331136, + '@timestamp': 1547159331136, + username: 'dhicks28', + percent_uptime: 0.71, + }, + { + age: 26, + cost: 20.59, + country: 'UK', + price: 52, + project: 'kibana', + state: 'done', + time: 1547174150962, + '@timestamp': 1547174150962, + username: 'greynolds2j', + percent_uptime: 0.94, + }, + { + age: 19, + cost: 25.73, + country: 'RU', + price: 45, + project: 'beats', + state: 'start', + time: 1547205411225, + '@timestamp': 1547205411225, + username: 'sadams1v', + percent_uptime: 0.6, + }, + { + age: 53, + cost: 46.19, + country: 'JP', + price: 30, + project: 'apm', + state: 'done', + time: 1547217171103, + '@timestamp': 1547217171103, + username: 'jlawson2p', + percent_uptime: 0.54, + }, + { + age: 76, + cost: 40.52, + country: 'DE', + price: 43, + project: 'machine-learning', + state: 'start', + time: 1547261271103, + '@timestamp': 1547261271103, + username: 'athomas1w', + percent_uptime: 0.86, + }, + { + age: 31, + cost: 27.62, + country: 'BR', + price: 71, + project: 'machine-learning', + state: 'start', + time: 1547262771238, + '@timestamp': 1547262771238, + username: 'jhanson1x', + percent_uptime: 0.79, + }, + { + age: 42, + cost: 30.91, + country: 'US', + price: 58, + project: 'beats', + state: 'running', + time: 1547274291106, + '@timestamp': 1547274291106, + username: 'amartinez26', + percent_uptime: 0.82, + }, + { + age: 43, + cost: 23.29, + country: 'UK', + price: 41, + project: 'kibana', + state: 'start', + time: 1547293010955, + '@timestamp': 1547293010955, + username: 'ediaz2d', + percent_uptime: 0.93, + }, + { + age: 45, + cost: 21.18, + country: 'AZ', + price: 62, + project: 'logstash', + state: 'done', + time: 1547316050970, + '@timestamp': 1547316050970, + username: 'hperez29', + percent_uptime: 0.75, + }, + { + age: 39, + cost: 29.66, + country: 'IN', + price: 40, + project: 'swiftype', + state: 'start', + time: 1547320011249, + '@timestamp': 1547320011249, + username: 'hcrawford2h', + percent_uptime: 0.99, + }, + { + age: 98, + cost: 37.42, + country: 'US', + price: 58, + project: 'beats', + state: 'done', + time: 1547331051346, + '@timestamp': 1547331051346, + username: 'jmills21', + percent_uptime: 0.51, + }, + { + age: 96, + cost: 40, + country: 'DE', + price: 58, + project: 'apm', + state: 'start', + time: 1547425371273, + '@timestamp': 1547425371273, + username: 'rsmith25', + percent_uptime: 0.87, + }, + { + age: 13, + cost: 47.45, + country: 'AZ', + price: 30, + project: 'apm', + state: 'done', + time: 1547482911215, + '@timestamp': 1547482911215, + username: 'smurphy1y', + percent_uptime: 0.83, + }, + { + age: 100, + cost: 24.36, + country: 'IN', + price: 59, + project: 'apm', + state: 'done', + time: 1547485611233, + '@timestamp': 1547485611233, + username: 'jlawson2p', + percent_uptime: 0.64, + }, + { + age: 10, + cost: 27.59, + country: 'US', + price: 53, + project: 'apm', + state: 'start', + time: 1547518911272, + '@timestamp': 1547518911272, + username: 'wmontgomery22', + percent_uptime: 0.93, + }, + { + age: 83, + cost: 37.05, + country: 'BR', + price: 77, + project: 'logstash', + state: 'running', + time: 1547521971300, + '@timestamp': 1547521971300, + username: 'hperez29', + percent_uptime: 0.53, + }, + { + age: 60, + cost: 31.19, + country: 'CN', + price: 69, + project: 'kibana', + state: 'running', + time: 1547555751264, + '@timestamp': 1547555751264, + username: 'aevans2e', + percent_uptime: 0.99, + }, + { + age: 61, + cost: 27.69, + country: 'JP', + price: 39, + project: 'elasticsearch', + state: 'start', + time: 1547564691226, + '@timestamp': 1547564691226, + username: 'greynolds2j', + percent_uptime: 0.72, + }, + { + age: 89, + cost: 33.03, + country: 'JP', + price: 75, + project: 'machine-learning', + state: 'done', + time: 1547581671013, + '@timestamp': 1547581671013, + username: 'aevans2e', + percent_uptime: 0.88, + }, + { + age: 45, + cost: 40.38, + country: 'JP', + price: 76, + project: 'x-pack', + state: 'start', + time: 1547582451365, + '@timestamp': 1547582451365, + username: 'wrodriguez1r', + percent_uptime: 0.65, + }, + { + age: 62, + cost: 29.53, + country: 'AZ', + price: 46, + project: 'machine-learning', + state: 'running', + time: 1547598471186, + '@timestamp': 1547598471186, + username: 'aking2c', + percent_uptime: 0.93, + }, + { + age: 69, + cost: 45.37, + country: 'AZ', + price: 35, + project: 'machine-learning', + state: 'start', + time: 1547599370965, + '@timestamp': 1547599370965, + username: 'jlawson2p', + percent_uptime: 0.82, + }, + { + age: 46, + cost: 39.71, + country: 'UK', + price: 39, + project: 'machine-learning', + state: 'done', + time: 1547650491235, + '@timestamp': 1547650491235, + username: 'wmontgomery22', + percent_uptime: 0.99, + }, + { + age: 62, + cost: 38.21, + country: 'SA', + price: 31, + project: 'x-pack', + state: 'start', + time: 1547667891326, + '@timestamp': 1547667891326, + username: 'greynolds2j', + percent_uptime: 0.73, + }, + { + age: 46, + cost: 28.44, + country: 'TZ', + price: 75, + project: 'apm', + state: 'running', + time: 1547685471027, + '@timestamp': 1547685471027, + username: 'aking2c', + percent_uptime: 0.7, + }, + { + age: 85, + cost: 30.5, + country: 'JP', + price: 30, + project: 'beats', + state: 'running', + time: 1547694951230, + '@timestamp': 1547694951230, + username: 'sjordan2k', + percent_uptime: 0.5, + }, + { + age: 51, + cost: 27.1, + country: 'DE', + price: 37, + project: 'kibana', + state: 'done', + time: 1547699331145, + '@timestamp': 1547699331145, + username: 'wmontgomery22', + percent_uptime: 0.79, + }, + { + age: 84, + cost: 36.47, + country: 'TZ', + price: 43, + project: 'logstash', + state: 'start', + time: 1547729571155, + '@timestamp': 1547729571155, + username: 'jchavez2a', + percent_uptime: 0.67, + }, + { + age: 66, + cost: 37.74, + country: 'PH', + price: 63, + project: 'x-pack', + state: 'start', + time: 1547738331360, + '@timestamp': 1547738331360, + username: 'ccarpenter2m', + percent_uptime: 0.74, + }, + { + age: 87, + cost: 49.07, + country: 'BR', + price: 72, + project: 'machine-learning', + state: 'running', + time: 1547742291143, + '@timestamp': 1547742291143, + username: 'hcrawford2h', + percent_uptime: 0.99, + }, + { + age: 92, + cost: 31.7, + country: 'TZ', + price: 55, + project: 'apm', + state: 'done', + time: 1547772651030, + '@timestamp': 1547772651030, + username: 'jhanson1x', + percent_uptime: 0.89, + }, + { + age: 98, + cost: 29.77, + country: 'US', + price: 72, + project: 'logstash', + state: 'start', + time: 1547786271226, + '@timestamp': 1547786271226, + username: 'wmontgomery22', + percent_uptime: 0.66, + }, + { + age: 10, + cost: 20.49, + country: 'DE', + price: 64, + project: 'machine-learning', + state: 'running', + time: 1547871831230, + '@timestamp': 1547871831230, + username: 'dmarshall24', + percent_uptime: 0.54, + }, + { + age: 69, + cost: 42.89, + country: 'AZ', + price: 61, + project: 'kibana', + state: 'start', + time: 1547902191247, + '@timestamp': 1547902191247, + username: 'sadams1v', + percent_uptime: 0.8, + }, + { + age: 42, + cost: 32.31, + country: 'SA', + price: 47, + project: 'swiftype', + state: 'running', + time: 1547922591339, + '@timestamp': 1547922591339, + username: 'bmorris2n', + percent_uptime: 0.65, + }, + { + age: 100, + cost: 30.42, + country: 'BR', + price: 42, + project: 'kibana', + state: 'done', + time: 1547926491261, + '@timestamp': 1547926491261, + username: 'jaustin1z', + percent_uptime: 0.66, + }, + { + age: 34, + cost: 48.98, + country: 'DE', + price: 70, + project: 'beats', + state: 'running', + time: 1547958651364, + '@timestamp': 1547958651364, + username: 'jlawson2p', + percent_uptime: 0.9, + }, + { + age: 68, + cost: 31.64, + country: 'NL', + price: 47, + project: 'machine-learning', + state: 'done', + time: 1547967231273, + '@timestamp': 1547967231273, + username: 'hbowman1s', + percent_uptime: 0.55, + }, + { + age: 91, + cost: 46.82, + country: 'RU', + price: 62, + project: 'swiftype', + state: 'done', + time: 1547969691305, + '@timestamp': 1547969691305, + username: 'wmontgomery22', + percent_uptime: 0.89, + }, + { + age: 17, + cost: 42.19, + country: 'IN', + price: 79, + project: 'apm', + state: 'running', + time: 1547974551309, + '@timestamp': 1547974551309, + username: 'hperez29', + percent_uptime: 0.58, + }, + { + age: 83, + cost: 25.61, + country: 'CN', + price: 54, + project: 'swiftype', + state: 'running', + time: 1547977911240, + '@timestamp': 1547977911240, + username: 'aking2c', + percent_uptime: 0.96, + }, + { + age: 31, + cost: 49.49, + country: 'JP', + price: 58, + project: 'elasticsearch', + state: 'done', + time: 1547984271197, + '@timestamp': 1547984271197, + username: 'dmarshall24', + percent_uptime: 0.72, + }, + { + age: 97, + cost: 33.33, + country: 'PH', + price: 34, + project: 'logstash', + state: 'start', + time: 1547984631153, + '@timestamp': 1547984631153, + username: 'hbowman1s', + percent_uptime: 0.56, + }, + { + age: 67, + cost: 31.1, + country: 'US', + price: 73, + project: 'x-pack', + state: 'done', + time: 1548001430974, + '@timestamp': 1548001430974, + username: 'ccarpenter2m', + percent_uptime: 0.78, + }, + { + age: 31, + cost: 21.6, + country: 'PH', + price: 73, + project: 'kibana', + state: 'running', + time: 1548014391252, + '@timestamp': 1548014391252, + username: 'jmills21', + percent_uptime: 0.59, + }, + { + age: 57, + cost: 25.84, + country: 'NL', + price: 53, + project: 'swiftype', + state: 'start', + time: 1548039051145, + '@timestamp': 1548039051145, + username: 'dhicks28', + percent_uptime: 0.63, + }, + { + age: 92, + cost: 27.09, + country: 'CN', + price: 34, + project: 'apm', + state: 'done', + time: 1548052791195, + '@timestamp': 1548052791195, + username: 'dramirez2i', + percent_uptime: 0.98, + }, + { + age: 43, + cost: 36.39, + country: 'US', + price: 68, + project: 'elasticsearch', + state: 'done', + time: 1548058071369, + '@timestamp': 1548058071369, + username: 'wmontgomery22', + percent_uptime: 0.55, + }, + { + age: 68, + cost: 44.69, + country: 'JP', + price: 66, + project: 'machine-learning', + state: 'running', + time: 1548072471282, + '@timestamp': 1548072471282, + username: 'jmills21', + percent_uptime: 0.68, + }, + { + age: 47, + cost: 25.34, + country: 'NL', + price: 32, + project: 'kibana', + state: 'running', + time: 1548075171245, + '@timestamp': 1548075171245, + username: 'wrodriguez1r', + percent_uptime: 0.95, + }, + { + age: 19, + cost: 25.4, + country: 'SA', + price: 42, + project: 'kibana', + state: 'start', + time: 1548125331273, + '@timestamp': 1548125331273, + username: 'dhicks28', + percent_uptime: 0.95, + }, + { + age: 88, + cost: 36.38, + country: 'TZ', + price: 77, + project: 'x-pack', + state: 'start', + time: 1548126771234, + '@timestamp': 1548126771234, + username: 'sjordan2k', + percent_uptime: 0.84, + }, + { + age: 36, + cost: 28.62, + country: 'DE', + price: 34, + project: 'kibana', + state: 'start', + time: 1548128331153, + '@timestamp': 1548128331153, + username: 'dramirez2i', + percent_uptime: 0.72, + }, + { + age: 32, + cost: 48.69, + country: 'AZ', + price: 40, + project: 'swiftype', + state: 'start', + time: 1548161391285, + '@timestamp': 1548161391285, + username: 'dramirez2i', + percent_uptime: 0.69, + }, + { + age: 53, + cost: 44.25, + country: 'UK', + price: 35, + project: 'machine-learning', + state: 'running', + time: 1548192651185, + '@timestamp': 1548192651185, + username: 'wmontgomery22', + percent_uptime: 0.68, + }, + { + age: 37, + cost: 32.67, + country: 'DE', + price: 31, + project: 'kibana', + state: 'running', + time: 1548218751137, + '@timestamp': 1548218751137, + username: 'ccarpenter2m', + percent_uptime: 0.77, + }, + { + age: 58, + cost: 40.83, + country: 'PH', + price: 61, + project: 'logstash', + state: 'running', + time: 1548221151061, + '@timestamp': 1548221151061, + username: 'dmarshall24', + percent_uptime: 0.88, + }, + { + age: 45, + cost: 42.97, + country: 'AZ', + price: 44, + project: 'machine-learning', + state: 'running', + time: 1548262131313, + '@timestamp': 1548262131313, + username: 'dmarshall24', + percent_uptime: 0.64, + }, + { + age: 21, + cost: 23.16, + country: 'NL', + price: 78, + project: 'machine-learning', + state: 'start', + time: 1548265611336, + '@timestamp': 1548265611336, + username: 'jlawson2p', + percent_uptime: 0.88, + }, + { + age: 77, + cost: 31.37, + country: 'RU', + price: 52, + project: 'kibana', + state: 'start', + time: 1548274611337, + '@timestamp': 1548274611337, + username: 'jhanson1x', + percent_uptime: 0.68, + }, + { + age: 34, + cost: 41.41, + country: 'AZ', + price: 52, + project: 'elasticsearch', + state: 'start', + time: 1548276411368, + '@timestamp': 1548276411368, + username: 'agonzales1t', + percent_uptime: 0.75, + }, + { + age: 95, + cost: 24.93, + country: 'AZ', + price: 66, + project: 'logstash', + state: 'running', + time: 1548301071035, + '@timestamp': 1548301071035, + username: 'phansen1q', + percent_uptime: 0.75, + }, + { + age: 12, + cost: 32.33, + country: 'PH', + price: 31, + project: 'elasticsearch', + state: 'start', + time: 1548342711164, + '@timestamp': 1548342711164, + username: 'amartinez26', + percent_uptime: 0.96, + }, + { + age: 15, + cost: 44.74, + country: 'IN', + price: 41, + project: 'x-pack', + state: 'done', + time: 1548372111228, + '@timestamp': 1548372111228, + username: 'rmartinez2g', + percent_uptime: 0.51, + }, + { + age: 83, + cost: 29.03, + country: 'DE', + price: 66, + project: 'machine-learning', + state: 'done', + time: 1548417590970, + '@timestamp': 1548417590970, + username: 'agonzales1t', + percent_uptime: 0.84, + }, + { + age: 31, + cost: 38.12, + country: 'PH', + price: 35, + project: 'logstash', + state: 'done', + time: 1548419931271, + '@timestamp': 1548419931271, + username: 'lperez2f', + percent_uptime: 0.69, + }, + { + age: 97, + cost: 38.24, + country: 'RU', + price: 32, + project: 'apm', + state: 'done', + time: 1548474651117, + '@timestamp': 1548474651117, + username: 'sadams1v', + percent_uptime: 0.77, + }, + { + age: 87, + cost: 34.16, + country: 'TZ', + price: 38, + project: 'beats', + state: 'start', + time: 1548575991155, + '@timestamp': 1548575991155, + username: 'bmorris2n', + percent_uptime: 0.65, + }, + { + age: 74, + cost: 45.69, + country: 'AZ', + price: 66, + project: 'elasticsearch', + state: 'start', + time: 1548599391338, + '@timestamp': 1548599391338, + username: 'greynolds2j', + percent_uptime: 0.98, + }, + { + age: 83, + cost: 33.43, + country: 'BR', + price: 79, + project: 'elasticsearch', + state: 'done', + time: 1548648171078, + '@timestamp': 1548648171078, + username: 'kbrooks23', + percent_uptime: 0.57, + }, + { + age: 89, + cost: 41.87, + country: 'SA', + price: 44, + project: 'apm', + state: 'start', + time: 1548666111256, + '@timestamp': 1548666111256, + username: 'hcrawford2h', + percent_uptime: 0.91, + }, + { + age: 83, + cost: 33.43, + country: 'BR', + price: 79, + project: 'elasticsearch', + state: 'done', + time: 1548648171078, + '@timestamp': 1548648171078, + username: 'kbrooks23', + percent_uptime: 0.57, + }, + { + age: 89, + cost: 41.87, + country: 'SA', + price: 44, + project: 'apm', + state: 'start', + time: 1548666111256, + '@timestamp': 1548666111256, + username: 'hcrawford2h', + percent_uptime: 0.91, + }, + ], + }, + paginate: true, + perPage: 10, + showHeader: true, +}; + +export const smallPayload = { + datatable: { + type: 'datatable', + columns: [ + { + name: '@timestamp', + type: 'date', + }, + { + name: 'time', + type: 'date', + }, + { + name: 'cost', + type: 'number', + }, + { + name: 'username', + type: 'string', + }, + { + name: 'price', + type: 'number', + }, + { + name: 'age', + type: 'number', + }, + { + name: 'country', + type: 'string', + }, + { + name: 'state', + type: 'string', + }, + { + name: 'project', + type: 'string', + }, + { + name: 'percent_uptime', + type: 'number', + }, + ], + rows: [ + { + age: 63, + cost: 32.15, + country: 'US', + price: 53, + project: 'elasticsearch', + state: 'running', + time: 1546334211208, + '@timestamp': 1546334211208, + username: 'aevans2e', + percent_uptime: 0.83, + }, + { + age: 68, + cost: 20.52, + country: 'JP', + price: 33, + project: 'beats', + state: 'done', + time: 1546351551031, + '@timestamp': 1546351551031, + username: 'aking2c', + percent_uptime: 0.9, + }, + { + age: 57, + cost: 21.15, + country: 'UK', + price: 59, + project: 'apm', + state: 'running', + time: 1546352631083, + '@timestamp': 1546352631083, + username: 'mmoore2o', + percent_uptime: 0.96, + }, + { + age: 73, + cost: 35.64, + country: 'CN', + price: 71, + project: 'machine-learning', + state: 'start', + time: 1546402490956, + '@timestamp': 1546402490956, + username: 'wrodriguez1r', + percent_uptime: 0.61, + }, + { + age: 38, + cost: 27.19, + country: 'TZ', + price: 36, + project: 'kibana', + state: 'done', + time: 1546467111351, + '@timestamp': 1546467111351, + username: 'wrodriguez1r', + percent_uptime: 0.72, + }, + { + age: 61, + cost: 49.95, + country: 'NL', + price: 65, + project: 'machine-learning', + state: 'start', + time: 1546473771019, + '@timestamp': 1546473771019, + username: 'mmoore2o', + percent_uptime: 0.72, + }, + { + age: 53, + cost: 27.36, + country: 'JP', + price: 60, + project: 'x-pack', + state: 'running', + time: 1546482171310, + '@timestamp': 1546482171310, + username: 'hcrawford2h', + percent_uptime: 0.65, + }, + { + age: 31, + cost: 33.77, + country: 'AZ', + price: 77, + project: 'kibana', + state: 'start', + time: 1546493451206, + '@timestamp': 1546493451206, + username: 'aking2c', + percent_uptime: 0.92, + }, + { + age: 71, + cost: 20.2, + country: 'TZ', + price: 57, + project: 'swiftype', + state: 'running', + time: 1546494651235, + '@timestamp': 1546494651235, + username: 'jlawson2p', + percent_uptime: 0.59, + }, + { + age: 54, + cost: 36.65, + country: 'TZ', + price: 72, + project: 'apm', + state: 'done', + time: 1546498431195, + '@timestamp': 1546498431195, + username: 'aking2c', + percent_uptime: 1, + }, + ], + }, + paginate: true, + perPage: 10, + showHeader: true, +}; diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/debug.js b/x-pack/legacy/plugins/canvas/public/components/debug/debug.tsx similarity index 72% rename from x-pack/legacy/plugins/canvas/public/components/debug/debug.js rename to x-pack/legacy/plugins/canvas/public/components/debug/debug.tsx index 749ba00758881..eb8189d479f4c 100644 --- a/x-pack/legacy/plugins/canvas/public/components/debug/debug.js +++ b/x-pack/legacy/plugins/canvas/public/components/debug/debug.tsx @@ -7,9 +7,17 @@ import React from 'react'; import PropTypes from 'prop-types'; import { EuiCode } from '@elastic/eui'; -export const Debug = ({ payload }) => ( + +const LimitRows = (key: string, value: any) => { + if (key === 'rows') { + return value.slice(0, 99); + } + return value; +}; + +export const Debug = ({ payload }: any) => ( -
{JSON.stringify(payload, null, 2)}
+
{JSON.stringify(payload, LimitRows, 2)}
); diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/index.js b/x-pack/legacy/plugins/canvas/public/components/debug/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/index.js rename to x-pack/legacy/plugins/canvas/public/components/debug/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js b/x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js index e21ffb16a10b6..ab023aef9520f 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js +++ b/x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js @@ -81,11 +81,15 @@ export class ElementShareContainer extends React.PureComponent { }; render() { + const shouldTrackComplete = this.props.functionName !== 'embeddable'; + // NOTE: the data-shared-item and data-render-complete attributes are used for reporting + // Embeddables should be setting data-shared-item and data-render-complete on themselves + // so we should not be tracking them here. return (
(this.sharedItemRef = ref)} > diff --git a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx index 353a59397d6b6..a86784d374f49 100644 --- a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx @@ -24,10 +24,10 @@ const allowedEmbeddables = { [EmbeddableTypes.lens]: (id: string) => { return `savedLens id="${id}" | render`; }, - // FIX: Only currently allow Map embeddables - /* [EmbeddableTypes.visualization]: (id: string) => { - return `filters | savedVisualization id="${id}" | render`; + [EmbeddableTypes.visualization]: (id: string) => { + return `savedVisualization id="${id}" | render`; }, + /* [EmbeddableTypes.search]: (id: string) => { return `filters | savedSearch id="${id}" | render`; },*/ diff --git a/x-pack/legacy/plugins/graph/index.ts b/x-pack/legacy/plugins/graph/index.ts index 53d32a836cfa1..5c7f8fa46c18b 100644 --- a/x-pack/legacy/plugins/graph/index.ts +++ b/x-pack/legacy/plugins/graph/index.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; - // @ts-ignore import migrations from './migrations'; import mappings from './mappings.json'; @@ -30,40 +28,5 @@ export const graph: LegacyPluginInitializer = kibana => { .default('configAndData'), }).default(); }, - - init(server) { - server.plugins.xpack_main.registerFeature({ - id: 'graph', - name: i18n.translate('xpack.graph.featureRegistry.graphFeatureName', { - defaultMessage: 'Graph', - }), - order: 1200, - icon: 'graphApp', - navLinkId: 'graph', - app: ['graph', 'kibana'], - catalogue: ['graph'], - validLicenses: ['platinum', 'enterprise', 'trial'], - privileges: { - all: { - app: ['graph', 'kibana'], - catalogue: ['graph'], - savedObject: { - all: ['graph-workspace'], - read: ['index-pattern'], - }, - ui: ['save', 'delete'], - }, - read: { - app: ['graph', 'kibana'], - catalogue: ['graph'], - savedObject: { - all: [], - read: ['index-pattern', 'graph-workspace'], - }, - ui: [], - }, - }, - }); - }, }); }; diff --git a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js index 7a656b33d59ff..c6d28adcefd78 100644 --- a/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js +++ b/x-pack/legacy/plugins/grokdebugger/public/services/grokdebugger/grokdebugger_service.js @@ -4,19 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import chrome from 'ui/chrome'; import { ROUTES } from '../../../common/constants'; import { GrokdebuggerResponse } from 'plugins/grokdebugger/models/grokdebugger_response'; export class GrokdebuggerService { constructor(http) { this.http = http; - this.basePath = chrome.addBasePath(ROUTES.API_ROOT); } simulate(grokdebuggerRequest) { return this.http - .post(`${this.basePath}/simulate`, { body: JSON.stringify(grokdebuggerRequest.upstreamJSON) }) + .post(`${ROUTES.API_ROOT}/simulate`, { + body: JSON.stringify(grokdebuggerRequest.upstreamJSON), + }) .then(response => { return GrokdebuggerResponse.fromUpstreamJSON(response.grokdebuggerResponse); }) diff --git a/x-pack/legacy/plugins/lens/index.ts b/x-pack/legacy/plugins/lens/index.ts index b1c67fb81ba07..e9a901c58cd90 100644 --- a/x-pack/legacy/plugins/lens/index.ts +++ b/x-pack/legacy/plugins/lens/index.ts @@ -7,12 +7,7 @@ import * as Joi from 'joi'; import { resolve } from 'path'; import { LegacyPluginInitializer } from 'src/legacy/types'; -import mappings from './mappings.json'; -import { - PLUGIN_ID, - getEditPath, - NOT_INTERNATIONALIZED_PRODUCT_NAME, -} from '../../../plugins/lens/common'; +import { PLUGIN_ID, NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../../plugins/lens/common'; export const lens: LegacyPluginInitializer = kibana => { return new kibana.Plugin({ @@ -32,18 +27,6 @@ export const lens: LegacyPluginInitializer = kibana => { visualize: [`plugins/${PLUGIN_ID}/legacy`], embeddableFactories: [`plugins/${PLUGIN_ID}/legacy`], styleSheetPaths: resolve(__dirname, 'public/index.scss'), - mappings, - savedObjectsManagement: { - lens: { - defaultSearchField: 'title', - isImportableAndExportable: true, - getTitle: (obj: { attributes: { title: string } }) => obj.attributes.title, - getInAppUrl: (obj: { id: string }) => ({ - path: getEditPath(obj.id), - uiCapabilitiesPath: 'lens.show', - }), - }, - }, }, config: () => { diff --git a/x-pack/legacy/plugins/lens/mappings.json b/x-pack/legacy/plugins/lens/mappings.json deleted file mode 100644 index 8304cf9c9cb64..0000000000000 --- a/x-pack/legacy/plugins/lens/mappings.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "lens": { - "properties": { - "title": { - "type": "text" - }, - "visualizationType": { - "type": "keyword" - }, - "state": { - "type": "flattened" - }, - "expression": { - "index": false, - "type": "keyword" - } - } - }, - "lens-ui-telemetry": { - "properties": { - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - }, - "date": { - "type": "date" - }, - "count": { - "type": "integer" - } - } - } -} diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index fbda18cc0e307..be72dd4b4edef 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -77,6 +77,20 @@ function createMockFilterManager() { }; } +function createMockTimefilter() { + const unsubscribe = jest.fn(); + + return { + getTime: jest.fn(() => ({ from: 'now-7d', to: 'now' })), + setTime: jest.fn(), + getTimeUpdate$: () => ({ + subscribe: ({ next }: { next: () => void }) => { + return unsubscribe; + }, + }), + }; +} + describe('Lens App', () => { let frame: jest.Mocked; let core: ReturnType; @@ -108,10 +122,7 @@ describe('Lens App', () => { query: { filterManager: createMockFilterManager(), timefilter: { - timefilter: { - getTime: jest.fn(() => ({ from: 'now-7d', to: 'now' })), - setTime: jest.fn(), - }, + timefilter: createMockTimefilter(), }, }, indexPatterns: { diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index a0c6e4c21a34b..dfea2e39fcbc5 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -94,8 +94,23 @@ export function App({ trackUiEvent('app_filters_updated'); }, }); + + const timeSubscription = data.query.timefilter.timefilter.getTimeUpdate$().subscribe({ + next: () => { + const currentRange = data.query.timefilter.timefilter.getTime(); + setState(s => ({ + ...s, + dateRange: { + fromDate: currentRange.from, + toDate: currentRange.to, + }, + })); + }, + }); + return () => { filterSubscription.unsubscribe(); + timeSubscription.unsubscribe(); }; }, []); diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx index 440f7bdc42bcb..050f294d0b964 100644 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx +++ b/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx @@ -8,13 +8,12 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { i18n } from '@kbn/i18n'; import { EuiBasicTable } from '@elastic/eui'; -import { LensMultiTable } from '../types'; +import { FormatFactory, LensMultiTable } from '../types'; import { ExpressionFunctionDefinition, ExpressionRenderDefinition, IInterpreterRenderHandlers, } from '../../../../../../src/plugins/expressions/public'; -import { FormatFactory } from '../../../../../../src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities'; import { VisualizationContainer } from '../visualization_container'; export interface DatatableColumns { @@ -102,7 +101,7 @@ export const datatableColumns: ExpressionFunctionDefinition< }; export const getDatatableRenderer = ( - formatFactory: FormatFactory + formatFactory: Promise ): ExpressionRenderDefinition => ({ name: 'lens_datatable_renderer', displayName: i18n.translate('xpack.lens.datatable.visualizationName', { @@ -116,8 +115,9 @@ export const getDatatableRenderer = ( config: DatatableProps, handlers: IInterpreterRenderHandlers ) => { + const resolvedFormatFactory = await formatFactory; ReactDOM.render( - , + , domNode, () => { handlers.done(); diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts b/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts index 6dee47cc632c2..7a54a5daa3095 100644 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts +++ b/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts @@ -8,12 +8,11 @@ import { CoreSetup } from 'src/core/public'; import { datatableVisualization } from './visualization'; import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; import { datatable, datatableColumns, getDatatableRenderer } from './expression'; -import { FormatFactory } from '../legacy_imports'; -import { EditorFrameSetup } from '../types'; +import { EditorFrameSetup, FormatFactory } from '../types'; export interface DatatableVisualizationPluginSetupPlugins { expressions: ExpressionsSetup; - formatFactory: FormatFactory; + formatFactory: Promise; editorFrame: EditorFrameSetup; } diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx index 252ba5c9bc0bc..c2ab1c72af545 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx @@ -14,8 +14,11 @@ import { IIndexPattern, TimefilterContract, } from 'src/plugins/data/public'; + import { Subscription } from 'rxjs'; import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +import { VIS_EVENT_TO_TRIGGER } from '../../../../../../../src/plugins/visualizations/public'; + import { Embeddable as AbstractEmbeddable, EmbeddableOutput, @@ -90,6 +93,18 @@ export class Embeddable extends AbstractEmbeddable !filter.meta.disabled) diff --git a/x-pack/legacy/plugins/lens/public/helpers/index.ts b/x-pack/legacy/plugins/lens/public/helpers/index.ts new file mode 100644 index 0000000000000..f464b5dcc97a3 --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/helpers/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { addEmbeddableToDashboardUrl, getUrlVars } from './url_helper'; diff --git a/x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts b/x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts new file mode 100644 index 0000000000000..9c59c9a96d00f --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../legacy_imports', () => ({ + DashboardConstants: { + ADD_EMBEDDABLE_ID: 'addEmbeddableId', + ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', + }, +})); + +import { addEmbeddableToDashboardUrl, getUrlVars } from './url_helper'; + +describe('Dashboard URL Helper', () => { + it('addEmbeddableToDashboardUrl', () => { + const id = '123eb456cd'; + const urlVars = { + x: '1', + y: '2', + z: '3', + }; + const url = + "/pep/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!())"; + expect(addEmbeddableToDashboardUrl(url, id, urlVars)).toEqual( + `/pep/app/kibana#/dashboard?_a=%28description%3A%27%27%2Cfilters%3A%21%28%29%29&_g=%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29&addEmbeddableId=${id}&addEmbeddableType=lens&x=1&y=2&z=3` + ); + }); + + it('getUrlVars', () => { + let url = + "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; + expect(getUrlVars(url)).toEqual({ + _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))', + _a: "(description:'',filters:!()", + }); + url = 'http://mybusiness.mydomain.com/app/kibana#/dashboard?x=y&y=z'; + expect(getUrlVars(url)).toEqual({ + x: 'y', + y: 'z', + }); + url = 'http://localhost:5601/app/kibana#/dashboard/777182'; + expect(getUrlVars(url)).toEqual({}); + url = + 'http://localhost:5601/app/kibana#/dashboard/777182?title=Some%20Dashboard%20With%20Spaces'; + expect(getUrlVars(url)).toEqual({ title: 'Some Dashboard With Spaces' }); + }); +}); diff --git a/x-pack/legacy/plugins/lens/public/helpers/url_helper.ts b/x-pack/legacy/plugins/lens/public/helpers/url_helper.ts new file mode 100644 index 0000000000000..fca44195b98c4 --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/helpers/url_helper.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { parseUrl, stringify } from 'query-string'; +import { DashboardConstants } from '../legacy_imports'; + +type UrlVars = Record; + +/** + * Return query params from URL + * @param url given url + */ +export function getUrlVars(url: string): Record { + const vars: UrlVars = {}; + for (const [, key, value] of url.matchAll(/[?&]+([^=&]+)=([^&]*)/gi)) { + vars[key] = decodeURIComponent(value); + } + return vars; +} + +/** * + * Returns dashboard URL with added embeddableType and embeddableId query params + * eg. + * input: url: /lol/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)), embeddableId: 12345 + * output: /lol/app/kibana#/dashboard?addEmbeddableType=lens&addEmbeddableId=12345&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)) + * @param url dasbhoard absolute url + * @param embeddableId id of the saved visualization + * @param urlVars url query params + */ +export function addEmbeddableToDashboardUrl(url: string, embeddableId: string, urlVars: UrlVars) { + const dashboardParsedUrl = parseUrl(url); + const keys = Object.keys(urlVars).sort(); + + keys.forEach(key => { + dashboardParsedUrl.query[key] = urlVars[key]; + }); + dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = 'lens'; + dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + const query = stringify(dashboardParsedUrl.query); + + return `${dashboardParsedUrl.url}?${query}`; +} diff --git a/x-pack/legacy/plugins/lens/public/legacy.ts b/x-pack/legacy/plugins/lens/public/legacy.ts index 1cfd3e198547d..b7d47644c7f31 100644 --- a/x-pack/legacy/plugins/lens/public/legacy.ts +++ b/x-pack/legacy/plugins/lens/public/legacy.ts @@ -5,7 +5,7 @@ */ import { npSetup, npStart } from 'ui/new_platform'; -import { getFormat, visualizations } from './legacy_imports'; +import { visualizations } from './legacy_imports'; export * from './types'; @@ -14,6 +14,6 @@ import { plugin } from './index'; const pluginInstance = plugin(); pluginInstance.setup(npSetup.core, { ...npSetup.plugins, - __LEGACY: { formatFactory: getFormat, visualizations }, + __LEGACY: { visualizations }, }); pluginInstance.start(npStart.core, npStart.plugins); diff --git a/x-pack/legacy/plugins/lens/public/legacy_imports.ts b/x-pack/legacy/plugins/lens/public/legacy_imports.ts index 88f189fe3db5a..857443ae0fa1c 100644 --- a/x-pack/legacy/plugins/lens/public/legacy_imports.ts +++ b/x-pack/legacy/plugins/lens/public/legacy_imports.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { getFormat, FormatFactory } from 'ui/visualize/loader/pipeline_helpers/utilities'; -export { setup as visualizations } from '../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/legacy'; -export { VisualizationsSetup } from '../../../../../src/legacy/core_plugins/visualizations/public'; +import { npSetup } from 'ui/new_platform'; +export const { visualizations } = npSetup.plugins; +export { VisualizationsSetup } from '../../../../../src/plugins/visualizations/public'; +export { DashboardConstants } from '../../../../../src/legacy/core_plugins/kibana/public/dashboard'; diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts b/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts index 217cc6902fc99..65f064258a5e2 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts +++ b/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts @@ -5,15 +5,14 @@ */ import { CoreSetup } from 'src/core/public'; -import { FormatFactory } from '../legacy_imports'; import { metricVisualization } from './metric_visualization'; import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; import { metricChart, getMetricChartRenderer } from './metric_expression'; -import { EditorFrameSetup } from '../types'; +import { EditorFrameSetup, FormatFactory } from '../types'; export interface MetricVisualizationPluginSetupPlugins { expressions: ExpressionsSetup; - formatFactory: FormatFactory; + formatFactory: Promise; editorFrame: EditorFrameSetup; } diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx index 4d979a766cd2b..a80552e57a9e0 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx @@ -6,14 +6,13 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { FormatFactory } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { ExpressionFunctionDefinition, ExpressionRenderDefinition, IInterpreterRenderHandlers, } from '../../../../../../src/plugins/expressions/public'; import { MetricConfig } from './types'; -import { LensMultiTable } from '../types'; +import { FormatFactory, LensMultiTable } from '../types'; import { AutoScale } from './auto_scale'; import { VisualizationContainer } from '../visualization_container'; @@ -68,17 +67,26 @@ export const metricChart: ExpressionFunctionDefinition< }; export const getMetricChartRenderer = ( - formatFactory: FormatFactory + formatFactory: Promise ): ExpressionRenderDefinition => ({ name: 'lens_metric_chart_renderer', displayName: 'Metric chart', help: 'Metric chart renderer', validate: () => undefined, reuseDomNode: true, - render: (domNode: Element, config: MetricChartProps, handlers: IInterpreterRenderHandlers) => { - ReactDOM.render(, domNode, () => { - handlers.done(); - }); + render: async ( + domNode: Element, + config: MetricChartProps, + handlers: IInterpreterRenderHandlers + ) => { + const resolvedFormatFactory = await formatFactory; + ReactDOM.render( + , + domNode, + () => { + handlers.done(); + } + ); handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); }, }); diff --git a/x-pack/legacy/plugins/lens/public/plugin.tsx b/x-pack/legacy/plugins/lens/public/plugin.tsx index c74653c70703c..45817fdc3c05f 100644 --- a/x-pack/legacy/plugins/lens/public/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/plugin.tsx @@ -8,10 +8,14 @@ import React from 'react'; import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom'; import { render, unmountComponentAtNode } from 'react-dom'; -import { AppMountParameters, CoreSetup, CoreStart } from 'src/core/public'; -import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public'; import rison, { RisonObject, RisonValue } from 'rison-node'; import { isObject } from 'lodash'; + +import { AppMountParameters, CoreSetup, CoreStart } from 'src/core/public'; +import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public'; +import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public'; +import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public'; +import { KibanaLegacySetup } from 'src/plugins/kibana_legacy/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { EditorFrameService } from './editor_frame_service'; import { IndexPatternDatasource } from './indexpattern_datasource'; @@ -19,7 +23,6 @@ import { addHelpMenuToAppChrome } from './help_menu_util'; import { SavedObjectIndexStore } from './persistence'; import { XyVisualization } from './xy_visualization'; import { MetricVisualization } from './metric_visualization'; -import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public'; import { DatatableVisualization } from './datatable_visualization'; import { App } from './app_plugin'; import { @@ -28,18 +31,13 @@ import { stopReportManager, trackUiEvent, } from './lens_ui_telemetry'; -import { KibanaLegacySetup } from '../../../../../src/plugins/kibana_legacy/public'; + +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../../../plugins/lens/common'; -import { - addEmbeddableToDashboardUrl, - getUrlVars, - getLensUrlFromDashboardAbsoluteUrl, -} from '../../../../../src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper'; -import { FormatFactory } from './legacy_imports'; -import { EmbeddableSetup, EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; +import { addEmbeddableToDashboardUrl, getUrlVars } from './helpers'; import { EditorFrameStart } from './types'; import { getLensAliasConfig } from './vis_type_alias'; -import { VisualizationsSetup } from './legacy_imports'; +import { VisualizationsSetup, DashboardConstants } from './legacy_imports'; export interface LensPluginSetupDependencies { kibanaLegacy: KibanaLegacySetup; @@ -47,7 +45,6 @@ export interface LensPluginSetupDependencies { data: DataPublicPluginSetup; embeddable: EmbeddableSetup; __LEGACY: { - formatFactory: FormatFactory; visualizations: VisualizationsSetup; }; } @@ -56,6 +53,7 @@ export interface LensPluginStartDependencies { data: DataPublicPluginStart; embeddable: EmbeddableStart; expressions: ExpressionsStart; + uiActions: UiActionsStart; } export const isRisonObject = (value: RisonValue): value is RisonObject => { @@ -84,7 +82,7 @@ export class LensPlugin { expressions, data, embeddable, - __LEGACY: { formatFactory, visualizations }, + __LEGACY: { visualizations }, }: LensPluginSetupDependencies ) { const editorFrameSetupInterface = this.editorFrameService.setup(core, { @@ -96,7 +94,9 @@ export class LensPlugin { expressions, data, editorFrame: editorFrameSetupInterface, - formatFactory, + formatFactory: core + .getStartServices() + .then(([_, { data: dataStart }]) => dataStart.fieldFormats.deserialize), }; this.indexpatternDatasource.setup(core, dependencies); this.xyVisualization.setup(core, dependencies); @@ -142,40 +142,24 @@ export class LensPlugin { routeProps.history.push(`/lens/edit/${id}`); } else if (addToDashboardMode && id) { routeProps.history.push(`/lens/edit/${id}`); - const url = coreStart.chrome.navLinks.get('kibana:dashboard'); - if (!url) { + const lastDashboardLink = coreStart.chrome.navLinks.get('kibana:dashboard'); + if (!lastDashboardLink || !lastDashboardLink.url) { throw new Error('Cannot get last dashboard url'); } - const lastDashboardAbsoluteUrl = url.url; - const basePath = coreStart.http.basePath.get(); - const lensUrl = getLensUrlFromDashboardAbsoluteUrl( - lastDashboardAbsoluteUrl, - basePath, - id - ); - if (!lastDashboardAbsoluteUrl || !lensUrl) { - throw new Error('Cannot get last dashboard url'); - } - window.history.pushState({}, '', lensUrl); - const urlVars = getUrlVars(lastDashboardAbsoluteUrl); + const urlVars = getUrlVars(lastDashboardLink.url); updateUrlTime(urlVars); // we need to pass in timerange in query params directly - const dashboardParsedUrl = addEmbeddableToDashboardUrl( - lastDashboardAbsoluteUrl, - basePath, - id, - urlVars - ); - if (!dashboardParsedUrl) { - throw new Error('Problem parsing dashboard url'); - } - window.history.pushState({}, '', dashboardParsedUrl); + const dashboardUrl = addEmbeddableToDashboardUrl(lastDashboardLink.url, id, urlVars); + window.history.pushState({}, '', dashboardUrl); } }; const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => { trackUiEvent('loaded'); const addToDashboardMode = - !!routeProps.location.search && routeProps.location.search.includes('addToDashboard'); + !!routeProps.location.search && + routeProps.location.search.includes( + DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM + ); return ( void; +export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat; + export interface PublicAPIProps { state: T; layerId: string; diff --git a/x-pack/legacy/plugins/lens/public/vis_type_alias.ts b/x-pack/legacy/plugins/lens/public/vis_type_alias.ts index c4e0a20110c81..123b994e6ccce 100644 --- a/x-pack/legacy/plugins/lens/public/vis_type_alias.ts +++ b/x-pack/legacy/plugins/lens/public/vis_type_alias.ts @@ -5,8 +5,8 @@ */ import { i18n } from '@kbn/i18n'; +import { VisTypeAlias } from 'src/plugins/visualizations/public'; import { getBasePath, getEditPath } from '../../../../plugins/lens/common'; -import { VisTypeAlias } from '../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/vis_types'; export const getLensAliasConfig = (): VisTypeAlias => ({ aliasUrl: getBasePath(), diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap b/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap index 4b19ad288ddaa..bef53c2fd266e 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap @@ -6,6 +6,7 @@ exports[`xy_expression XYChart component it renders area 1`] = ` > ; editorFrame: EditorFrameSetup; } +interface XyVisualizationPluginStartPlugins { + uiActions: UiActionsStart; +} + function getTimeZone(uiSettings: IUiSettingsClient) { const configuredTimeZone = uiSettings.get('dateFormat:tz'); if (configuredTimeZone === 'Browser') { @@ -53,4 +58,7 @@ export class XyVisualization { editorFrame.registerVisualization(xyVisualization); } + start(core: CoreStart, { uiActions }: XyVisualizationPluginStartPlugins) { + setExecuteTriggerActions(uiActions.executeTriggerActions); + } } diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/services.ts b/x-pack/legacy/plugins/lens/public/xy_visualization/services.ts new file mode 100644 index 0000000000000..af683efb86534 --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/services.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createGetterSetter } from '../../../../../../src/plugins/kibana_utils/public'; +import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; + +export const [getExecuteTriggerActions, setExecuteTriggerActions] = createGetterSetter< + UiActionsStart['executeTriggerActions'] +>('executeTriggerActions'); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx index adf64fece2942..cdc5fc2ff1c17 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx @@ -12,6 +12,8 @@ import { LineSeries, Settings, ScaleType, + GeometryValue, + XYChartSeriesIdentifier, SeriesNameFn, } from '@elastic/charts'; import { xyChart, XYChart } from './xy_expression'; @@ -20,6 +22,9 @@ import React from 'react'; import { shallow } from 'enzyme'; import { XYArgs, LegendConfig, legendConfig, layerConfig, LayerArgs } from './types'; import { createMockExecutionContext } from '../../../../../../src/plugins/expressions/common/mocks'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; + +const executeTriggerActions = jest.fn(); function sampleArgs() { const data: LensMultiTable = { @@ -34,7 +39,12 @@ function sampleArgs() { formatHint: { id: 'number', params: { pattern: '0,0.000' } }, }, { id: 'b', name: 'b', formatHint: { id: 'number', params: { pattern: '000,0' } } }, - { id: 'c', name: 'c', formatHint: { id: 'string' } }, + { + id: 'c', + name: 'c', + formatHint: { id: 'string' }, + meta: { type: 'date-histogram', aggConfigParams: { interval: '10s' } }, + }, { id: 'd', name: 'ColD', formatHint: { id: 'string' } }, ], rows: [ @@ -141,6 +151,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -166,12 +177,14 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(Settings).prop('xDomain')).toMatchInlineSnapshot(` Object { "max": 1546491600000, "min": 1546405200000, + "minInterval": 10000, } `); }); @@ -195,6 +208,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(Settings).prop('xDomain')).toBeUndefined(); @@ -209,6 +223,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -224,6 +239,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -239,6 +255,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -246,6 +263,69 @@ describe('xy_expression', () => { expect(component.find(Settings).prop('rotation')).toEqual(90); }); + test('onElementClick returns correct context data', () => { + const geometry: GeometryValue = { x: 5, y: 1, accessor: 'y1' }; + const series = { + key: 'spec{d}yAccessor{d}splitAccessors{b-2}', + specId: 'd', + yAccessor: 'd', + splitAccessors: {}, + seriesKeys: [2, 'd'], + }; + + const { args, data } = sampleArgs(); + + const wrapper = mountWithIntl( + + ); + + wrapper + .find(Settings) + .first() + .prop('onElementClick')!([[geometry, series as XYChartSeriesIdentifier]]); + + expect(executeTriggerActions).toHaveBeenCalledWith('VALUE_CLICK_TRIGGER', { + data: { + data: [ + { + column: 1, + row: 1, + table: data.tables.first, + value: 5, + }, + { + column: 1, + row: 0, + table: data.tables.first, + value: 2, + }, + ], + }, + }); + }); + test('it renders stacked bar', () => { const { data, args } = sampleArgs(); const component = shallow( @@ -255,6 +335,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -271,6 +352,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -290,6 +372,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component).toMatchSnapshot(); @@ -307,6 +390,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="CEST" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(LineSeries).prop('timeZone')).toEqual('CEST'); @@ -323,6 +407,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(BarSeries).prop('enableHistogramMode')).toEqual(true); @@ -346,6 +431,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(BarSeries).prop('enableHistogramMode')).toEqual(true); @@ -363,6 +449,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(BarSeries).prop('enableHistogramMode')).toEqual(false); @@ -378,6 +465,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; @@ -414,6 +502,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; @@ -442,6 +531,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(LineSeries).prop('xScaleType')).toEqual(ScaleType.Ordinal); @@ -457,6 +547,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); expect(component.find(LineSeries).prop('yScaleType')).toEqual(ScaleType.Sqrt); @@ -472,6 +563,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); @@ -488,6 +580,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); @@ -504,6 +597,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} chartTheme={{}} timeZone="UTC" + executeTriggerActions={executeTriggerActions} /> ); expect(getFormatSpy).toHaveBeenCalledWith({ @@ -522,6 +616,7 @@ describe('xy_expression', () => { formatFactory={getFormatSpy} timeZone="UTC" chartTheme={{}} + executeTriggerActions={executeTriggerActions} /> ); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx index ce966ee6150a0..a7d4b2a217f37 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -15,6 +15,8 @@ import { BarSeries, Position, PartialTheme, + GeometryValue, + XYChartSeriesIdentifier, } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import { @@ -26,11 +28,15 @@ import { import { EuiIcon, EuiText, IconType, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { FormatFactory } from '../legacy_imports'; -import { LensMultiTable } from '../types'; +import { EmbeddableVisTriggerContext } from '../../../../../../src/plugins/embeddable/public'; +import { VIS_EVENT_TO_TRIGGER } from '../../../../../../src/plugins/visualizations/public'; +import { LensMultiTable, FormatFactory } from '../types'; import { XYArgs, SeriesType, visualizationTypes } from './types'; import { VisualizationContainer } from '../visualization_container'; import { isHorizontalChart } from './state_helpers'; +import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; +import { parseInterval } from '../../../../../../src/plugins/data/common'; +import { getExecuteTriggerActions } from './services'; type InferPropType = T extends React.FunctionComponent ? P : T; type SeriesSpec = InferPropType & @@ -52,6 +58,7 @@ type XYChartRenderProps = XYChartProps & { chartTheme: PartialTheme; formatFactory: FormatFactory; timeZone: string; + executeTriggerActions: UiActionsStart['executeTriggerActions']; }; export const xyChart: ExpressionFunctionDefinition< @@ -101,7 +108,7 @@ export const xyChart: ExpressionFunctionDefinition< }; export const getXyChartRenderer = (dependencies: { - formatFactory: FormatFactory; + formatFactory: Promise; chartTheme: PartialTheme; timeZone: string; }): ExpressionRenderDefinition => ({ @@ -112,11 +119,19 @@ export const getXyChartRenderer = (dependencies: { }), validate: () => undefined, reuseDomNode: true, - render: (domNode: Element, config: XYChartProps, handlers: IInterpreterRenderHandlers) => { + render: async (domNode: Element, config: XYChartProps, handlers: IInterpreterRenderHandlers) => { + const executeTriggerActions = getExecuteTriggerActions(); handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); + const formatFactory = await dependencies.formatFactory; ReactDOM.render( - + , domNode, () => handlers.done() @@ -148,7 +163,14 @@ export function XYChartReportable(props: XYChartRenderProps) { ); } -export function XYChart({ data, args, formatFactory, timeZone, chartTheme }: XYChartRenderProps) { +export function XYChart({ + data, + args, + formatFactory, + timeZone, + chartTheme, + executeTriggerActions, +}: XYChartRenderProps) { const { legend, layers } = args; if (Object.values(data.tables).every(table => table.rows.length === 0)) { @@ -189,7 +211,16 @@ export function XYChart({ data, args, formatFactory, timeZone, chartTheme }: XYC const shouldRotate = isHorizontalChart(layers); const xTitle = (xAxisColumn && xAxisColumn.name) || args.xTitle; + const interval = parseInterval(xAxisColumn?.meta?.aggConfigParams?.interval); + const xDomain = + data.dateRange && layers.every(l => l.xScaleType === 'time') + ? { + min: data.dateRange.fromDate.getTime(), + max: data.dateRange.toDate.getTime(), + minInterval: interval?.asMilliseconds(), + } + : undefined; return ( l.xScaleType === 'time') - ? { - min: data.dateRange.fromDate.getTime(), - max: data.dateRange.toDate.getTime(), - } - : undefined - } + xDomain={xDomain} + onElementClick={([[geometry, series]]) => { + // for xyChart series is always XYChartSeriesIdentifier and geometry is always type of GeometryValue + const xySeries = series as XYChartSeriesIdentifier; + const xyGeometry = geometry as GeometryValue; + + const layer = layers.find(l => + xySeries.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString())) + ); + if (!layer) { + return; + } + + const table = data.tables[layer.layerId]; + + const points = [ + { + row: table.rows.findIndex( + row => layer.xAccessor && row[layer.xAccessor] === xyGeometry.x + ), + column: table.columns.findIndex(col => col.id === layer.xAccessor), + value: xyGeometry.x, + }, + ]; + + if (xySeries.seriesKeys.length > 1) { + const pointValue = xySeries.seriesKeys[0]; + + points.push({ + row: table.rows.findIndex( + row => layer.splitAccessor && row[layer.splitAccessor] === pointValue + ), + column: table.columns.findIndex(col => col.id === layer.splitAccessor), + value: pointValue, + }); + } + + const xAxisFieldName: string | undefined = table.columns.find( + col => col.id === layer.xAccessor + )?.meta?.aggConfigParams?.field; + + const timeFieldName = xDomain && xAxisFieldName; + + const context: EmbeddableVisTriggerContext = { + data: { + data: points.map(point => ({ + row: point.row, + column: point.column, + value: point.value, + table, + })), + }, + timeFieldName, + }; + + executeTriggerActions(VIS_EVENT_TO_TRIGGER.filter, context); + }} /> = columnToLabel ? JSON.parse(columnToLabel) : {}; + const table = data.tables[layerId]; + + // For date histogram chart type, we're getting the rows that represent intervals without data. + // To not display them in the legend, they need to be filtered out. + const rows = table.rows.filter( + row => + !(splitAccessor && !row[splitAccessor] && accessors.every(accessor => !row[accessor])) + ); + const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], stackAccessors: seriesType.includes('stacked') ? [xAccessor] : [], id: splitAccessor || accessors.join(','), xAccessor, yAccessors: accessors, - data: table.rows, + data: rows, xScaleType, yScaleType, enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor), @@ -276,16 +365,17 @@ export function XYChart({ data, args, formatFactory, timeZone, chartTheme }: XYC }, }; - return seriesType === 'line' ? ( - - ) : seriesType === 'bar' || - seriesType === 'bar_stacked' || - seriesType === 'bar_horizontal' || - seriesType === 'bar_horizontal_stacked' ? ( - - ) : ( - - ); + switch (seriesType) { + case 'line': + return ; + case 'bar': + case 'bar_stacked': + case 'bar_horizontal': + case 'bar_horizontal_stacked': + return ; + default: + return ; + } } )} diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.ts new file mode 100644 index 0000000000000..1f0eda26e7f7d --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export * from '../../../../plugins/maps/common/descriptor_types'; diff --git a/x-pack/legacy/plugins/maps/common/migrations/migrate_symbol_style_descriptor.test.js b/x-pack/legacy/plugins/maps/common/migrations/migrate_symbol_style_descriptor.test.js index 2811b83f46d8f..fc0151083855c 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/migrate_symbol_style_descriptor.test.js +++ b/x-pack/legacy/plugins/maps/common/migrations/migrate_symbol_style_descriptor.test.js @@ -120,7 +120,7 @@ describe('migrateSymbolStyleDescriptor', () => { }, icon: { type: STYLE_TYPE.STATIC, - options: { value: 'airfield' }, + options: { value: 'marker' }, }, }, }, diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts b/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts index 3a61d5affd861..c1f5c31eb4210 100644 --- a/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.d.ts @@ -5,8 +5,10 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ +import { Filter, Query } from 'src/plugins/data/public'; +import { AnyAction } from 'redux'; import { LAYER_TYPE } from '../../common/constants'; -import { DataMeta, MapFilters } from '../../common/data_request_descriptor_types'; +import { DataMeta, MapFilters } from '../../common/descriptor_types'; export type SyncContext = { startLoading(dataId: string, requestToken: symbol, meta: DataMeta): void; @@ -24,3 +26,45 @@ export function updateSourceProp( value: unknown, newLayerType?: LAYER_TYPE ): void; + +export interface MapCenter { + lat: number; + lon: number; + zoom: number; +} + +export function setGotoWithCenter(config: MapCenter): AnyAction; + +export function replaceLayerList(layerList: unknown[]): AnyAction; + +export interface QueryGroup { + filters: Filter[]; + query?: Query; + timeFilters: unknown; + refresh: unknown; +} + +export function setQuery(query: QueryGroup): AnyAction; + +export interface RefreshConfig { + isPaused: boolean; + interval: number; +} + +export function setRefreshConfig(config: RefreshConfig): AnyAction; + +export function disableScrollZoom(): AnyAction; + +export function disableInteractive(): AnyAction; + +export function disableTooltipControl(): AnyAction; + +export function hideToolbarOverlay(): AnyAction; + +export function hideLayerControl(): AnyAction; + +export function hideViewControl(): AnyAction; + +export function setHiddenLayers(hiddenLayerIds: string[]): AnyAction; + +export function addLayerWithoutDataSync(layerDescriptor: unknown): AnyAction; diff --git a/x-pack/legacy/plugins/maps/public/actions/ui_actions.d.ts b/x-pack/legacy/plugins/maps/public/actions/ui_actions.d.ts new file mode 100644 index 0000000000000..233918847de08 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/actions/ui_actions.d.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AnyAction } from 'redux'; + +export function setOpenTOCDetails(layerIds?: string[]): AnyAction; + +export function setIsLayerTOCOpen(open: boolean): AnyAction; + +export function setReadOnly(readOnly: boolean): AnyAction; diff --git a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/index.ts b/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.d.ts similarity index 71% rename from x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/index.ts rename to x-pack/legacy/plugins/maps/public/angular/get_initial_layers.d.ts index db5bb3aa62a16..920888404b97d 100644 --- a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/index.ts +++ b/x-pack/legacy/plugins/maps/public/angular/get_initial_layers.d.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './action_factory_definition'; -export * from './action_factory'; +export function getInitialLayers(layerListJSON?: string, initialLayers?: unknown[]): unknown[]; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/gis_map/index.d.ts b/x-pack/legacy/plugins/maps/public/connected_components/gis_map/index.d.ts new file mode 100644 index 0000000000000..00a9400109dc1 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/connected_components/gis_map/index.d.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { Filter } from 'src/plugins/data/public'; +import { RenderToolTipContent } from '../../layers/tooltips/tooltip_property'; + +export const GisMap: React.ComponentType<{ + addFilters: ((filters: Filter[]) => void) | null; + renderTooltipContent?: RenderToolTipContent; +}>; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap index a52c118bca8cd..3b3d82c92fbb7 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap @@ -2,7 +2,7 @@ exports[`FeatureProperties should not show filter button 1`] = ` (this._node = node)}> +
(this._node = node)} + > {rows}
); diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/utils.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/utils.js index 413d66fce7f70..a2850d2bb6c23 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/utils.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/utils.js @@ -110,7 +110,9 @@ function getImageData(img) { export async function loadSpriteSheetImageData(imgUrl) { return new Promise((resolve, reject) => { const image = new Image(); - image.crossOrigin = 'Anonymous'; + if (isCrossOriginUrl(imgUrl)) { + image.crossOrigin = 'Anonymous'; + } image.onload = el => { const imgData = getImageData(el.currentTarget); resolve(imgData); @@ -142,3 +144,13 @@ export async function addSpritesheetToMap(json, imgUrl, mbMap) { const imgData = await loadSpriteSheetImageData(imgUrl); addSpriteSheetToMapFromImageData(json, imgData, mbMap); } + +function isCrossOriginUrl(url) { + const a = window.document.createElement('a'); + a.href = url; + return ( + a.protocol !== window.document.location.protocol || + a.host !== window.document.location.host || + a.port !== window.document.location.port + ); +} diff --git a/x-pack/legacy/plugins/maps/public/embeddable/index.ts b/x-pack/legacy/plugins/maps/public/embeddable/index.ts new file mode 100644 index 0000000000000..a410a6699a01f --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/embeddable/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './map_embeddable'; +export * from './map_embeddable_factory'; diff --git a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.tsx similarity index 70% rename from x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js rename to x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.tsx index 9af1a135794c0..69f55815d16a0 100644 --- a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.js +++ b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable.tsx @@ -10,16 +10,29 @@ import { Provider } from 'react-redux'; import { render, unmountComponentAtNode } from 'react-dom'; import 'mapbox-gl/dist/mapbox-gl.css'; -import { Embeddable } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; -import { APPLY_FILTER_TRIGGER } from '../../../../../../src/plugins/ui_actions/public'; -import { esFilters } from '../../../../../../src/plugins/data/public'; - import { I18nContext } from 'ui/i18n'; +import { npStart } from 'ui/new_platform'; +import { Subscription } from 'rxjs'; +import { Unsubscribe } from 'redux'; +import { + Embeddable, + IContainer, + EmbeddableInput, + EmbeddableOutput, +} from '../../../../../../src/plugins/embeddable/public'; +import { APPLY_FILTER_TRIGGER } from '../../../../../../src/plugins/ui_actions/public'; +import { + esFilters, + IIndexPattern, + TimeRange, + Filter, + Query, + RefreshInterval, +} from '../../../../../../src/plugins/data/public'; import { GisMap } from '../connected_components/gis_map'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { createMapStore } from '../../../../../plugins/maps/public/reducers/store'; -import { npStart } from 'ui/new_platform'; +import { createMapStore, MapStore } from '../../../../../plugins/maps/public/reducers/store'; import { setGotoWithCenter, replaceLayerList, @@ -32,21 +45,72 @@ import { hideLayerControl, hideViewControl, setHiddenLayers, + MapCenter, } from '../actions/map_actions'; import { setReadOnly, setIsLayerTOCOpen, setOpenTOCDetails } from '../actions/ui_actions'; import { getIsLayerTOCOpen, getOpenTOCDetails } from '../selectors/ui_selectors'; import { getInspectorAdapters, setEventHandlers, + EventHandlers, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../plugins/maps/public/reducers/non_serializable_instances'; import { getMapCenter, getMapZoom, getHiddenLayerIds } from '../selectors/map_selectors'; import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { RenderToolTipContent } from '../layers/tooltips/tooltip_property'; + +interface MapEmbeddableConfig { + editUrl?: string; + indexPatterns: IIndexPattern[]; + editable: boolean; + title?: string; + layerList: unknown[]; +} + +export interface MapEmbeddableInput extends EmbeddableInput { + timeRange?: TimeRange; + filters: Filter[]; + query?: Query; + refresh?: unknown; + refreshConfig: RefreshInterval; + isLayerTOCOpen: boolean; + openTOCDetails?: string[]; + disableTooltipControl?: boolean; + disableInteractive?: boolean; + hideToolbarOverlay?: boolean; + hideLayerControl?: boolean; + hideViewControl?: boolean; + mapCenter?: MapCenter; + hiddenLayers?: string[]; + hideFilterActions?: boolean; +} -export class MapEmbeddable extends Embeddable { +export interface MapEmbeddableOutput extends EmbeddableOutput { + indexPatterns: IIndexPattern[]; +} + +export class MapEmbeddable extends Embeddable { type = MAP_SAVED_OBJECT_TYPE; - constructor(config, initialInput, parent, renderTooltipContent, eventHandlers) { + private _renderTooltipContent?: RenderToolTipContent; + private _eventHandlers?: EventHandlers; + private _layerList: unknown[]; + private _store: MapStore; + private _subscription: Subscription; + private _prevTimeRange?: TimeRange; + private _prevQuery?: Query; + private _prevRefreshConfig?: RefreshInterval; + private _prevFilters?: Filter[]; + private _domNode?: HTMLElement; + private _unsubscribeFromStore?: Unsubscribe; + + constructor( + config: MapEmbeddableConfig, + initialInput: MapEmbeddableInput, + parent?: IContainer, + renderTooltipContent?: RenderToolTipContent, + eventHandlers?: EventHandlers + ) { super( initialInput, { @@ -70,7 +134,7 @@ export class MapEmbeddable extends Embeddable { return getInspectorAdapters(this._store.getState()); } - onContainerStateChanged(containerState) { + onContainerStateChanged(containerState: MapEmbeddableInput) { if ( !_.isEqual(containerState.timeRange, this._prevTimeRange) || !_.isEqual(containerState.query, this._prevQuery) || @@ -84,7 +148,12 @@ export class MapEmbeddable extends Embeddable { } } - _dispatchSetQuery({ query, timeRange, filters, refresh }) { + _dispatchSetQuery({ + query, + timeRange, + filters, + refresh, + }: Pick) { this._prevTimeRange = timeRange; this._prevQuery = query; this._prevFilters = filters; @@ -98,7 +167,7 @@ export class MapEmbeddable extends Embeddable { ); } - _dispatchSetRefreshConfig({ refreshConfig }) { + _dispatchSetRefreshConfig({ refreshConfig }: Pick) { this._prevRefreshConfig = refreshConfig; this._store.dispatch( setRefreshConfig({ @@ -113,7 +182,7 @@ export class MapEmbeddable extends Embeddable { * @param {HTMLElement} domNode * @param {ContainerState} containerState */ - render(domNode) { + render(domNode: HTMLElement) { this._store.dispatch(setEventHandlers(this._eventHandlers)); this._store.dispatch(setReadOnly(true)); this._store.dispatch(disableScrollZoom()); @@ -127,23 +196,22 @@ export class MapEmbeddable extends Embeddable { } if (_.has(this.input, 'disableInteractive') && this.input.disableInteractive) { - this._store.dispatch(disableInteractive(this.input.disableInteractive)); + this._store.dispatch(disableInteractive()); } if (_.has(this.input, 'disableTooltipControl') && this.input.disableTooltipControl) { - this._store.dispatch(disableTooltipControl(this.input.disableTooltipControl)); + this._store.dispatch(disableTooltipControl()); } - if (_.has(this.input, 'hideToolbarOverlay') && this.input.hideToolbarOverlay) { - this._store.dispatch(hideToolbarOverlay(this.input.hideToolbarOverlay)); + this._store.dispatch(hideToolbarOverlay()); } if (_.has(this.input, 'hideLayerControl') && this.input.hideLayerControl) { - this._store.dispatch(hideLayerControl(this.input.hideLayerControl)); + this._store.dispatch(hideLayerControl()); } if (_.has(this.input, 'hideViewControl') && this.input.hideViewControl) { - this._store.dispatch(hideViewControl(this.input.hideViewControl)); + this._store.dispatch(hideViewControl()); } if (this.input.mapCenter) { @@ -182,12 +250,12 @@ export class MapEmbeddable extends Embeddable { }); } - async setLayerList(layerList) { + async setLayerList(layerList: unknown[]) { this._layerList = layerList; return await this._store.dispatch(replaceLayerList(this._layerList)); } - addFilters = filters => { + addFilters = (filters: Filter[]) => { npStart.plugins.uiActions.executeTriggerActions(APPLY_FILTER_TRIGGER, { embeddable: this, filters, @@ -213,7 +281,7 @@ export class MapEmbeddable extends Embeddable { this._dispatchSetQuery({ query: this._prevQuery, timeRange: this._prevTimeRange, - filters: this._prevFilters, + filters: this._prevFilters ?? [], refresh: true, }); } @@ -222,7 +290,7 @@ export class MapEmbeddable extends Embeddable { const center = getMapCenter(this._store.getState()); const zoom = getMapZoom(this._store.getState()); - const mapCenter = this.input.mapCenter || {}; + const mapCenter = this.input.mapCenter || undefined; if ( !mapCenter || mapCenter.lat !== center.lat || @@ -233,7 +301,7 @@ export class MapEmbeddable extends Embeddable { mapCenter: { lat: center.lat, lon: center.lon, - zoom: zoom, + zoom, }, }); } diff --git a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.ts similarity index 78% rename from x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js rename to x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.ts index fcbae894dffa4..ddb937dd98926 100644 --- a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js +++ b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.ts @@ -8,12 +8,16 @@ import _ from 'lodash'; import chrome from 'ui/chrome'; import { capabilities } from 'ui/capabilities'; import { i18n } from '@kbn/i18n'; +import { npSetup, npStart } from 'ui/new_platform'; +import { SavedObjectLoader } from 'src/plugins/saved_objects/public'; +import { IIndexPattern } from 'src/plugins/data/public'; import { EmbeddableFactory, ErrorEmbeddable, + IContainer, } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; import { setup } from '../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; -import { MapEmbeddable } from './map_embeddable'; +import { MapEmbeddable, MapEmbeddableInput } from './map_embeddable'; import { getIndexPatternService } from '../kibana_services'; import { createMapPath, MAP_SAVED_OBJECT_TYPE, APP_ICON } from '../../common/constants'; @@ -25,7 +29,11 @@ import { getInitialLayers } from '../angular/get_initial_layers'; import { mergeInputWithSavedMap } from './merge_input_with_saved_map'; import '../angular/services/gis_map_saved_object_loader'; import { bindSetupCoreAndPlugins, bindStartCoreAndPlugins } from '../plugin'; -import { npSetup, npStart } from 'ui/new_platform'; +import { RenderToolTipContent } from '../layers/tooltips/tooltip_property'; +import { + EventHandlers, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../plugins/maps/public/reducers/non_serializable_instances'; export class MapEmbeddableFactory extends EmbeddableFactory { type = MAP_SAVED_OBJECT_TYPE; @@ -44,8 +52,9 @@ export class MapEmbeddableFactory extends EmbeddableFactory { bindSetupCoreAndPlugins(npSetup.core, npSetup.plugins); bindStartCoreAndPlugins(npStart.core, npStart.plugins); } - isEditable() { - return capabilities.get().maps.save; + + async isEditable() { + return capabilities.get().maps.save as boolean; } // Not supported yet for maps types. @@ -59,12 +68,12 @@ export class MapEmbeddableFactory extends EmbeddableFactory { }); } - async _getIndexPatterns(layerList) { + async _getIndexPatterns(layerList: unknown[]): Promise { // Need to extract layerList from store to get queryable index pattern ids const store = createMapStore(); let queryableIndexPatternIds; try { - layerList.forEach(layerDescriptor => { + layerList.forEach((layerDescriptor: unknown) => { store.dispatch(addLayerWithoutDataSync(layerDescriptor)); }); queryableIndexPatternIds = getQueryableUniqueIndexPatternIds(store.getState()); @@ -86,16 +95,20 @@ export class MapEmbeddableFactory extends EmbeddableFactory { } }); const indexPatterns = await Promise.all(promises); - return _.compact(indexPatterns); + return _.compact(indexPatterns) as IIndexPattern[]; } - async _fetchSavedMap(savedObjectId) { + async _fetchSavedMap(savedObjectId: string) { const $injector = await chrome.dangerouslyGetActiveInjector(); - const savedObjectLoader = $injector.get('gisMapSavedObjectLoader'); + const savedObjectLoader = $injector.get('gisMapSavedObjectLoader'); return await savedObjectLoader.get(savedObjectId); } - async createFromSavedObject(savedObjectId, input, parent) { + async createFromSavedObject( + savedObjectId: string, + input: MapEmbeddableInput, + parent?: IContainer + ) { const savedMap = await this._fetchSavedMap(savedObjectId); const layerList = getInitialLayers(savedMap.layerListJSON); const indexPatterns = await this._getIndexPatterns(layerList); @@ -106,7 +119,7 @@ export class MapEmbeddableFactory extends EmbeddableFactory { title: savedMap.title, editUrl: chrome.addBasePath(createMapPath(savedObjectId)), indexPatterns, - editable: this.isEditable(), + editable: await this.isEditable(), }, input, parent @@ -125,7 +138,13 @@ export class MapEmbeddableFactory extends EmbeddableFactory { return embeddable; } - async createFromState(state, input, parent, renderTooltipContent, eventHandlers) { + async createFromState( + state: { title?: string; layerList?: unknown[] }, + input: MapEmbeddableInput, + parent: IContainer, + renderTooltipContent: RenderToolTipContent, + eventHandlers: EventHandlers + ) { const layerList = state && state.layerList ? state.layerList : getInitialLayers(); const indexPatterns = await this._getIndexPatterns(layerList); @@ -133,7 +152,6 @@ export class MapEmbeddableFactory extends EmbeddableFactory { { layerList, title: state && state.title ? state.title : '', - editUrl: null, indexPatterns, editable: false, }, @@ -144,7 +162,7 @@ export class MapEmbeddableFactory extends EmbeddableFactory { ); } - async create(input) { + async create(input: MapEmbeddableInput) { window.location.href = chrome.addBasePath(createMapPath('')); return new ErrorEmbeddable( 'Maps can only be created with createFromSavedObject or createFromState', diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/i18n.ts b/x-pack/legacy/plugins/maps/public/embeddable/merge_input_with_saved_map.d.ts similarity index 58% rename from x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/i18n.ts rename to x-pack/legacy/plugins/maps/public/embeddable/merge_input_with_saved_map.d.ts index 98b746bafd24a..4ce4df02f6a39 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/i18n.ts +++ b/x-pack/legacy/plugins/maps/public/embeddable/merge_input_with_saved_map.d.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; +import { MapEmbeddableInput } from './map_embeddable'; -export const txtGoToDashboard = i18n.translate('xpack.dashboard.drilldown.goToDashboard', { - defaultMessage: 'Go to Dashboard', -}); +export function mergeInputWithSavedMap( + input: MapEmbeddableInput, + savedmap: unknown +): Partial; diff --git a/x-pack/legacy/plugins/maps/public/index.ts b/x-pack/legacy/plugins/maps/public/index.ts index 27cd64103eec9..2d13f005f1a70 100644 --- a/x-pack/legacy/plugins/maps/public/index.ts +++ b/x-pack/legacy/plugins/maps/public/index.ts @@ -25,3 +25,6 @@ import { MapsPlugin } from './plugin'; export const plugin = (initializerContext: PluginInitializerContext) => { return new MapsPlugin(); }; + +export { RenderTooltipContentParams, ITooltipProperty } from './layers/tooltips/tooltip_property'; +export { MapEmbeddable, MapEmbeddableInput } from './embeddable'; diff --git a/x-pack/legacy/plugins/maps/public/kibana_services.d.ts b/x-pack/legacy/plugins/maps/public/kibana_services.d.ts new file mode 100644 index 0000000000000..89b1fee1aa842 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/kibana_services.d.ts @@ -0,0 +1,23 @@ +/* + * 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 { IIndexPattern } from 'src/plugins/data/public'; + +export function getIndexPatternService(): { + get: (id: string) => IIndexPattern | undefined; +}; + +export function setLicenseId(args: unknown): void; +export function setInspector(args: unknown): void; +export function setFileUpload(args: unknown): void; +export function setIndexPatternSelect(args: unknown): void; +export function setHttp(args: unknown): void; +export function setTimeFilter(args: unknown): void; +export function setUiSettings(args: unknown): void; +export function setInjectedVarFunc(args: unknown): void; +export function setToasts(args: unknown): void; +export function setIndexPatternService(args: unknown): void; +export function setAutocompleteService(args: unknown): void; diff --git a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts index 8c54720987e41..f5526ad703dd2 100644 --- a/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/legacy/plugins/maps/public/layers/blended_vector_layer.ts @@ -34,7 +34,7 @@ import { VectorStyleDescriptor, SizeDynamicOptions, DynamicStylePropertyOptions, -} from '../../common/style_property_descriptor_types'; +} from '../../common/descriptor_types'; const ACTIVE_COUNT_DATA_ID = 'ACTIVE_COUNT_DATA_ID'; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts index b565cb9108aea..ffd1d343b59e0 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.d.ts @@ -7,7 +7,7 @@ import { AbstractVectorSource } from './vector_source'; import { IVectorSource } from './vector_source'; import { IndexPattern, SearchSource } from '../../../../../../../src/plugins/data/public'; -import { VectorSourceRequestMeta } from '../../../common/data_request_descriptor_types'; +import { VectorSourceRequestMeta } from '../../../common/descriptor_types'; export interface IESSource extends IVectorSource { getId(): string; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts index fd585e100924e..7a747da244233 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts @@ -8,7 +8,7 @@ import { FeatureCollection } from 'geojson'; import { AbstractSource, ISource } from './source'; import { IField } from '../fields/field'; -import { ESSearchSourceResponseMeta } from '../../../common/data_request_descriptor_types'; +import { ESSearchSourceResponseMeta } from '../../../common/descriptor_types'; export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss index 519e97f4b30cd..09a9ad59bce3c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/_color_stops.scss @@ -4,15 +4,5 @@ & + & { margin-top: $euiSizeS; } - - &:hover, - &:focus { - .mapColorStop__icons { - visibility: visible; - opacity: 1; - display: block; - animation: mapColorStopBecomeVisible $euiAnimSpeedFast $euiAnimSlightResistance; - } - } } 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 0d4cf322d2a40..bf57306df5697 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 @@ -123,6 +123,7 @@ export class ColorMapSelect extends Component { { value: CUSTOM_COLOR_MAP, inputDisplay: this.props.customOptionLabel, + 'data-test-subj': `colorMapSelectOption_${CUSTOM_COLOR_MAP}`, }, ...this.props.colorMapOptions, ]; @@ -150,6 +151,7 @@ export class ColorMapSelect extends Component { onChange={this._onColorMapSelect} valueOfSelected={valueOfSelected} hasDividers={true} + data-test-subj={`colorMapSelect_${this.props.styleProperty.getStyleName()}`} /> diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js index 3e9b9e2aafc47..059543d705fc7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_stops.js @@ -12,7 +12,7 @@ import { EuiButtonIcon, EuiColorPicker, EuiFlexGroup, EuiFlexItem, EuiFormRow } function getColorStopRow({ index, errors, stopInput, onColorChange, color, deleteButton, onAdd }) { const colorPickerButtons = ( -
+
{deleteButton} ); }; 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 c6b68b7e94409..a1c15e27c9eb3 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 @@ -123,6 +123,7 @@ export function DynamicColorForm({ { onChange({ field: selectedFields.length > 0 ? selectedFields[0].value : null, @@ -98,6 +98,7 @@ export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) { defaultMessage: 'Select a field', })} renderOption={renderOption} + data-test-subj={`styleFieldSelect_${styleName}`} {...rest} /> ); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js index 0c9011b811f38..bbba6705f7de7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/dynamic_label_form.js @@ -27,6 +27,7 @@ export function DynamicLabelForm({ ); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_prop_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_prop_editor.js index 752e0e4213217..005bc11aa1bd8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_prop_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_prop_editor.js @@ -77,6 +77,7 @@ export class StylePropEditor extends Component { defaultMessage: 'Select to style by fixed value or by data value', })} compressed + data-test-subj={`staticDynamicSelect_${this.props.styleProperty.getStyleName()}`} /> ); } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js index 9065102dc8bd7..6b79ac17f2e22 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/dynamic_icon_form.js @@ -59,6 +59,7 @@ export function DynamicIconForm({ { @@ -19,9 +20,31 @@ function isDuplicateStop(targetStop, iconStops) { return stops.length > 1; } +export function getFirstUnusedSymbol(symbolOptions, iconStops) { + const firstUnusedPreferredIconId = PREFERRED_ICONS.find(iconId => { + const isSymbolBeingUsed = iconStops.some(({ icon }) => { + return icon === iconId; + }); + return !isSymbolBeingUsed; + }); + + if (firstUnusedPreferredIconId) { + return firstUnusedPreferredIconId; + } + + const firstUnusedSymbol = symbolOptions.find(({ value }) => { + const isSymbolBeingUsed = iconStops.some(({ icon }) => { + return icon === value; + }); + return !isSymbolBeingUsed; + }); + + return firstUnusedSymbol ? firstUnusedSymbol.value : DEFAULT_ICON; +} + const DEFAULT_ICON_STOPS = [ - { stop: null, icon: DEFAULT_ICON }, //first stop is the "other" color - { stop: '', icon: DEFAULT_ICON }, + { stop: null, icon: PREFERRED_ICONS[0] }, //first stop is the "other" color + { stop: '', icon: PREFERRED_ICONS[1] }, ]; export function IconStops({ @@ -58,7 +81,7 @@ export function IconStops({ ...iconStops.slice(0, index + 1), { stop: '', - icon: DEFAULT_ICON, + icon: getFirstUnusedSymbol(symbolOptions, iconStops), }, ...iconStops.slice(index + 1), ], @@ -66,12 +89,12 @@ export function IconStops({ }; const onRemove = () => { onChange({ - iconStops: [...iconStops.slice(0, index), ...iconStops.slice(index + 1)], + customMapStops: [...iconStops.slice(0, index), ...iconStops.slice(index + 1)], }); }; let deleteButton; - if (index > 0) { + if (iconStops.length > 2 && index !== 0) { deleteButton = ( + {deleteButton} + +
+ ); + const errors = []; // TODO check for duplicate values and add error messages here @@ -116,29 +152,20 @@ export function IconStops({ error={errors} display="rowCompressed" > -
- - {stopInput} - - - - -
- {deleteButton} - + + {stopInput} + + + -
-
+ + ); }); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/icon_stops.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/icon_stops.test.js new file mode 100644 index 0000000000000..ffe9b6feef462 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/symbol/icon_stops.test.js @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getFirstUnusedSymbol } from './icon_stops'; + +describe('getFirstUnusedSymbol', () => { + const symbolOptions = [{ value: 'icon1' }, { value: 'icon2' }]; + + test('Should return first unused icon from PREFERRED_ICONS', () => { + const iconStops = [ + { stop: 'category1', icon: 'circle' }, + { stop: 'category2', icon: 'marker' }, + ]; + const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops); + expect(nextIcon).toBe('square'); + }); + + test('Should fallback to first unused general icons when all PREFERRED_ICONS are used', () => { + const iconStops = [ + { stop: 'category1', icon: 'circle' }, + { stop: 'category2', icon: 'marker' }, + { stop: 'category3', icon: 'square' }, + { stop: 'category4', icon: 'star' }, + { stop: 'category5', icon: 'triangle' }, + { stop: 'category6', icon: 'hospital' }, + { stop: 'category7', icon: 'circle-stroked' }, + { stop: 'category8', icon: 'marker-stroked' }, + { stop: 'category9', icon: 'square-stroked' }, + { stop: 'category10', icon: 'star-stroked' }, + { stop: 'category11', icon: 'triangle-stroked' }, + { stop: 'category12', icon: 'icon1' }, + ]; + const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops); + expect(nextIcon).toBe('icon2'); + }); + + test('Should fallback to default icon when all icons are used', () => { + const iconStops = [ + { stop: 'category1', icon: 'circle' }, + { stop: 'category2', icon: 'marker' }, + { stop: 'category3', icon: 'square' }, + { stop: 'category4', icon: 'star' }, + { stop: 'category5', icon: 'triangle' }, + { stop: 'category6', icon: 'hospital' }, + { stop: 'category7', icon: 'circle-stroked' }, + { stop: 'category8', icon: 'marker-stroked' }, + { stop: 'category9', icon: 'square-stroked' }, + { stop: 'category10', icon: 'star-stroked' }, + { stop: 'category11', icon: 'triangle-stroked' }, + { stop: 'category12', icon: 'icon1' }, + { stop: 'category13', icon: 'icon2' }, + ]; + const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops); + expect(nextIcon).toBe('marker'); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts index a83dd55c0c175..88eb489c4996e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts @@ -8,11 +8,12 @@ import { IStyleProperty } from './style_property'; import { FIELD_ORIGIN } from '../../../../../common/constants'; import { - FieldMetaOptions, + CategoryFieldMeta, DynamicStylePropertyOptions, -} from '../../../../../common/style_property_descriptor_types'; + FieldMetaOptions, + RangeFieldMeta, +} from '../../../../../common/descriptor_types'; import { IField } from '../../../fields/field'; -import { CategoryFieldMeta, RangeFieldMeta } from '../../../../../common/descriptor_types'; export interface IDynamicStyleProperty extends IStyleProperty { getOptions(): DynamicStylePropertyOptions; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts index fef7778c5f08e..af04a95e3c3bd 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts @@ -8,10 +8,7 @@ import { ReactElement } from 'react'; // @ts-ignore import { getVectorStyleLabel } from '../components/get_vector_style_label'; -import { - FieldMetaOptions, - StylePropertyOptions, -} from '../../../../../common/style_property_descriptor_types'; +import { FieldMetaOptions, StylePropertyOptions } from '../../../../../common/descriptor_types'; import { VECTOR_STYLES } from '../../../../../common/constants'; type LegendProps = { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js index affb9c1805170..c1c4375faaeb1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js @@ -101,6 +101,16 @@ const ICON_PALETTES = [ }, ]; +// PREFERRED_ICONS is used to provide less random default icon values for forms that need default icon values +export const PREFERRED_ICONS = []; +ICON_PALETTES.forEach(iconPalette => { + iconPalette.icons.forEach(iconId => { + if (!PREFERRED_ICONS.includes(iconId)) { + PREFERRED_ICONS.push(iconId); + } + }); +}); + export function getIconPaletteOptions(isDarkMode) { return ICON_PALETTES.map(({ id, icons }) => { const iconsDisplay = icons.map(iconId => { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts index 37aea501f5193..77ea44ac26bf9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.d.ts @@ -7,7 +7,7 @@ import { IStyleProperty } from './properties/style_property'; import { IDynamicStyleProperty } from './properties/dynamic_style_property'; import { IVectorLayer } from '../../vector_layer'; import { IVectorSource } from '../../sources/vector_source'; -import { VectorStyleDescriptor } from '../../../../common/style_property_descriptor_types'; +import { VectorStyleDescriptor } from '../../../../common/descriptor_types'; export interface IVectorStyle { getAllStyleProperties(): IStyleProperty[]; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js index d669fd280e32c..426f1d6afa952 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js @@ -96,7 +96,7 @@ describe('getDescriptorWithMissingStylePropsRemoved', () => { }, icon: { options: { - value: 'airfield', + value: 'marker', }, type: 'STATIC', }, diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.ts index f104afd2a7857..86602381cf615 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.ts +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.ts @@ -18,7 +18,7 @@ import { DEFAULT_LINE_COLORS, // @ts-ignore } from '../color_utils'; -import { VectorStylePropertiesDescriptor } from '../../../../common/style_property_descriptor_types'; +import { VectorStylePropertiesDescriptor } from '../../../../common/descriptor_types'; // @ts-ignore import { getUiSettings } from '../../../kibana_services'; diff --git a/x-pack/legacy/plugins/maps/public/layers/tooltips/tooltip_property.ts b/x-pack/legacy/plugins/maps/public/layers/tooltips/tooltip_property.ts index 3428cb9589267..c77af11d0ae24 100644 --- a/x-pack/legacy/plugins/maps/public/layers/tooltips/tooltip_property.ts +++ b/x-pack/legacy/plugins/maps/public/layers/tooltips/tooltip_property.ts @@ -16,10 +16,37 @@ export interface ITooltipProperty { getESFilters(): Promise; } +export interface MapFeature { + id: number; + layerId: string; +} + +export interface LoadFeatureProps { + layerId: string; + featureId: number; +} + +export interface FeatureGeometry { + coordinates: [number]; + type: string; +} + +export interface RenderTooltipContentParams { + addFilters(filter: object): void; + closeTooltip(): void; + features: MapFeature[]; + isLocked: boolean; + getLayerName(layerId: string): Promise; + loadFeatureProperties({ layerId, featureId }: LoadFeatureProps): Promise; + loadFeatureGeometry({ layerId, featureId }: LoadFeatureProps): FeatureGeometry; +} + +export type RenderToolTipContent = (params: RenderTooltipContentParams) => JSX.Element; + export class TooltipProperty implements ITooltipProperty { private readonly _propertyKey: string; - private readonly _propertyName: string; private readonly _rawValue: string | undefined; + private readonly _propertyName: string; constructor(propertyKey: string, propertyName: string, rawValue: string | undefined) { this._propertyKey = propertyKey; diff --git a/x-pack/legacy/plugins/maps/public/layers/util/can_skip_fetch.ts b/x-pack/legacy/plugins/maps/public/layers/util/can_skip_fetch.ts index 7b75bb0f21b79..758cc35f41fbb 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/can_skip_fetch.ts +++ b/x-pack/legacy/plugins/maps/public/layers/util/can_skip_fetch.ts @@ -9,7 +9,7 @@ import turf from 'turf'; import turfBooleanContains from '@turf/boolean-contains'; import { isRefreshOnlyQuery } from './is_refresh_only_query'; import { ISource } from '../sources/source'; -import { DataMeta } from '../../../common/data_request_descriptor_types'; +import { DataMeta } from '../../../common/descriptor_types'; import { DataRequest } from './data_request'; const SOURCE_UPDATE_REQUIRED = true; diff --git a/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts index e361574194628..eeef5c49c6ef8 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts +++ b/x-pack/legacy/plugins/maps/public/layers/util/data_request.ts @@ -6,7 +6,7 @@ /* eslint-disable max-classes-per-file */ import _ from 'lodash'; -import { DataRequestDescriptor, DataMeta } from '../../../common/data_request_descriptor_types'; +import { DataRequestDescriptor, DataMeta } from '../../../common/descriptor_types'; export class DataRequest { private readonly _descriptor: DataRequestDescriptor; diff --git a/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.ts b/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.ts index 48b1340207fd4..a56da4b23aa1e 100644 --- a/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.ts +++ b/x-pack/legacy/plugins/maps/public/layers/util/is_refresh_only_query.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Query } from '../../../common/map_descriptor'; +import { Query } from '../../../common/descriptor_types'; // Refresh only query is query where timestamps are different but query is the same. // Triggered by clicking "Refresh" button in QueryBar diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index 390374f761fc7..70fd9927b7732 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -7,8 +7,11 @@ import { AbstractLayer } from './layer'; import { IVectorSource } from './sources/vector_source'; -import { VectorLayerDescriptor } from '../../common/descriptor_types'; -import { MapFilters, VectorSourceRequestMeta } from '../../common/data_request_descriptor_types'; +import { + MapFilters, + VectorLayerDescriptor, + VectorSourceRequestMeta, +} from '../../common/descriptor_types'; import { ILayer } from './layer'; import { IJoin } from './joins/join'; import { IVectorStyle } from './styles/vector/vector_style'; diff --git a/x-pack/legacy/plugins/maps/public/plugin.ts b/x-pack/legacy/plugins/maps/public/plugin.ts index 1f8f83e44a769..53c951ac787e1 100644 --- a/x-pack/legacy/plugins/maps/public/plugin.ts +++ b/x-pack/legacy/plugins/maps/public/plugin.ts @@ -24,7 +24,6 @@ import { setToasts, setIndexPatternService, setAutocompleteService, - // @ts-ignore } from './kibana_services'; // @ts-ignore import { setInjectedVarFunc as npSetInjectedVarFunc } from '../../../../plugins/maps/public/kibana_services'; // eslint-disable-line @kbn/eslint/no-restricted-paths @@ -80,7 +79,7 @@ export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { setIndexPatternSelect(data.ui.IndexPatternSelect); setTimeFilter(data.query.timefilter.timefilter); setIndexPatternService(data.indexPatterns); - setAutocompleteService(data.autocompleteService); + setAutocompleteService(data.autocomplete); }; /** @internal */ diff --git a/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js b/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js index 4d87b6a055802..64a42173098ee 100644 --- a/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js +++ b/x-pack/legacy/plugins/maps/public/register_vis_type_alias.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { setup as visualizationsSetup } from '../../../../../src/legacy/core_plugins/visualizations/public/np_ready/public/legacy'; +import { npSetup } from '../../../../../src/legacy/ui/public/new_platform'; import { i18n } from '@kbn/i18n'; import { APP_ID, APP_ICON, MAP_BASE_URL } from '../common/constants'; @@ -23,7 +23,7 @@ The Maps app offers more functionality and is easier to use.`, } ); -visualizationsSetup.registerAlias({ +npSetup.plugins.visualizations.registerAlias({ aliasUrl: MAP_BASE_URL, name: APP_ID, title: i18n.translate('xpack.maps.visTypeAlias.title', { @@ -37,5 +37,5 @@ visualizationsSetup.registerAlias({ }); if (!showMapVisualizationTypes) { - visualizationsSetup.hideTypes(['region_map', 'tile_map']); + npSetup.plugins.visualizations.hideTypes(['region_map', 'tile_map']); } diff --git a/x-pack/legacy/plugins/maps/public/selectors/map_selectors.d.ts b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.d.ts new file mode 100644 index 0000000000000..237a04027e21b --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/selectors/map_selectors.d.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AnyAction } from 'redux'; +import { MapCenter } from '../actions/map_actions'; + +export function getHiddenLayerIds(state: unknown): string[]; + +export function getMapZoom(state: unknown): number; + +export function getMapCenter(state: unknown): MapCenter; + +export function getQueryableUniqueIndexPatternIds(state: unknown): string[]; diff --git a/x-pack/legacy/plugins/maps/public/selectors/ui_selectors.d.ts b/x-pack/legacy/plugins/maps/public/selectors/ui_selectors.d.ts new file mode 100644 index 0000000000000..812e2082241bd --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/selectors/ui_selectors.d.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export function getOpenTOCDetails(state: unknown): string[]; + +export function getIsLayerTOCOpen(state: unknown): boolean; diff --git a/x-pack/legacy/plugins/siem/common/constants.ts b/x-pack/legacy/plugins/siem/common/constants.ts index ec720164e9bd7..662fb8fb8ef68 100644 --- a/x-pack/legacy/plugins/siem/common/constants.ts +++ b/x-pack/legacy/plugins/siem/common/constants.ts @@ -65,6 +65,8 @@ export const INTERNAL_IDENTIFIER = '__internal'; export const INTERNAL_RULE_ID_KEY = `${INTERNAL_IDENTIFIER}_rule_id`; export const INTERNAL_RULE_ALERT_ID_KEY = `${INTERNAL_IDENTIFIER}_rule_alert_id`; export const INTERNAL_IMMUTABLE_KEY = `${INTERNAL_IDENTIFIER}_immutable`; +export const INTERNAL_NOTIFICATION_ID_KEY = `${INTERNAL_IDENTIFIER}_notification_id`; +export const INTERNAL_NOTIFICATION_RULE_ID_KEY = `${INTERNAL_IDENTIFIER}_notification_rule_id`; /** * Detection engine routes @@ -80,6 +82,7 @@ export const DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL = `${DETECTION_ENGINE export const TIMELINE_URL = '/api/timeline'; export const TIMELINE_EXPORT_URL = `${TIMELINE_URL}/_export`; +export const TIMELINE_IMPORT_URL = `${TIMELINE_URL}/_import`; /** * Default signals index key for kibana.dev.yml @@ -94,4 +97,19 @@ export const DETECTION_ENGINE_QUERY_SIGNALS_URL = `${DETECTION_ENGINE_SIGNALS_UR */ export const UNAUTHENTICATED_USER = 'Unauthenticated'; +/* + Licensing requirements + */ +export const MINIMUM_ML_LICENSE = 'platinum'; + +/* + Rule notifications options +*/ +export const NOTIFICATION_SUPPORTED_ACTION_TYPES_IDS = [ + '.email', + '.slack', + '.pagerduty', + '.webhook', +]; +export const NOTIFICATION_THROTTLE_NO_ACTIONS = 'no_actions'; export const NOTIFICATION_THROTTLE_RULE = 'rule'; diff --git a/x-pack/legacy/plugins/siem/cypress.json b/x-pack/legacy/plugins/siem/cypress.json index d2397e1ec90dd..cc41b72714ed9 100644 --- a/x-pack/legacy/plugins/siem/cypress.json +++ b/x-pack/legacy/plugins/siem/cypress.json @@ -1,6 +1,6 @@ { "baseUrl": "http://localhost:5601", - "defaultCommandTimeout": 30000, + "defaultCommandTimeout": 60000, "screenshotsFolder": "../../../../target/kibana-siem/cypress/screenshots", "trashAssetsBeforeRuns": false, "video": false, diff --git a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_custom.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_custom.spec.ts new file mode 100644 index 0000000000000..b7e42f7e46a70 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_custom.spec.ts @@ -0,0 +1,273 @@ +/* + * 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 { newRule, totalNumberOfPrebuiltRules } from '../objects/rule'; + +import { + ABOUT_FALSE_POSITIVES, + ABOUT_INVESTIGATION_NOTES, + ABOUT_MITRE, + ABOUT_RISK, + ABOUT_RULE_DESCRIPTION, + ABOUT_SEVERITY, + ABOUT_STEP, + ABOUT_TAGS, + ABOUT_URLS, + DEFINITION_CUSTOM_QUERY, + DEFINITION_INDEX_PATTERNS, + DEFINITION_TIMELINE, + DEFINITION_STEP, + INVESTIGATION_NOTES_MARKDOWN, + INVESTIGATION_NOTES_TOGGLE, + RULE_ABOUT_DETAILS_HEADER_TOGGLE, + RULE_NAME_HEADER, + SCHEDULE_LOOPBACK, + SCHEDULE_RUNS, + SCHEDULE_STEP, +} from '../screens/rule_details'; +import { + CUSTOM_RULES_BTN, + RISK_SCORE, + RULE_NAME, + RULES_ROW, + RULES_TABLE, + SEVERITY, + SHOWING_RULES_TEXT, +} from '../screens/signal_detection_rules'; + +import { + createAndActivateRule, + fillAboutRuleAndContinue, + fillDefineCustomRuleAndContinue, +} from '../tasks/create_new_rule'; +import { + goToManageSignalDetectionRules, + waitForSignalsIndexToBeCreated, + waitForSignalsPanelToBeLoaded, +} from '../tasks/detections'; +import { + changeToThreeHundredRowsPerPage, + deleteFirstRule, + deleteSelectedRules, + filterByCustomRules, + goToCreateNewRule, + goToRuleDetails, + selectNumberOfRules, + waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, + waitForRulesToBeLoaded, +} from '../tasks/signal_detection_rules'; +import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; +import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; + +import { DETECTIONS } from '../urls/navigation'; + +describe('Signal detection rules, custom', () => { + before(() => { + esArchiverLoad('prebuilt_rules_loaded'); + }); + + after(() => { + esArchiverUnload('prebuilt_rules_loaded'); + }); + + it('Creates and activates a new custom rule', () => { + loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); + goToManageSignalDetectionRules(); + waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); + goToCreateNewRule(); + fillDefineCustomRuleAndContinue(newRule); + fillAboutRuleAndContinue(newRule); + createAndActivateRule(); + + cy.get(CUSTOM_RULES_BTN) + .invoke('text') + .should('eql', 'Custom rules (1)'); + + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + const expectedNumberOfRules = totalNumberOfPrebuiltRules + 1; + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); + }); + + filterByCustomRules(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', 1); + }); + cy.get(RULE_NAME) + .invoke('text') + .should('eql', newRule.name); + cy.get(RISK_SCORE) + .invoke('text') + .should('eql', newRule.riskScore); + cy.get(SEVERITY) + .invoke('text') + .should('eql', newRule.severity); + cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + + goToRuleDetails(); + + let expectedUrls = ''; + newRule.referenceUrls.forEach(url => { + expectedUrls = expectedUrls + url; + }); + let expectedFalsePositives = ''; + newRule.falsePositivesExamples.forEach(falsePositive => { + expectedFalsePositives = expectedFalsePositives + falsePositive; + }); + let expectedTags = ''; + newRule.tags.forEach(tag => { + expectedTags = expectedTags + tag; + }); + let expectedMitre = ''; + newRule.mitre.forEach(mitre => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach(technique => { + expectedMitre = expectedMitre + technique; + }); + }); + const expectedIndexPatterns = [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'packetbeat-*', + 'winlogbeat-*', + ]; + + cy.get(RULE_NAME_HEADER) + .invoke('text') + .should('eql', `${newRule.name} Beta`); + + cy.get(ABOUT_RULE_DESCRIPTION) + .invoke('text') + .should('eql', newRule.description); + cy.get(ABOUT_STEP) + .eq(ABOUT_SEVERITY) + .invoke('text') + .should('eql', newRule.severity); + cy.get(ABOUT_STEP) + .eq(ABOUT_RISK) + .invoke('text') + .should('eql', newRule.riskScore); + cy.get(ABOUT_STEP) + .eq(ABOUT_URLS) + .invoke('text') + .should('eql', expectedUrls); + cy.get(ABOUT_STEP) + .eq(ABOUT_FALSE_POSITIVES) + .invoke('text') + .should('eql', expectedFalsePositives); + cy.get(ABOUT_STEP) + .eq(ABOUT_MITRE) + .invoke('text') + .should('eql', expectedMitre); + cy.get(ABOUT_STEP) + .eq(ABOUT_TAGS) + .invoke('text') + .should('eql', expectedTags); + + cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE) + .eq(INVESTIGATION_NOTES_TOGGLE) + .click({ force: true }); + cy.get(ABOUT_INVESTIGATION_NOTES) + .invoke('text') + .should('eql', INVESTIGATION_NOTES_MARKDOWN); + + cy.get(DEFINITION_INDEX_PATTERNS).then(patterns => { + cy.wrap(patterns).each((pattern, index) => { + cy.wrap(pattern) + .invoke('text') + .should('eql', expectedIndexPatterns[index]); + }); + }); + cy.get(DEFINITION_STEP) + .eq(DEFINITION_CUSTOM_QUERY) + .invoke('text') + .should('eql', `${newRule.customQuery} `); + cy.get(DEFINITION_STEP) + .eq(DEFINITION_TIMELINE) + .invoke('text') + .should('eql', 'Default blank timeline'); + + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_RUNS) + .invoke('text') + .should('eql', '5m'); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_LOOPBACK) + .invoke('text') + .should('eql', '1m'); + }); +}); + +describe('Deletes custom rules', () => { + beforeEach(() => { + esArchiverLoad('custom_rules'); + loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); + goToManageSignalDetectionRules(); + }); + + after(() => { + esArchiverUnload('custom_rules'); + }); + + it('Deletes one rule', () => { + cy.get(RULES_TABLE) + .find(RULES_ROW) + .then(rules => { + const initialNumberOfRules = rules.length; + const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1; + + cy.get(SHOWING_RULES_TEXT) + .invoke('text') + .should('eql', `Showing ${initialNumberOfRules} rules`); + + deleteFirstRule(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + }); + cy.get(SHOWING_RULES_TEXT) + .invoke('text') + .should('eql', `Showing ${expectedNumberOfRulesAfterDeletion} rules`); + cy.get(CUSTOM_RULES_BTN) + .invoke('text') + .should('eql', `Custom rules (${expectedNumberOfRulesAfterDeletion})`); + }); + }); + + it('Deletes more than one rule', () => { + cy.get(RULES_TABLE) + .find(RULES_ROW) + .then(rules => { + const initialNumberOfRules = rules.length; + const numberOfRulesToBeDeleted = 3; + const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - numberOfRulesToBeDeleted; + + selectNumberOfRules(numberOfRulesToBeDeleted); + deleteSelectedRules(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + }); + cy.get(SHOWING_RULES_TEXT) + .invoke('text') + .should('eql', `Showing ${expectedNumberOfRulesAfterDeletion} rule`); + cy.get(CUSTOM_RULES_BTN) + .invoke('text') + .should('eql', `Custom rules (${expectedNumberOfRulesAfterDeletion})`); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_ml.spec.ts similarity index 63% rename from x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts rename to x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_ml.spec.ts index 70e4fb052e172..db56193c6b51c 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_ml.spec.ts @@ -4,31 +4,33 @@ * you may not use this file except in compliance with the Elastic License. */ -import { newRule } from '../objects/rule'; +import { machineLearningRule, totalNumberOfPrebuiltRules } from '../objects/rule'; import { ABOUT_FALSE_POSITIVES, ABOUT_MITRE, ABOUT_RISK, + ABOUT_RULE_DESCRIPTION, ABOUT_SEVERITY, ABOUT_STEP, ABOUT_TAGS, ABOUT_URLS, - DEFINITION_CUSTOM_QUERY, - DEFINITION_INDEX_PATTERNS, + ANOMALY_SCORE, DEFINITION_TIMELINE, DEFINITION_STEP, + MACHINE_LEARNING_JOB_ID, + MACHINE_LEARNING_JOB_STATUS, RULE_NAME_HEADER, SCHEDULE_LOOPBACK, SCHEDULE_RUNS, SCHEDULE_STEP, - ABOUT_RULE_DESCRIPTION, + RULE_TYPE, } from '../screens/rule_details'; import { CUSTOM_RULES_BTN, - ELASTIC_RULES_BTN, RISK_SCORE, RULE_NAME, + RULE_SWITCH, RULES_ROW, RULES_TABLE, SEVERITY, @@ -37,64 +39,46 @@ import { import { createAndActivateRule, fillAboutRuleAndContinue, - fillDefineRuleAndContinue, + fillDefineMachineLearningRuleAndContinue, + selectMachineLearningRuleType, } from '../tasks/create_new_rule'; +import { + goToManageSignalDetectionRules, + waitForSignalsIndexToBeCreated, + waitForSignalsPanelToBeLoaded, +} from '../tasks/detections'; import { changeToThreeHundredRowsPerPage, filterByCustomRules, goToCreateNewRule, goToRuleDetails, - loadPrebuiltDetectionRules, waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, - waitForPrebuiltDetectionRulesToBeLoaded, waitForRulesToBeLoaded, } from '../tasks/signal_detection_rules'; -import { - goToManageSignalDetectionRules, - waitForSignalsIndexToBeCreated, - waitForSignalsPanelToBeLoaded, -} from '../tasks/detections'; -import { esArchiverLoadEmptyKibana, esArchiverUnloadEmptyKibana } from '../tasks/es_archiver'; +import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { DETECTIONS } from '../urls/navigation'; -describe('Signal detection rules', () => { +describe('Signal detection rules, machine learning', () => { before(() => { - esArchiverLoadEmptyKibana(); - loginAndWaitForPageWithoutDateRange(DETECTIONS); - waitForSignalsPanelToBeLoaded(); - waitForSignalsIndexToBeCreated(); - goToManageSignalDetectionRules(); - waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); + esArchiverLoad('prebuilt_rules_loaded'); }); after(() => { - esArchiverUnloadEmptyKibana(); - }); - - it('Loads prebuilt rules', () => { - loadPrebuiltDetectionRules(); - waitForPrebuiltDetectionRulesToBeLoaded(); - - const expectedElasticRulesBtnText = 'Elastic rules (92)'; - cy.get(ELASTIC_RULES_BTN) - .invoke('text') - .should('eql', expectedElasticRulesBtnText); - - changeToThreeHundredRowsPerPage(); - waitForRulesToBeLoaded(); - - const expectedNumberOfRules = 92; - cy.get(RULES_TABLE).then($table => { - cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); - }); + esArchiverUnload('prebuilt_rules_loaded'); }); - it('Creates and activates new rule', () => { + it('Creates and activates a new ml rule', () => { + loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); + goToManageSignalDetectionRules(); + waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); goToCreateNewRule(); - fillDefineRuleAndContinue(newRule); - fillAboutRuleAndContinue(newRule); + selectMachineLearningRuleType(); + fillDefineMachineLearningRuleAndContinue(machineLearningRule); + fillAboutRuleAndContinue(machineLearningRule); createAndActivateRule(); cy.get(CUSTOM_RULES_BTN) @@ -104,7 +88,7 @@ describe('Signal detection rules', () => { changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - const expectedNumberOfRules = 93; + const expectedNumberOfRules = totalNumberOfPrebuiltRules + 1; cy.get(RULES_TABLE).then($table => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); }); @@ -116,60 +100,52 @@ describe('Signal detection rules', () => { }); cy.get(RULE_NAME) .invoke('text') - .should('eql', newRule.name); + .should('eql', machineLearningRule.name); cy.get(RISK_SCORE) .invoke('text') - .should('eql', newRule.riskScore); + .should('eql', machineLearningRule.riskScore); cy.get(SEVERITY) .invoke('text') - .should('eql', newRule.severity); - cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + .should('eql', machineLearningRule.severity); + cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); let expectedUrls = ''; - newRule.referenceUrls.forEach(url => { + machineLearningRule.referenceUrls.forEach(url => { expectedUrls = expectedUrls + url; }); let expectedFalsePositives = ''; - newRule.falsePositivesExamples.forEach(falsePositive => { + machineLearningRule.falsePositivesExamples.forEach(falsePositive => { expectedFalsePositives = expectedFalsePositives + falsePositive; }); let expectedTags = ''; - newRule.tags.forEach(tag => { + machineLearningRule.tags.forEach(tag => { expectedTags = expectedTags + tag; }); let expectedMitre = ''; - newRule.mitre.forEach(mitre => { + machineLearningRule.mitre.forEach(mitre => { expectedMitre = expectedMitre + mitre.tactic; mitre.techniques.forEach(technique => { expectedMitre = expectedMitre + technique; }); }); - const expectedIndexPatterns = [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; cy.get(RULE_NAME_HEADER) .invoke('text') - .should('eql', `${newRule.name} Beta`); + .should('eql', `${machineLearningRule.name} Beta`); cy.get(ABOUT_RULE_DESCRIPTION) .invoke('text') - .should('eql', newRule.description); + .should('eql', machineLearningRule.description); cy.get(ABOUT_STEP) .eq(ABOUT_SEVERITY) .invoke('text') - .should('eql', newRule.severity); + .should('eql', machineLearningRule.severity); cy.get(ABOUT_STEP) .eq(ABOUT_RISK) .invoke('text') - .should('eql', newRule.riskScore); + .should('eql', machineLearningRule.riskScore); cy.get(ABOUT_STEP) .eq(ABOUT_URLS) .invoke('text') @@ -187,17 +163,23 @@ describe('Signal detection rules', () => { .invoke('text') .should('eql', expectedTags); - cy.get(DEFINITION_INDEX_PATTERNS).then(patterns => { - cy.wrap(patterns).each((pattern, index) => { - cy.wrap(pattern) - .invoke('text') - .should('eql', expectedIndexPatterns[index]); - }); - }); cy.get(DEFINITION_STEP) - .eq(DEFINITION_CUSTOM_QUERY) + .eq(RULE_TYPE) + .invoke('text') + .should('eql', 'Machine Learning'); + cy.get(DEFINITION_STEP) + .eq(ANOMALY_SCORE) .invoke('text') - .should('eql', `${newRule.customQuery} `); + .should('eql', machineLearningRule.anomalyScoreThreshold); + cy.get(DEFINITION_STEP) + .get(MACHINE_LEARNING_JOB_STATUS) + .invoke('text') + .should('eql', 'Stopped'); + cy.get(DEFINITION_STEP) + .get(MACHINE_LEARNING_JOB_ID) + .invoke('text') + .should('eql', machineLearningRule.machineLearningJob); + cy.get(DEFINITION_STEP) .eq(DEFINITION_TIMELINE) .invoke('text') diff --git a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_prebuilt.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_prebuilt.spec.ts new file mode 100644 index 0000000000000..98af25cd7d209 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules_prebuilt.spec.ts @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + COLLAPSED_ACTION_BTN, + ELASTIC_RULES_BTN, + RELOAD_PREBUILT_RULES_BTN, + RULES_ROW, + RULES_TABLE, +} from '../screens/signal_detection_rules'; + +import { + changeToThreeHundredRowsPerPage, + deleteFirstRule, + deleteSelectedRules, + loadPrebuiltDetectionRules, + reloadDeletedRules, + selectNumberOfRules, + waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, + waitForPrebuiltDetectionRulesToBeLoaded, + waitForRulesToBeLoaded, +} from '../tasks/signal_detection_rules'; +import { + goToManageSignalDetectionRules, + waitForSignalsIndexToBeCreated, + waitForSignalsPanelToBeLoaded, +} from '../tasks/detections'; +import { + esArchiverLoad, + esArchiverLoadEmptyKibana, + esArchiverUnloadEmptyKibana, + esArchiverUnload, +} from '../tasks/es_archiver'; +import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; + +import { DETECTIONS } from '../urls/navigation'; + +import { totalNumberOfPrebuiltRules } from '../objects/rule'; + +describe('Signal detection rules, prebuilt rules', () => { + before(() => { + esArchiverLoadEmptyKibana(); + }); + + after(() => { + esArchiverUnloadEmptyKibana(); + }); + + it('Loads prebuilt rules', () => { + const expectedNumberOfRules = totalNumberOfPrebuiltRules; + const expectedElasticRulesBtnText = `Elastic rules (${expectedNumberOfRules})`; + + loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); + goToManageSignalDetectionRules(); + waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); + loadPrebuiltDetectionRules(); + waitForPrebuiltDetectionRulesToBeLoaded(); + + cy.get(ELASTIC_RULES_BTN) + .invoke('text') + .should('eql', expectedElasticRulesBtnText); + + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); + }); + }); +}); + +describe('Deleting prebuilt rules', () => { + beforeEach(() => { + esArchiverLoad('prebuilt_rules_loaded'); + loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); + goToManageSignalDetectionRules(); + }); + + afterEach(() => { + esArchiverUnload('prebuilt_rules_loaded'); + }); + + it('Does not allow to delete one rule when more than one is selected', () => { + const numberOfRulesToBeSelected = 2; + selectNumberOfRules(numberOfRulesToBeSelected); + + cy.get(COLLAPSED_ACTION_BTN).each(collapsedItemActionBtn => { + cy.wrap(collapsedItemActionBtn).should('have.attr', 'disabled'); + }); + }); + + it('Deletes and recovers one rule', () => { + const expectedNumberOfRulesAfterDeletion = totalNumberOfPrebuiltRules - 1; + const expectedNumberOfRulesAfterRecovering = totalNumberOfPrebuiltRules; + + deleteFirstRule(); + cy.reload(); + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + cy.get(ELASTIC_RULES_BTN) + .invoke('text') + .should('eql', `Elastic rules (${expectedNumberOfRulesAfterDeletion})`); + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + }); + cy.get(RELOAD_PREBUILT_RULES_BTN).should('exist'); + cy.get(RELOAD_PREBUILT_RULES_BTN) + .invoke('text') + .should('eql', 'Reload 1 deleted Elastic prebuilt rule '); + + reloadDeletedRules(); + + cy.get(RELOAD_PREBUILT_RULES_BTN).should('not.exist'); + + cy.reload(); + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterRecovering); + }); + cy.get(ELASTIC_RULES_BTN) + .invoke('text') + .should('eql', `Elastic rules (${expectedNumberOfRulesAfterRecovering})`); + }); + + it('Deletes and recovers more than one rule', () => { + const numberOfRulesToBeSelected = 2; + const expectedNumberOfRulesAfterDeletion = totalNumberOfPrebuiltRules - 2; + const expectedNumberOfRulesAfterRecovering = totalNumberOfPrebuiltRules; + + selectNumberOfRules(numberOfRulesToBeSelected); + deleteSelectedRules(); + cy.reload(); + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + cy.get(RELOAD_PREBUILT_RULES_BTN).should('exist'); + cy.get(RELOAD_PREBUILT_RULES_BTN) + .invoke('text') + .should('eql', `Reload ${numberOfRulesToBeSelected} deleted Elastic prebuilt rules `); + cy.get(ELASTIC_RULES_BTN) + .invoke('text') + .should('eql', `Elastic rules (${expectedNumberOfRulesAfterDeletion})`); + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + }); + + reloadDeletedRules(); + + cy.get(RELOAD_PREBUILT_RULES_BTN).should('not.exist'); + + cy.reload(); + changeToThreeHundredRowsPerPage(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then($table => { + cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterRecovering); + }); + cy.get(ELASTIC_RULES_BTN) + .invoke('text') + .should('eql', `Elastic rules (${expectedNumberOfRulesAfterRecovering})`); + }); +}); diff --git a/x-pack/legacy/plugins/siem/cypress/objects/rule.ts b/x-pack/legacy/plugins/siem/cypress/objects/rule.ts index ed9ef12860ab4..37c325c3b8030 100644 --- a/x-pack/legacy/plugins/siem/cypress/objects/rule.ts +++ b/x-pack/legacy/plugins/siem/cypress/objects/rule.ts @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +export const totalNumberOfPrebuiltRules = 92; + interface Mitre { tactic: string; techniques: string[]; } -export interface Rule { +export interface CustomRule { customQuery: string; name: string; description: string; @@ -20,6 +22,22 @@ export interface Rule { referenceUrls: string[]; falsePositivesExamples: string[]; mitre: Mitre[]; + note: string; +} + +export interface MachineLearningRule { + machineLearningJob: string; + anomalyScoreThreshold: string; + name: string; + description: string; + severity: string; + riskScore: string; + tags: string[]; + timelineTemplate?: string; + referenceUrls: string[]; + falsePositivesExamples: string[]; + mitre: Mitre[]; + note: string; } const mitre1: Mitre = { @@ -32,7 +50,7 @@ const mitre2: Mitre = { techniques: ['CMSTP (T1191)'], }; -export const newRule: Rule = { +export const newRule: CustomRule = { customQuery: 'hosts.name: *', name: 'New Rule Test', description: 'The new rule description.', @@ -42,4 +60,19 @@ export const newRule: Rule = { referenceUrls: ['https://www.google.com/', 'https://elastic.co/'], falsePositivesExamples: ['False1', 'False2'], mitre: [mitre1, mitre2], + note: '# test markdown', +}; + +export const machineLearningRule: MachineLearningRule = { + machineLearningJob: 'linux_anomalous_network_service', + anomalyScoreThreshold: '20', + name: 'New ML Rule Test', + description: 'The new ML rule description.', + severity: 'Critical', + riskScore: '70', + tags: ['ML'], + referenceUrls: ['https://elastic.co/'], + falsePositivesExamples: ['False1'], + mitre: [mitre1], + note: '# test markdown', }; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/create_new_rule.ts b/x-pack/legacy/plugins/siem/cypress/screens/create_new_rule.ts index 1ac9278c3ce1c..db9866cdf7f63 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/create_new_rule.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/create_new_rule.ts @@ -12,6 +12,8 @@ export const ADD_FALSE_POSITIVE_BTN = export const ADD_REFERENCE_URL_BTN = '[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] .euiButtonEmpty__text'; +export const ANOMALY_THRESHOLD_INPUT = '[data-test-subj="anomalyThresholdSlider"] .euiFieldNumber'; + export const MITRE_BTN = '[data-test-subj="addMitre"]'; export const ADVANCED_SETTINGS_BTN = '[data-test-subj="advancedSettings"] .euiAccordion__button'; @@ -20,11 +22,20 @@ export const CREATE_AND_ACTIVATE_BTN = '[data-test-subj="create-activate"]'; export const CUSTOM_QUERY_INPUT = '[data-test-subj="queryInput"]'; -export const DEFINE_CONTINUE_BUTTON = '[data-test-subj="continue"]'; +export const DEFINE_CONTINUE_BUTTON = '[data-test-subj="define-continue"]'; + +export const INVESTIGATION_NOTES_TEXTAREA = + '[data-test-subj="detectionEngineStepAboutRuleNote"] textarea'; export const FALSE_POSITIVES_INPUT = '[data-test-subj="detectionEngineStepAboutRuleFalsePositives"] input'; +export const MACHINE_LEARNING_DROPDOWN = '[data-test-subj="mlJobSelect"] button'; + +export const MACHINE_LEARNING_LIST = '.euiContextMenuItem__text'; + +export const MACHINE_LEARNING_TYPE = '[data-test-subj="machineLearningRuleType"]'; + export const MITRE_TACTIC = '.euiContextMenuItem__text'; export const MITRE_TACTIC_DROPDOWN = '[data-test-subj="mitreTactic"]'; @@ -43,7 +54,10 @@ export const RULE_DESCRIPTION_INPUT = export const RULE_NAME_INPUT = '[data-test-subj="detectionEngineStepAboutRuleName"] [data-test-subj="input"]'; -export const SEVERITY_DROPDOWN = '[data-test-subj="select"]'; +export const SCHEDULE_CONTINUE_BUTTON = '[data-test-subj="schedule-continue"]'; + +export const SEVERITY_DROPDOWN = + '[data-test-subj="detectionEngineStepAboutRuleSeverity"] [data-test-subj="select"]'; export const TAGS_INPUT = '[data-test-subj="detectionEngineStepAboutRuleTags"] [data-test-subj="comboBoxSearchInput"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts b/x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts index 06e535b37708c..ec57e142125da 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/rule_details.ts @@ -6,6 +6,8 @@ export const ABOUT_FALSE_POSITIVES = 3; +export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]'; + export const ABOUT_MITRE = 4; export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggleDescriptionText]'; @@ -20,6 +22,8 @@ export const ABOUT_TAGS = 5; export const ABOUT_URLS = 2; +export const ANOMALY_SCORE = 1; + export const DEFINITION_CUSTOM_QUERY = 1; export const DEFINITION_TIMELINE = 3; @@ -30,8 +34,20 @@ export const DEFINITION_INDEX_PATTERNS = export const DEFINITION_STEP = '[data-test-subj=definitionRule] [data-test-subj="listItemColumnStepRuleDescription"] .euiDescriptionList__description'; +export const INVESTIGATION_NOTES_MARKDOWN = 'test markdown'; + +export const INVESTIGATION_NOTES_TOGGLE = 1; + +export const MACHINE_LEARNING_JOB_ID = '[data-test-subj="machineLearningJobId"]'; + +export const MACHINE_LEARNING_JOB_STATUS = '[data-test-subj="machineLearningJobStatus" ]'; + +export const RULE_ABOUT_DETAILS_HEADER_TOGGLE = '[data-test-subj="stepAboutDetailsToggle"]'; + export const RULE_NAME_HEADER = '[data-test-subj="header-page-title"]'; +export const RULE_TYPE = 0; + export const SCHEDULE_STEP = '[data-test-subj="schedule"] .euiDescriptionList__description'; export const SCHEDULE_RUNS = 0; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/signal_detection_rules.ts b/x-pack/legacy/plugins/siem/cypress/screens/signal_detection_rules.ts index db3aaaaa94f4a..09fbc2132302c 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/signal_detection_rules.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/signal_detection_rules.ts @@ -4,10 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ +export const BULK_ACTIONS_BTN = '[data-test-subj="bulkActions"] span'; + export const CREATE_NEW_RULE_BTN = '[data-test-subj="create-new-rule"]'; +export const COLLAPSED_ACTION_BTN = '[data-test-subj="euiCollapsedItemActionsButton"]'; + export const CUSTOM_RULES_BTN = '[data-test-subj="show-custom-rules-filter-button"]'; +export const DELETE_RULE_ACTION_BTN = '[data-test-subj="deleteRuleAction"]'; + +export const DELETE_RULE_BULK_BTN = '[data-test-subj="deleteRuleBulk"]'; + export const ELASTIC_RULES_BTN = '[data-test-subj="show-elastic-rules-filter-button"]'; export const LOAD_PREBUILT_RULES_BTN = '[data-test-subj="load-prebuilt-rules"]'; @@ -21,12 +29,20 @@ export const PAGINATION_POPOVER_BTN = '[data-test-subj="tablePaginationPopoverBu export const RISK_SCORE = '[data-test-subj="riskScore"]'; +export const RELOAD_PREBUILT_RULES_BTN = '[data-test-subj="reloadPrebuiltRulesBtn"]'; + +export const RULE_CHECKBOX = '.euiTableRow .euiCheckbox__input'; + export const RULE_NAME = '[data-test-subj="ruleName"]'; +export const RULE_SWITCH = '[data-test-subj="rule-switch"]'; + export const RULES_TABLE = '[data-test-subj="rules-table"]'; export const RULES_ROW = '.euiTableRow'; export const SEVERITY = '[data-test-subj="severity"]'; +export const SHOWING_RULES_TEXT = '[data-test-subj="showingRules"]'; + export const THREE_HUNDRED_ROWS = '[data-test-subj="tablePagination-300-rows"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts b/x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts index 6bd5e0887e2fc..a20ad372a689c 100644 --- a/x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts +++ b/x-pack/legacy/plugins/siem/cypress/tasks/create_new_rule.ts @@ -3,9 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { Rule } from '../objects/rule'; +import { CustomRule, MachineLearningRule, machineLearningRule } from '../objects/rule'; import { ABOUT_CONTINUE_BTN, + ANOMALY_THRESHOLD_INPUT, ADD_FALSE_POSITIVE_BTN, ADD_REFERENCE_URL_BTN, ADVANCED_SETTINGS_BTN, @@ -13,6 +14,10 @@ import { CUSTOM_QUERY_INPUT, DEFINE_CONTINUE_BUTTON, FALSE_POSITIVES_INPUT, + INVESTIGATION_NOTES_TEXTAREA, + MACHINE_LEARNING_DROPDOWN, + MACHINE_LEARNING_LIST, + MACHINE_LEARNING_TYPE, MITRE_BTN, MITRE_TACTIC, MITRE_TACTIC_DROPDOWN, @@ -21,16 +26,18 @@ import { REFERENCE_URLS_INPUT, RULE_DESCRIPTION_INPUT, RULE_NAME_INPUT, + SCHEDULE_CONTINUE_BUTTON, SEVERITY_DROPDOWN, TAGS_INPUT, } from '../screens/create_new_rule'; export const createAndActivateRule = () => { + cy.get(SCHEDULE_CONTINUE_BUTTON).click({ force: true }); cy.get(CREATE_AND_ACTIVATE_BTN).click({ force: true }); cy.get(CREATE_AND_ACTIVATE_BTN).should('not.exist'); }; -export const fillAboutRuleAndContinue = (rule: Rule) => { +export const fillAboutRuleAndContinue = (rule: CustomRule | MachineLearningRule) => { cy.get(RULE_NAME_INPUT).type(rule.name, { force: true }); cy.get(RULE_DESCRIPTION_INPUT).type(rule.description, { force: true }); @@ -76,12 +83,14 @@ export const fillAboutRuleAndContinue = (rule: Rule) => { cy.get(MITRE_BTN).click({ force: true }); }); + cy.get(INVESTIGATION_NOTES_TEXTAREA).type(rule.note, { force: true }); + cy.get(ABOUT_CONTINUE_BTN) .should('exist') .click({ force: true }); }; -export const fillDefineRuleAndContinue = (rule: Rule) => { +export const fillDefineCustomRuleAndContinue = (rule: CustomRule) => { cy.get(CUSTOM_QUERY_INPUT).type(rule.customQuery); cy.get(CUSTOM_QUERY_INPUT).should('have.attr', 'value', rule.customQuery); cy.get(DEFINE_CONTINUE_BUTTON) @@ -90,3 +99,20 @@ export const fillDefineRuleAndContinue = (rule: Rule) => { cy.get(CUSTOM_QUERY_INPUT).should('not.exist'); }; + +export const fillDefineMachineLearningRuleAndContinue = (rule: MachineLearningRule) => { + cy.get(MACHINE_LEARNING_DROPDOWN).click({ force: true }); + cy.contains(MACHINE_LEARNING_LIST, rule.machineLearningJob).click(); + cy.get(ANOMALY_THRESHOLD_INPUT).type(`{selectall}${machineLearningRule.anomalyScoreThreshold}`, { + force: true, + }); + cy.get(DEFINE_CONTINUE_BUTTON) + .should('exist') + .click({ force: true }); + + cy.get(MACHINE_LEARNING_DROPDOWN).should('not.exist'); +}; + +export const selectMachineLearningRuleType = () => { + cy.get(MACHINE_LEARNING_TYPE).click({ force: true }); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts b/x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts index 1743fcb561064..6417a7d872251 100644 --- a/x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts +++ b/x-pack/legacy/plugins/siem/cypress/tasks/es_archiver.ts @@ -20,9 +20,17 @@ export const esArchiverLoad = (folder: string) => { ); }; +export const esArchiverUnload = (folder: string) => { + cy.exec( + `node ../../../../scripts/es_archiver unload ${folder} --dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url ${Cypress.env( + 'ELASTICSEARCH_URL' + )} --kibana-url ${Cypress.config().baseUrl}` + ); +}; + export const esArchiverUnloadEmptyKibana = () => { cy.exec( - `node ../../../../scripts/es_archiver empty_kibana unload empty--dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url ${Cypress.env( + `node ../../../../scripts/es_archiver unload empty_kibana empty--dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url ${Cypress.env( 'ELASTICSEARCH_URL' )} --kibana-url ${Cypress.config().baseUrl}` ); diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/login.ts b/x-pack/legacy/plugins/siem/cypress/tasks/login.ts index 3abf5a6930486..c7788b080d06e 100644 --- a/x-pack/legacy/plugins/siem/cypress/tasks/login.ts +++ b/x-pack/legacy/plugins/siem/cypress/tasks/login.ts @@ -131,5 +131,5 @@ export const loginAndWaitForPageWithoutDateRange = (url: string) => { login(); cy.viewport('macbook-15'); cy.visit(url); - cy.contains('a', 'SIEM', { timeout: 60000 }); + cy.contains('a', 'SIEM', { timeout: 120000 }); }; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/signal_detection_rules.ts b/x-pack/legacy/plugins/siem/cypress/tasks/signal_detection_rules.ts index 22e5f166b2981..cfc490526d84e 100644 --- a/x-pack/legacy/plugins/siem/cypress/tasks/signal_detection_rules.ts +++ b/x-pack/legacy/plugins/siem/cypress/tasks/signal_detection_rules.ts @@ -5,13 +5,21 @@ */ import { + BULK_ACTIONS_BTN, + COLLAPSED_ACTION_BTN, CREATE_NEW_RULE_BTN, + CUSTOM_RULES_BTN, + DELETE_RULE_ACTION_BTN, + DELETE_RULE_BULK_BTN, LOAD_PREBUILT_RULES_BTN, LOADING_INITIAL_PREBUILT_RULES_TABLE, LOADING_SPINNER, PAGINATION_POPOVER_BTN, + RULE_CHECKBOX, + RULE_NAME, RULES_TABLE, THREE_HUNDRED_ROWS, + RELOAD_PREBUILT_RULES_BTN, } from '../screens/signal_detection_rules'; export const changeToThreeHundredRowsPerPage = () => { @@ -19,10 +27,22 @@ export const changeToThreeHundredRowsPerPage = () => { cy.get(THREE_HUNDRED_ROWS).click(); }; +export const deleteFirstRule = () => { + cy.get(COLLAPSED_ACTION_BTN) + .first() + .click({ force: true }); + cy.get(DELETE_RULE_ACTION_BTN).click(); +}; + +export const deleteSelectedRules = () => { + cy.get(BULK_ACTIONS_BTN).click({ force: true }); + cy.get(DELETE_RULE_BULK_BTN).click(); +}; + export const filterByCustomRules = () => { - cy.get('[data-test-subj="show-custom-rules-filter-button"]').click({ force: true }); - cy.get('[data-test-subj="loading-spinner"]').should('exist'); - cy.get('[data-test-subj="loading-spinner"]').should('not.exist'); + cy.get(CUSTOM_RULES_BTN).click({ force: true }); + cy.get(LOADING_SPINNER).should('exist'); + cy.get(LOADING_SPINNER).should('not.exist'); }; export const goToCreateNewRule = () => { @@ -30,9 +50,7 @@ export const goToCreateNewRule = () => { }; export const goToRuleDetails = () => { - cy.get('[data-test-subj="ruleName"]').click({ force: true }); - cy.get('.euiLoadingSpinner').should('exist'); - cy.get('.euiLoadingSpinner').should('not.exist'); + cy.get(RULE_NAME).click({ force: true }); }; export const loadPrebuiltDetectionRules = () => { @@ -41,6 +59,18 @@ export const loadPrebuiltDetectionRules = () => { .click({ force: true }); }; +export const reloadDeletedRules = () => { + cy.get(RELOAD_PREBUILT_RULES_BTN).click({ force: true }); +}; + +export const selectNumberOfRules = (numberOfRules: number) => { + for (let i = 0; i < numberOfRules; i++) { + cy.get(RULE_CHECKBOX) + .eq(i) + .click({ force: true }); + } +}; + export const waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded = () => { cy.get(LOADING_INITIAL_PREBUILT_RULES_TABLE).should('exist'); cy.get(LOADING_INITIAL_PREBUILT_RULES_TABLE).should('not.exist'); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx index d0b1d8ffcb5ae..a3c4a655a4937 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx @@ -22,7 +22,8 @@ import { createEmbeddable, findMatchingIndexPatterns } from './embedded_map_help import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt'; import { MapToolTip } from './map_tool_tip/map_tool_tip'; import * as i18n from './translations'; -import { MapEmbeddable, SetQuery } from './types'; +import { SetQuery } from './types'; +import { MapEmbeddable } from '../../../../../plugins/maps/public'; import { Query, Filter } from '../../../../../../../src/plugins/data/public'; import { useKibana, useUiSetting$ } from '../../lib/kibana'; import { getSavedObjectFinder } from '../../../../../../../src/plugins/saved_objects/public'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx index 888df8447a728..4b32fd8299ef7 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map_helpers.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { OutPortal, PortalNode } from 'react-reverse-portal'; import minimatch from 'minimatch'; import { ViewMode } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; -import { IndexPatternMapping, MapEmbeddable, RenderTooltipContentParams, SetQuery } from './types'; +import { IndexPatternMapping, SetQuery } from './types'; import { getLayerList } from './map_config'; -// @ts-ignore Missing type defs as maps moves to Typescript -import { MAP_SAVED_OBJECT_TYPE } from '../../../../maps/common/constants'; +import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../plugins/maps/public'; +import { MapEmbeddable, RenderTooltipContentParams } from '../../../../maps/public'; import * as i18n from './translations'; import { Query, Filter } from '../../../../../../../src/plugins/data/public'; import { EmbeddableStart } from '../../../../../../../src/plugins/embeddable/public'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/map_tool_tip.tsx index 15c423a3b3dc1..fc55e3437dc21 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -64,7 +64,7 @@ export const MapToolTipComponent = ({ getLayerName(layerId), ]); - setFeatureProps(featureProperties); + setFeatureProps((featureProperties as unknown) as FeatureProperty[]); setFeatureGeometry(featureGeo); setLayerName(layerNameString); } catch (e) { diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts index cc253beb08eae..216fe9105327c 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/types.ts @@ -4,26 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TimeRange } from 'src/plugins/data/public'; -import { - EmbeddableInput, - EmbeddableOutput, - IEmbeddable, -} from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; +import { RenderTooltipContentParams } from '../../../../maps/public'; import { inputsModel } from '../../store/inputs'; -import { Query, Filter } from '../../../../../../../src/plugins/data/public'; - -export interface MapEmbeddableInput extends EmbeddableInput { - filters: Filter[]; - query: Query; - refreshConfig: { - isPaused: boolean; - interval: number; - }; - timeRange?: TimeRange; -} - -export type MapEmbeddable = IEmbeddable; export interface IndexPatternMapping { title: string; @@ -73,14 +55,4 @@ export interface FeatureGeometry { type: string; } -export interface RenderTooltipContentParams { - addFilters(filter: object): void; - closeTooltip(): void; - features: MapFeature[]; - isLocked: boolean; - getLayerName(layerId: string): Promise; - loadFeatureProperties({ layerId, featureId }: LoadFeatureProps): Promise; - loadFeatureGeometry({ layerId, featureId }: LoadFeatureProps): FeatureGeometry; -} - export type MapToolTipProps = Partial; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/import_data_modal/__snapshots__/index.test.tsx.snap similarity index 75% rename from x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/__snapshots__/index.test.tsx.snap rename to x-pack/legacy/plugins/siem/public/components/import_data_modal/__snapshots__/index.test.tsx.snap index 6b5ea2c5390f1..6503dd8dfb508 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/import_data_modal/__snapshots__/index.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ImportRuleModal renders correctly against snapshot 1`] = ` +exports[`ImportDataModal renders correctly against snapshot 1`] = ` - Import rule + title @@ -17,7 +17,7 @@ exports[`ImportRuleModal renders correctly against snapshot 1`] = ` size="s" >

- Select a SIEM rule (as exported from the Detection Engine UI) to import + description

@@ -39,9 +39,9 @@ exports[`ImportRuleModal renders correctly against snapshot 1`] = ` checked={false} compressed={false} disabled={false} - id="rule-overwrite-saved-object" + id="import-data-modal-checkbox-label" indeterminate={false} - label="Automatically overwrite saved objects with the same rule ID" + label="checkBoxLabel" onChange={[Function]} />
@@ -56,7 +56,7 @@ exports[`ImportRuleModal renders correctly against snapshot 1`] = ` fill={true} onClick={[Function]} > - Import rule + submitBtnText
diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/import_data_modal/index.test.tsx similarity index 51% rename from x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.test.tsx rename to x-pack/legacy/plugins/siem/public/components/import_data_modal/index.test.tsx index e10194853e7f9..85dcf9eeb3e5e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/import_data_modal/index.test.tsx @@ -6,17 +6,26 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { ImportRuleModalComponent } from './index'; +import { ImportDataModalComponent } from './index'; +jest.mock('../../lib/kibana'); -jest.mock('../../../../../lib/kibana'); - -describe('ImportRuleModal', () => { +describe('ImportDataModal', () => { test('renders correctly against snapshot', () => { const wrapper = shallow( - 'successMessage')} + title="title" /> ); expect(wrapper).toMatchSnapshot(); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.tsx b/x-pack/legacy/plugins/siem/public/components/import_data_modal/index.tsx similarity index 63% rename from x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.tsx rename to x-pack/legacy/plugins/siem/public/components/import_data_modal/index.tsx index 49a181a1cd897..c827411a41e2e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/import_data_modal/index.tsx @@ -21,29 +21,49 @@ import { } from '@elastic/eui'; import React, { useCallback, useState } from 'react'; -import { importRules } from '../../../../../containers/detection_engine/rules'; +import { ImportDataResponse, ImportDataProps } from '../../containers/detection_engine/rules'; import { displayErrorToast, displaySuccessToast, useStateToaster, errorToToaster, -} from '../../../../../components/toasters'; +} from '../toasters'; import * as i18n from './translations'; -interface ImportRuleModalProps { - showModal: boolean; +interface ImportDataModalProps { + checkBoxLabel: string; closeModal: () => void; + description: string; + errorMessage: string; + failedDetailed: (id: string, statusCode: number, message: string) => string; importComplete: () => void; + importData: (arg: ImportDataProps) => Promise; + showCheckBox: boolean; + showModal: boolean; + submitBtnText: string; + subtitle: string; + successMessage: (totalCount: number) => string; + title: string; } /** * Modal component for importing Rules from a json file */ -export const ImportRuleModalComponent = ({ - showModal, +export const ImportDataModalComponent = ({ + checkBoxLabel, closeModal, + description, + errorMessage, + failedDetailed, importComplete, -}: ImportRuleModalProps) => { + importData, + showCheckBox = true, + showModal, + submitBtnText, + subtitle, + successMessage, + title, +}: ImportDataModalProps) => { const [selectedFiles, setSelectedFiles] = useState(null); const [isImporting, setIsImporting] = useState(false); const [overwrite, setOverwrite] = useState(false); @@ -55,13 +75,13 @@ export const ImportRuleModalComponent = ({ closeModal(); }, [setIsImporting, setSelectedFiles, closeModal]); - const importRulesCallback = useCallback(async () => { + const importDataCallback = useCallback(async () => { if (selectedFiles != null) { setIsImporting(true); const abortCtrl = new AbortController(); try { - const importResponse = await importRules({ + const importResponse = await importData({ fileToImport: selectedFiles[0], overwrite, signal: abortCtrl.signal, @@ -70,23 +90,20 @@ export const ImportRuleModalComponent = ({ // TODO: Improve error toast details for better debugging failed imports // e.g. When success == true && success_count === 0 that means no rules were overwritten, etc if (importResponse.success) { - displaySuccessToast( - i18n.SUCCESSFULLY_IMPORTED_RULES(importResponse.success_count), - dispatchToaster - ); + displaySuccessToast(successMessage(importResponse.success_count), dispatchToaster); } if (importResponse.errors.length > 0) { const formattedErrors = importResponse.errors.map(e => - i18n.IMPORT_FAILED_DETAILED(e.rule_id, e.error.status_code, e.error.message) + failedDetailed(e.rule_id, e.error.status_code, e.error.message) ); - displayErrorToast(i18n.IMPORT_FAILED, formattedErrors, dispatchToaster); + displayErrorToast(errorMessage, formattedErrors, dispatchToaster); } importComplete(); cleanupAndCloseModal(); } catch (error) { cleanupAndCloseModal(); - errorToToaster({ title: i18n.IMPORT_FAILED, error, dispatchToaster }); + errorToToaster({ title: errorMessage, error, dispatchToaster }); } } }, [selectedFiles, overwrite]); @@ -102,18 +119,18 @@ export const ImportRuleModalComponent = ({ - {i18n.IMPORT_RULE} + {title} -

{i18n.SELECT_RULE}

+

{description}

{ setSelectedFiles(files && files.length > 0 ? files : null); }} @@ -122,22 +139,24 @@ export const ImportRuleModalComponent = ({ isLoading={isImporting} /> - setOverwrite(!overwrite)} - /> + {showCheckBox && ( + setOverwrite(!overwrite)} + /> + )}
{i18n.CANCEL_BUTTON} - {i18n.IMPORT_RULE} + {submitBtnText}
@@ -147,8 +166,8 @@ export const ImportRuleModalComponent = ({ ); }; -ImportRuleModalComponent.displayName = 'ImportRuleModalComponent'; +ImportDataModalComponent.displayName = 'ImportDataModalComponent'; -export const ImportRuleModal = React.memo(ImportRuleModalComponent); +export const ImportDataModal = React.memo(ImportDataModalComponent); -ImportRuleModal.displayName = 'ImportRuleModal'; +ImportDataModal.displayName = 'ImportDataModal'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/i18n.ts b/x-pack/legacy/plugins/siem/public/components/import_data_modal/translations.ts similarity index 65% rename from x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/i18n.ts rename to x-pack/legacy/plugins/siem/public/components/import_data_modal/translations.ts index 4e2e5eb7092e4..3fe8f2e3ee4bb 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/i18n.ts +++ b/x-pack/legacy/plugins/siem/public/components/import_data_modal/translations.ts @@ -6,9 +6,9 @@ import { i18n } from '@kbn/i18n'; -export const txtDisplayName = i18n.translate( - 'xpack.dashboard.panel.openFlyoutEditDrilldown.displayName', +export const CANCEL_BUTTON = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.cancelTitle', { - defaultMessage: 'Manage drilldowns', + defaultMessage: 'Cancel', } ); diff --git a/x-pack/legacy/plugins/siem/public/components/markdown/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/markdown/__snapshots__/index.test.tsx.snap index 4b02d23568d26..ce0c797c2b2b4 100644 --- a/x-pack/legacy/plugins/siem/public/components/markdown/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/markdown/__snapshots__/index.test.tsx.snap @@ -10,6 +10,7 @@ exports[`Markdown markdown links it renders the expected content containing a li rawSourcePos={false} renderers={ Object { + "blockquote": [Function], "link": [Function], "root": [Function], "table": [Function], @@ -35,6 +36,7 @@ exports[`Markdown markdown tables it renders the expected table content 1`] = ` rawSourcePos={false} renderers={ Object { + "blockquote": [Function], "link": [Function], "root": [Function], "table": [Function], diff --git a/x-pack/legacy/plugins/siem/public/components/markdown/index.tsx b/x-pack/legacy/plugins/siem/public/components/markdown/index.tsx index 1368c13619d6b..8e051685af56d 100644 --- a/x-pack/legacy/plugins/siem/public/components/markdown/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/markdown/index.tsx @@ -9,12 +9,20 @@ import { EuiLink, EuiTableRow, EuiTableRowCell, EuiText, EuiToolTip } from '@elastic/eui'; import React from 'react'; import ReactMarkdown from 'react-markdown'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; const TableHeader = styled.thead` font-weight: bold; `; +const MyBlockquote = styled.div` + ${({ theme }) => css` + padding: 0 ${theme.eui.euiSize}; + color: ${theme.eui.euiColorMediumShade}; + border-left: ${theme.eui.euiSizeXS} solid ${theme.eui.euiColorLightShade}; + `} +`; + TableHeader.displayName = 'TableHeader'; /** prevents links to the new pages from accessing `window.opener` */ @@ -63,6 +71,9 @@ export const Markdown = React.memo<{ ), + blockquote: ({ children }: { children: React.ReactNode[] }) => ( + {children} + ), }; return ( diff --git a/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts b/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts index ad59d3dc436a7..c4ca7dc203619 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml/anomaly/use_anomalies_table_data.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useState, useEffect, useContext } from 'react'; +import { useState, useEffect } from 'react'; import { anomaliesTableData } from '../api/anomalies_table_data'; import { InfluencerInput, Anomalies, CriteriaFields } from '../types'; import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../permissions/ml_capabilities_provider'; import { useSiemJobs } from '../../ml_popover/hooks/use_siem_jobs'; +import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities'; import { useStateToaster, errorToToaster } from '../../toasters'; import * as i18n from './translations'; @@ -59,7 +59,7 @@ export const useAnomaliesTableData = ({ const [tableData, setTableData] = useState(null); const [, siemJobs] = useSiemJobs(true); const [loading, setLoading] = useState(true); - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const userPermissions = hasMlUserPermissions(capabilities); const [, dispatchToaster] = useStateToaster(); const timeZone = useTimeZone(); diff --git a/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.test.ts b/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.test.ts new file mode 100644 index 0000000000000..693f0bd0dd0fd --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { isJobStarted, isJobLoading, isJobFailed } from './'; + +describe('isJobStarted', () => { + test('returns false if only jobState is enabled', () => { + expect(isJobStarted('started', 'closing')).toBe(false); + }); + + test('returns false if only datafeedState is enabled', () => { + expect(isJobStarted('stopping', 'opened')).toBe(false); + }); + + test('returns true if both enabled states are provided', () => { + expect(isJobStarted('started', 'opened')).toBe(true); + }); +}); + +describe('isJobLoading', () => { + test('returns true if both loading states are not provided', () => { + expect(isJobLoading('started', 'closing')).toBe(true); + }); + + test('returns true if only jobState is loading', () => { + expect(isJobLoading('starting', 'opened')).toBe(true); + }); + + test('returns true if only datafeedState is loading', () => { + expect(isJobLoading('started', 'opening')).toBe(true); + }); + + test('returns false if both disabling states are provided', () => { + expect(isJobLoading('stopping', 'closing')).toBe(true); + }); +}); + +describe('isJobFailed', () => { + test('returns true if only jobState is failure/deleted', () => { + expect(isJobFailed('failed', 'stopping')).toBe(true); + }); + + test('returns true if only dataFeed is failure/deleted', () => { + expect(isJobFailed('started', 'deleted')).toBe(true); + }); + + test('returns true if both enabled states are failure/deleted', () => { + expect(isJobFailed('failed', 'deleted')).toBe(true); + }); + + test('returns false only if both states are not failure/deleted', () => { + expect(isJobFailed('opened', 'stopping')).toBe(false); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.ts b/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.ts new file mode 100644 index 0000000000000..c06596b49317d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/ml/helpers/index.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. + */ + +// Based on ML Job/Datafeed States from x-pack/legacy/plugins/ml/common/constants/states.js +const enabledStates = ['started', 'opened']; +const loadingStates = ['starting', 'stopping', 'opening', 'closing']; +const failureStates = ['deleted', 'failed']; + +export const isJobStarted = (jobState: string, datafeedState: string): boolean => { + return enabledStates.includes(jobState) && enabledStates.includes(datafeedState); +}; + +export const isJobLoading = (jobState: string, datafeedState: string): boolean => { + return loadingStates.includes(jobState) || loadingStates.includes(datafeedState); +}; + +export const isJobFailed = (jobState: string, datafeedState: string): boolean => { + return failureStates.includes(jobState) || failureStates.includes(datafeedState); +}; diff --git a/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_host_table.tsx b/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_host_table.tsx index 9e58e39a08f67..16bde076ef763 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_host_table.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_host_table.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useAnomaliesTableData } from '../anomaly/use_anomalies_table_data'; import { HeaderSection } from '../../header_section'; @@ -16,7 +16,7 @@ import { Loader } from '../../loader'; import { getIntervalFromAnomalies } from '../anomaly/get_interval_from_anomalies'; import { AnomaliesHostTableProps } from '../types'; import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../permissions/ml_capabilities_provider'; +import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities'; import { BasicTable } from './basic_table'; import { hostEquality } from './host_equality'; import { getCriteriaFromHostType } from '../criteria/get_criteria_from_host_type'; @@ -37,7 +37,7 @@ const AnomaliesHostTableComponent: React.FC = ({ skip, type, }) => { - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const [loading, tableData] = useAnomaliesTableData({ startDate, endDate, diff --git a/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_network_table.tsx b/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_network_table.tsx index 05f3044ff2929..bba6355f0b8b9 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_network_table.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/tables/anomalies_network_table.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { useAnomaliesTableData } from '../anomaly/use_anomalies_table_data'; import { HeaderSection } from '../../header_section'; @@ -13,8 +13,8 @@ import { convertAnomaliesToNetwork } from './convert_anomalies_to_network'; import { Loader } from '../../loader'; import { AnomaliesNetworkTableProps } from '../types'; import { getAnomaliesNetworkTableColumnsCurated } from './get_anomalies_network_table_columns'; +import { useMlCapabilities } from '../../ml_popover/hooks/use_ml_capabilities'; import { hasMlUserPermissions } from '../permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../permissions/ml_capabilities_provider'; import { BasicTable } from './basic_table'; import { networkEquality } from './network_equality'; import { getCriteriaFromNetworkType } from '../criteria/get_criteria_from_network_type'; @@ -35,7 +35,7 @@ const AnomaliesNetworkTableComponent: React.FC = ({ type, flowTarget, }) => { - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const [loading, tableData] = useAnomaliesTableData({ startDate, endDate, diff --git a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory_definition.ts b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_ml_capabilities.tsx similarity index 55% rename from x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory_definition.ts rename to x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_ml_capabilities.tsx index f8669a4bf813f..d897b2554b4fd 100644 --- a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory_definition.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_ml_capabilities.tsx @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable */ +import { useContext } from 'react'; -export { - ActionFactoryDefinition -} from '../../../../../../src/plugins/ui_actions/public/actions/action_factory_definition'; +import { MlCapabilitiesContext } from '../../ml/permissions/ml_capabilities_provider'; + +export const useMlCapabilities = () => useContext(MlCapabilitiesContext); diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx index 4e4cdbfc109a9..9a82859066f54 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/hooks/use_siem_jobs.tsx @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useContext, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { checkRecognizer, getJobsSummary, getModules } from '../api'; import { SiemJob } from '../types'; import { hasMlUserPermissions } from '../../ml/permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../../ml/permissions/ml_capabilities_provider'; import { errorToToaster, useStateToaster } from '../../toasters'; import { useUiSetting$ } from '../../../lib/kibana'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import * as i18n from './translations'; import { createSiemJobs } from './use_siem_jobs_helpers'; +import { useMlCapabilities } from './use_ml_capabilities'; type Return = [boolean, SiemJob[]]; @@ -30,8 +30,8 @@ type Return = [boolean, SiemJob[]]; export const useSiemJobs = (refetchData: boolean): Return => { const [siemJobs, setSiemJobs] = useState([]); const [loading, setLoading] = useState(true); - const capabilities = useContext(MlCapabilitiesContext); - const userPermissions = hasMlUserPermissions(capabilities); + const mlCapabilities = useMlCapabilities(); + const userPermissions = hasMlUserPermissions(mlCapabilities); const [siemDefaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); const [, dispatchToaster] = useStateToaster(); diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.test.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.test.tsx index 1186573e3e209..ade8c6fe80525 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.test.tsx @@ -7,7 +7,7 @@ import { shallow, mount } from 'enzyme'; import React from 'react'; -import { isChecked, isFailure, isJobLoading, JobSwitchComponent } from './job_switch'; +import { JobSwitchComponent } from './job_switch'; import { cloneDeep } from 'lodash/fp'; import { mockSiemJobs } from '../__mocks__/api'; import { SiemJob } from '../types'; @@ -75,54 +75,4 @@ describe('JobSwitch', () => { ); expect(wrapper.find('[data-test-subj="job-switch"]').exists()).toBe(false); }); - - describe('isChecked', () => { - test('returns false if only jobState is enabled', () => { - expect(isChecked('started', 'closing')).toBe(false); - }); - - test('returns false if only datafeedState is enabled', () => { - expect(isChecked('stopping', 'opened')).toBe(false); - }); - - test('returns true if both enabled states are provided', () => { - expect(isChecked('started', 'opened')).toBe(true); - }); - }); - - describe('isJobLoading', () => { - test('returns true if both loading states are not provided', () => { - expect(isJobLoading('started', 'closing')).toBe(true); - }); - - test('returns true if only jobState is loading', () => { - expect(isJobLoading('starting', 'opened')).toBe(true); - }); - - test('returns true if only datafeedState is loading', () => { - expect(isJobLoading('started', 'opening')).toBe(true); - }); - - test('returns false if both disabling states are provided', () => { - expect(isJobLoading('stopping', 'closing')).toBe(true); - }); - }); - - describe('isFailure', () => { - test('returns true if only jobState is failure/deleted', () => { - expect(isFailure('failed', 'stopping')).toBe(true); - }); - - test('returns true if only dataFeed is failure/deleted', () => { - expect(isFailure('started', 'deleted')).toBe(true); - }); - - test('returns true if both enabled states are failure/deleted', () => { - expect(isFailure('failed', 'deleted')).toBe(true); - }); - - test('returns false only if both states are not failure/deleted', () => { - expect(isFailure('opened', 'stopping')).toBe(false); - }); - }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx index 39c48413737e2..e5066eef18c8b 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/jobs_table/job_switch.tsx @@ -8,6 +8,7 @@ import styled from 'styled-components'; import React, { useState, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiSwitch } from '@elastic/eui'; import { SiemJob } from '../types'; +import { isJobLoading, isJobStarted, isJobFailed } from '../../ml/helpers'; const StaticSwitch = styled(EuiSwitch)` .euiSwitch__thumb, @@ -24,23 +25,6 @@ export interface JobSwitchProps { onJobStateChange: (job: SiemJob, latestTimestampMs: number, enable: boolean) => Promise; } -// Based on ML Job/Datafeed States from x-pack/legacy/plugins/ml/common/constants/states.js -const enabledStates = ['started', 'opened']; -const loadingStates = ['starting', 'stopping', 'opening', 'closing']; -const failureStates = ['deleted', 'failed']; - -export const isChecked = (jobState: string, datafeedState: string): boolean => { - return enabledStates.includes(jobState) && enabledStates.includes(datafeedState); -}; - -export const isJobLoading = (jobState: string, datafeedState: string): boolean => { - return loadingStates.includes(jobState) || loadingStates.includes(datafeedState); -}; - -export const isFailure = (jobState: string, datafeedState: string): boolean => { - return failureStates.includes(jobState) || failureStates.includes(datafeedState); -}; - export const JobSwitchComponent = ({ job, isSiemJobsLoading, @@ -64,8 +48,8 @@ export const JobSwitchComponent = ({ ) : ( { const [filterProperties, setFilterProperties] = useState(defaultFilterProps); const [isLoadingSiemJobs, siemJobs] = useSiemJobs(refreshToggle); const [, dispatchToaster] = useStateToaster(); - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const docLinks = useKibana().services.docLinks; // Enable/Disable Job & Datafeed -- passed to JobsTable for use as callback on JobSwitch diff --git a/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts b/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts index f3bf78fdbb94c..991c82cf701e8 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/ml_popover/types.ts @@ -5,6 +5,7 @@ */ import { MlError } from '../ml/types'; +import { AuditMessageBase } from '../../../../../../plugins/ml/common/types/audit_message'; export interface Group { id: string; @@ -101,6 +102,7 @@ export interface MlSetupArgs { * Representation of an ML Job as returned from the `ml/jobs/jobs_summary` API */ export interface JobSummary { + auditMessage?: AuditMessageBase; datafeedId: string; datafeedIndices: string[]; datafeedState: string; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.test.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.test.ts index 60ebd2578b7c0..a779d579bf4d1 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.test.ts @@ -4,16 +4,48 @@ * you may not use this file except in compliance with the Elastic License. */ import { cloneDeep, omit } from 'lodash/fp'; +import { Dispatch } from 'redux'; -import { mockTimelineResults } from '../../mock/timeline_results'; +import { + mockTimelineResults, + mockTimelineResult, + mockTimelineModel, +} from '../../mock/timeline_results'; import { timelineDefaults } from '../../store/timeline/defaults'; +import { setTimelineRangeDatePicker as dispatchSetTimelineRangeDatePicker } from '../../store/inputs/actions'; +import { + setKqlFilterQueryDraft as dispatchSetKqlFilterQueryDraft, + applyKqlFilterQuery as dispatchApplyKqlFilterQuery, + addTimeline as dispatchAddTimeline, + addNote as dispatchAddGlobalTimelineNote, +} from '../../store/timeline/actions'; +import { + addNotes as dispatchAddNotes, + updateNote as dispatchUpdateNote, +} from '../../store/app/actions'; import { defaultTimelineToTimelineModel, getNotesCount, getPinnedEventCount, isUntitled, + omitTypenameInTimeline, + dispatchUpdateTimeline, } from './helpers'; -import { OpenTimelineResult } from './types'; +import { OpenTimelineResult, DispatchUpdateTimeline } from './types'; +import { KueryFilterQueryKind } from '../../store/model'; +import { Note } from '../../lib/note'; +import moment from 'moment'; +import sinon from 'sinon'; + +jest.mock('../../store/inputs/actions'); +jest.mock('../../store/timeline/actions'); +jest.mock('../../store/app/actions'); +jest.mock('uuid', () => { + return { + v1: jest.fn(() => 'uuid.v1()'), + v4: jest.fn(() => 'uuid.v4()'), + }; +}); describe('helpers', () => { let mockResults: OpenTimelineResult[]; @@ -620,4 +652,229 @@ describe('helpers', () => { }); }); }); + + describe('omitTypenameInTimeline', () => { + test('it does not modify the passed in timeline if no __typename exists', () => { + const result = omitTypenameInTimeline(mockTimelineResult); + + expect(result).toEqual(mockTimelineResult); + }); + + test('it returns timeline with __typename removed when it exists', () => { + const mockTimeline = { + ...mockTimelineResult, + __typename: 'something, something', + }; + const result = omitTypenameInTimeline(mockTimeline); + const expectedTimeline = { + ...mockTimeline, + __typename: undefined, + }; + + expect(result).toEqual(expectedTimeline); + }); + }); + + describe('dispatchUpdateTimeline', () => { + const dispatch = jest.fn() as Dispatch; + const anchor = '2020-03-27T20:34:51.337Z'; + const unix = moment(anchor).valueOf(); + let clock: sinon.SinonFakeTimers; + let timelineDispatch: DispatchUpdateTimeline; + + beforeEach(() => { + jest.clearAllMocks(); + + clock = sinon.useFakeTimers(unix); + timelineDispatch = dispatchUpdateTimeline(dispatch); + }); + + afterEach(function() { + clock.restore(); + }); + + test('it invokes date range picker dispatch', () => { + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimelineModel, + })(); + + expect(dispatchSetTimelineRangeDatePicker).toHaveBeenCalledWith({ + from: 1585233356356, + to: 1585233716356, + }); + }); + + test('it invokes add timeline dispatch', () => { + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimelineModel, + })(); + + expect(dispatchAddTimeline).toHaveBeenCalledWith({ + id: 'timeline-1', + timeline: mockTimelineModel, + }); + }); + + test('it does not invoke kql filter query dispatches if timeline.kqlQuery.filterQuery is null', () => { + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimelineModel, + })(); + + expect(dispatchSetKqlFilterQueryDraft).not.toHaveBeenCalled(); + expect(dispatchApplyKqlFilterQuery).not.toHaveBeenCalled(); + }); + + test('it does not invoke notes dispatch if duplicate is true', () => { + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimelineModel, + })(); + + expect(dispatchAddNotes).not.toHaveBeenCalled(); + }); + + test('it does not invoke kql filter query dispatches if timeline.kqlQuery.kuery is null', () => { + const mockTimeline = { + ...mockTimelineModel, + kqlQuery: { + filterQuery: { + kuery: null, + serializedQuery: 'some-serialized-query', + }, + filterQueryDraft: null, + }, + }; + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimeline, + })(); + + expect(dispatchSetKqlFilterQueryDraft).not.toHaveBeenCalled(); + expect(dispatchApplyKqlFilterQuery).not.toHaveBeenCalled(); + }); + + test('it invokes kql filter query dispatches if timeline.kqlQuery.filterQuery.kuery is not null', () => { + const mockTimeline = { + ...mockTimelineModel, + kqlQuery: { + filterQuery: { + kuery: { expression: 'expression', kind: 'kuery' as KueryFilterQueryKind }, + serializedQuery: 'some-serialized-query', + }, + filterQueryDraft: null, + }, + }; + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimeline, + })(); + + expect(dispatchSetKqlFilterQueryDraft).toHaveBeenCalledWith({ + id: 'timeline-1', + filterQueryDraft: { + kind: 'kuery', + expression: 'expression', + }, + }); + expect(dispatchApplyKqlFilterQuery).toHaveBeenCalledWith({ + id: 'timeline-1', + filterQuery: { + kuery: { + kind: 'kuery', + expression: 'expression', + }, + serializedQuery: 'some-serialized-query', + }, + }); + }); + + test('it invokes dispatchAddNotes if duplicate is false', () => { + timelineDispatch({ + duplicate: false, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [ + { + created: 1585233356356, + updated: 1585233356356, + noteId: 'note-id', + note: 'I am a note', + }, + ], + timeline: mockTimelineModel, + })(); + + expect(dispatchAddGlobalTimelineNote).not.toHaveBeenCalled(); + expect(dispatchUpdateNote).not.toHaveBeenCalled(); + expect(dispatchAddNotes).toHaveBeenCalledWith({ + notes: [ + { + created: new Date('2020-03-26T14:35:56.356Z'), + id: 'note-id', + lastEdit: new Date('2020-03-26T14:35:56.356Z'), + note: 'I am a note', + user: 'unknown', + saveObjectId: 'note-id', + version: undefined, + }, + ], + }); + }); + + test('it invokes dispatch to create a timeline note if duplicate is true and ruleNote exists', () => { + timelineDispatch({ + duplicate: true, + id: 'timeline-1', + from: 1585233356356, + to: 1585233716356, + notes: [], + timeline: mockTimelineModel, + ruleNote: '# this would be some markdown', + })(); + const expectedNote: Note = { + created: new Date(anchor), + id: 'uuid.v4()', + lastEdit: null, + note: '# this would be some markdown', + saveObjectId: null, + user: 'elastic', + version: null, + }; + + expect(dispatchAddNotes).not.toHaveBeenCalled(); + expect(dispatchUpdateNote).toHaveBeenCalledWith({ note: expectedNote }); + expect(dispatchAddGlobalTimelineNote).toHaveBeenLastCalledWith({ + id: 'timeline-1', + noteId: 'uuid.v4()', + }); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts index 4f7d6cd64f1d9..16ba2de872bd1 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts @@ -5,18 +5,23 @@ */ import ApolloClient from 'apollo-client'; -import { getOr, set } from 'lodash/fp'; +import { getOr, set, isEmpty } from 'lodash/fp'; import { Action } from 'typescript-fsa'; +import uuid from 'uuid'; import { Dispatch } from 'redux'; import { oneTimelineQuery } from '../../containers/timeline/one/index.gql_query'; import { TimelineResult, GetOneTimeline, NoteResult } from '../../graphql/types'; -import { addNotes as dispatchAddNotes } from '../../store/app/actions'; +import { + addNotes as dispatchAddNotes, + updateNote as dispatchUpdateNote, +} from '../../store/app/actions'; import { setTimelineRangeDatePicker as dispatchSetTimelineRangeDatePicker } from '../../store/inputs/actions'; import { setKqlFilterQueryDraft as dispatchSetKqlFilterQueryDraft, applyKqlFilterQuery as dispatchApplyKqlFilterQuery, addTimeline as dispatchAddTimeline, + addNote as dispatchAddGlobalTimelineNote, } from '../../store/timeline/actions'; import { ColumnHeaderOptions, TimelineModel } from '../../store/timeline/model'; @@ -32,6 +37,7 @@ import { import { OpenTimelineResult, UpdateTimeline, DispatchUpdateTimeline } from './types'; import { getTimeRangeSettings } from '../../utils/default_date_settings'; +import { createNote } from '../notes/helpers'; export const OPEN_TIMELINE_CLASS_NAME = 'open-timeline'; @@ -250,6 +256,7 @@ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeli notes, timeline, to, + ruleNote, }: UpdateTimeline): (() => void) => () => { dispatch(dispatchSetTimelineRangeDatePicker({ from, to })); dispatch(dispatchAddTimeline({ id, timeline })); @@ -281,6 +288,14 @@ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeli }) ); } + + if (duplicate && ruleNote != null && !isEmpty(ruleNote)) { + const getNewNoteId = (): string => uuid.v4(); + const newNote = createNote({ newNote: ruleNote, getNewNoteId }); + dispatch(dispatchUpdateNote({ note: newNote })); + dispatch(dispatchAddGlobalTimelineNote({ noteId: newNote.id, id })); + } + if (!duplicate) { dispatch( dispatchAddNotes({ diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx index 6d00edf28a88f..c27a6039da29d 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx @@ -52,7 +52,10 @@ interface OwnProps { } export type OpenTimelineOwnProps = OwnProps & - Pick & + Pick< + OpenTimelineProps, + 'defaultPageSize' | 'title' | 'importDataModalToggle' | 'setImportDataModalToggle' + > & PropsFromRedux; /** Returns a collection of selected timeline ids */ @@ -74,7 +77,9 @@ export const StatefulOpenTimelineComponent = React.memo( defaultPageSize, hideActions = [], isModal = false, + importDataModalToggle, onOpenTimeline, + setImportDataModalToggle, timeline, title, updateTimeline, @@ -264,6 +269,7 @@ export const StatefulOpenTimelineComponent = React.memo( defaultPageSize={defaultPageSize} isLoading={loading} itemIdToExpandedNotesRowMap={itemIdToExpandedNotesRowMap} + importDataModalToggle={importDataModalToggle} onAddTimelinesToFavorites={undefined} onDeleteSelected={onDeleteSelected} onlyFavorites={onlyFavorites} @@ -278,6 +284,7 @@ export const StatefulOpenTimelineComponent = React.memo( query={search} refetch={refetch} searchResults={timelines} + setImportDataModalToggle={setImportDataModalToggle} selectedItems={selectedItems} sortDirection={sortDirection} sortField={sortField} diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.tsx index b1b100349eb86..6b2f953b82de4 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline.tsx @@ -12,8 +12,10 @@ import { OpenTimelineProps, OpenTimelineResult } from './types'; import { SearchRow } from './search_row'; import { TimelinesTable } from './timelines_table'; import { TitleRow } from './title_row'; - +import { ImportDataModal } from '../import_data_modal'; import * as i18n from './translations'; +import { importTimelines } from '../../containers/timeline/all/api'; + import { UtilityBarGroup, UtilityBarText, @@ -31,6 +33,7 @@ export const OpenTimeline = React.memo( defaultPageSize, isLoading, itemIdToExpandedNotesRowMap, + importDataModalToggle, onAddTimelinesToFavorites, onDeleteSelected, onlyFavorites, @@ -47,6 +50,7 @@ export const OpenTimeline = React.memo( searchResults, selectedItems, sortDirection, + setImportDataModalToggle, sortField, title, totalSearchResultsCount, @@ -93,9 +97,25 @@ export const OpenTimeline = React.memo( ); const onRefreshBtnClick = useCallback(() => { - if (typeof refetch === 'function') refetch(); + if (refetch != null) { + refetch(); + } }, [refetch]); + const handleCloseModal = useCallback(() => { + if (setImportDataModalToggle != null) { + setImportDataModalToggle(false); + } + }, [setImportDataModalToggle]); + const handleComplete = useCallback(() => { + if (setImportDataModalToggle != null) { + setImportDataModalToggle(false); + } + if (refetch != null) { + refetch(); + } + }, [setImportDataModalToggle, refetch]); + return ( <> ( onComplete={onCompleteEditTimelineAction} title={actionItem?.title ?? i18n.UNTITLED_TIMELINE} /> + { expect(wrapper.find('[data-test-subj="open-duplicate"]').exists()).toBe(true); }); + test('it renders only duplicate icon (without heading)', () => { + const testProps: TimelinesTableProps = { + ...getMockTimelinesTableProps(mockResults), + actionTimelineToShow: ['duplicate'], + }; + const wrapper = mountWithIntl( + + + + ); + + expect( + wrapper + .find('[data-test-subj="open-duplicate"]') + .first() + .text() + ).toEqual(''); + }); + test('it does NOT render the duplicate timeline when actionTimelineToShow is NOT including the action duplicate)', () => { const testProps: TimelinesTableProps = { ...getMockTimelinesTableProps(mockResults), @@ -156,4 +175,72 @@ describe('#getActionsColumns', () => { expect(onOpenTimeline).toBeCalledWith({ duplicate: true, timelineId: 'saved-timeline-11' }); }); + + test('it renders the export icon when enableExportTimelineDownloader is including the action export', () => { + const testProps: TimelinesTableProps = { + ...getMockTimelinesTableProps(mockResults), + actionTimelineToShow: ['export'], + }; + const wrapper = mountWithIntl( + + + + ); + expect(wrapper.find('[data-test-subj="export-timeline"]').exists()).toBe(true); + }); + + test('it renders No export icon when export is not included in the action ', () => { + const testProps: TimelinesTableProps = { + ...getMockTimelinesTableProps(mockResults), + }; + const wrapper = mountWithIntl( + + + + ); + expect(wrapper.find('[data-test-subj="export-timeline"]').exists()).toBe(false); + }); + + test('it renders a disabled the export button if the timeline does not have a saved object id', () => { + const missingSavedObjectId: OpenTimelineResult[] = [ + omit('savedObjectId', { ...mockResults[0] }), + ]; + + const testProps: TimelinesTableProps = { + ...getMockTimelinesTableProps(missingSavedObjectId), + actionTimelineToShow: ['export'], + }; + const wrapper = mountWithIntl( + + + + ); + + const props = wrapper + .find('[data-test-subj="export-timeline"]') + .first() + .props() as EuiButtonIconProps; + expect(props.isDisabled).toBe(true); + }); + + test('it invokes enableExportTimelineDownloader with the expected params when the button is clicked', () => { + const enableExportTimelineDownloader = jest.fn(); + const testProps: TimelinesTableProps = { + ...getMockTimelinesTableProps(mockResults), + actionTimelineToShow: ['export'], + enableExportTimelineDownloader, + }; + const wrapper = mountWithIntl( + + + + ); + + wrapper + .find('[data-test-subj="export-timeline"]') + .first() + .simulate('click'); + + expect(enableExportTimelineDownloader).toBeCalledWith(mockResults[0]); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.tsx index 4bbf98dafe38d..746503308c833 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/actions_columns.tsx @@ -42,6 +42,7 @@ export const getActionsColumns = ({ timelineId: savedObjectId ?? '', }); }, + type: 'icon', enabled: ({ savedObjectId }: OpenTimelineResult) => savedObjectId != null, description: i18n.OPEN_AS_DUPLICATE, 'data-test-subj': 'open-duplicate', @@ -55,6 +56,7 @@ export const getActionsColumns = ({ }, enabled: ({ savedObjectId }: OpenTimelineResult) => savedObjectId != null, description: i18n.EXPORT_SELECTED, + 'data-test-subj': 'export-timeline', }; const deleteTimelineColumn = { diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/translations.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/translations.ts index 4063b73d9499a..7914e368166db 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/translations.ts @@ -145,3 +145,61 @@ export const SUCCESSFULLY_EXPORTED_TIMELINES = (totalTimelines: number) => defaultMessage: 'Successfully exported {totalTimelines, plural, =0 {all timelines} =1 {{totalTimelines} timeline} other {{totalTimelines} timelines}}', }); + +export const IMPORT_TIMELINE_BTN_TITLE = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.importTimelineTitle', + { + defaultMessage: 'Import timeline', + } +); + +export const SELECT_TIMELINE = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.selectTimelineDescription', + { + defaultMessage: 'Select a SIEM timeline (as exported from the Timeline view) to import', + } +); + +export const INITIAL_PROMPT_TEXT = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.initialPromptTextDescription', + { + defaultMessage: 'Select or drag and drop a valid timelines_export.ndjson file', + } +); + +export const OVERWRITE_WITH_SAME_NAME = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.overwriteDescription', + { + defaultMessage: 'Automatically overwrite saved objects with the same timeline ID', + } +); + +export const SUCCESSFULLY_IMPORTED_TIMELINES = (totalCount: number) => + i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.successfullyImportedTimelinesTitle', + { + values: { totalCount }, + defaultMessage: + 'Successfully imported {totalCount} {totalCount, plural, =1 {timeline} other {timelines}}', + } + ); + +export const IMPORT_FAILED = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.importFailedTitle', + { + defaultMessage: 'Failed to import timelines', + } +); + +export const IMPORT_TIMELINE = i18n.translate( + 'xpack.siem.timelines.components.importTimelineModal.importTitle', + { + defaultMessage: 'Import timeline…', + } +); + +export const IMPORT_FAILED_DETAILED = (id: string, statusCode: number, message: string) => + i18n.translate('xpack.siem.timelines.components.importTimelineModal.importFailedDetailedTitle', { + values: { id, statusCode, message }, + defaultMessage: 'Timeline ID: {id}\n Status Code: {statusCode}\n Message: {message}', + }); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts index b466ea32799d9..b7cc92ebd183f 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts @@ -120,6 +120,8 @@ export interface OpenTimelineProps { isLoading: boolean; /** Required by EuiTable for expandable rows: a map of `TimelineResult.savedObjectId` to rendered notes */ itemIdToExpandedNotesRowMap: Record; + /** Display import timelines modal*/ + importDataModalToggle?: boolean; /** If this callback is specified, a "Favorite Selected" button will be displayed, and this callback will be invoked when the button is clicked */ onAddTimelinesToFavorites?: OnAddTimelinesToFavorites; /** If this callback is specified, a "Delete Selected" button will be displayed, and this callback will be invoked when the button is clicked */ @@ -144,13 +146,14 @@ export interface OpenTimelineProps { pageSize: number; /** The currently applied search criteria */ query: string; - /** Refetch timelines data */ + /** Refetch table */ refetch?: Refetch; - /** The results of executing a search */ searchResults: OpenTimelineResult[]; /** the currently-selected timelines in the table */ selectedItems: OpenTimelineResult[]; + /** Toggle export timelines modal*/ + setImportDataModalToggle?: React.Dispatch>; /** the requested sort direction of the query results */ sortDirection: 'asc' | 'desc'; /** the requested field to sort on */ @@ -170,6 +173,7 @@ export interface UpdateTimeline { notes: NoteResult[] | null | undefined; timeline: TimelineModel; to: number; + ruleNote?: string; } export type DispatchUpdateTimeline = ({ @@ -179,4 +183,5 @@ export type DispatchUpdateTimeline = ({ notes, timeline, to, + ruleNote, }: UpdateTimeline) => () => void; diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/host_overview/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/host_overview/index.tsx index bf32a33af1eac..4d0e6a737d303 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/host_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/host_overview/index.tsx @@ -8,7 +8,7 @@ import { EuiFlexItem } from '@elastic/eui'; import darkTheme from '@elastic/eui/dist/eui_theme_dark.json'; import lightTheme from '@elastic/eui/dist/eui_theme_light.json'; import { getOr } from 'lodash/fp'; -import React, { useContext } from 'react'; +import React from 'react'; import { DEFAULT_DARK_MODE } from '../../../../../common/constants'; import { DescriptionList } from '../../../../../common/utility_types'; @@ -19,8 +19,8 @@ import { InspectButton, InspectButtonContainer } from '../../../inspect'; import { HostItem } from '../../../../graphql/types'; import { Loader } from '../../../loader'; import { IPDetailsLink } from '../../../links'; -import { MlCapabilitiesContext } from '../../../ml/permissions/ml_capabilities_provider'; import { hasMlUserPermissions } from '../../../ml/permissions/has_ml_user_permissions'; +import { useMlCapabilities } from '../../../ml_popover/hooks/use_ml_capabilities'; import { AnomalyScores } from '../../../ml/score/anomaly_scores'; import { Anomalies, NarrowDateRange } from '../../../ml/types'; import { DescriptionListStyled, OverviewWrapper } from '../../index'; @@ -56,7 +56,7 @@ export const HostOverview = React.memo( anomaliesData, narrowDateRange, }) => { - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const userPermissions = hasMlUserPermissions(capabilities); const [darkMode] = useUiSetting$(DEFAULT_DARK_MODE); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx index 901b82210a661..56b59ca97156f 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx @@ -7,7 +7,7 @@ import { EuiFlexItem } from '@elastic/eui'; import darkTheme from '@elastic/eui/dist/eui_theme_dark.json'; import lightTheme from '@elastic/eui/dist/eui_theme_light.json'; -import React, { useContext } from 'react'; +import React from 'react'; import { DEFAULT_DARK_MODE } from '../../../../../common/constants'; import { DescriptionList } from '../../../../../common/utility_types'; @@ -30,7 +30,7 @@ import { DescriptionListStyled, OverviewWrapper } from '../../index'; import { Loader } from '../../../loader'; import { Anomalies, NarrowDateRange } from '../../../ml/types'; import { AnomalyScores } from '../../../ml/score/anomaly_scores'; -import { MlCapabilitiesContext } from '../../../ml/permissions/ml_capabilities_provider'; +import { useMlCapabilities } from '../../../ml_popover/hooks/use_ml_capabilities'; import { hasMlUserPermissions } from '../../../ml/permissions/has_ml_user_permissions'; import { InspectButton, InspectButtonContainer } from '../../../inspect'; @@ -71,7 +71,7 @@ export const IpOverview = React.memo( anomaliesData, narrowDateRange, }) => { - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const userPermissions = hasMlUserPermissions(capabilities); const [darkMode] = useUiSetting$(DEFAULT_DARK_MODE); const typeData: Overview = data[flowTarget]!; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/api.ts index 16ee294224bb9..7d5ae53b78ff8 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/api.ts @@ -8,10 +8,10 @@ import { CaseResponse, CasesResponse, CasesFindResponse, - CaseRequest, + CasePatchRequest, + CasePostRequest, CasesStatusResponse, CommentRequest, - CommentResponse, User, CaseUserActionsResponse, CaseExternalServiceRequest, @@ -19,19 +19,22 @@ import { ServiceConnectorCaseResponse, ActionTypeExecutorResult, } from '../../../../../../plugins/case/common/api'; + import { KibanaServices } from '../../lib/kibana'; + import { ActionLicense, AllCases, BulkUpdateStatus, Case, CasesStatus, - Comment, FetchCasesProps, SortFieldCase, CaseUserActions, } from './types'; + import { CASES_URL } from './constants'; + import { convertToCamelCase, convertAllCasesToCamel, @@ -40,17 +43,21 @@ import { decodeCasesResponse, decodeCasesFindResponse, decodeCasesStatusResponse, - decodeCommentResponse, decodeCaseUserActionsResponse, decodeServiceConnectorCaseResponse, } from './utils'; -export const getCase = async (caseId: string, includeComments: boolean = true): Promise => { +export const getCase = async ( + caseId: string, + includeComments: boolean = true, + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/${caseId}`, { method: 'GET', query: { includeComments, }, + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; @@ -66,9 +73,10 @@ export const getCasesStatus = async (signal: AbortSignal): Promise return convertToCamelCase(decodeCasesStatusResponse(response)); }; -export const getTags = async (): Promise => { +export const getTags = async (signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(`${CASES_URL}/tags`, { method: 'GET', + signal, }); return response ?? []; }; @@ -108,6 +116,7 @@ export const getCases = async ({ sortField: SortFieldCase.createdAt, sortOrder: 'desc', }, + signal, }: FetchCasesProps): Promise => { const query = { reporters: filterOptions.reporters.map(r => r.username), @@ -119,69 +128,85 @@ export const getCases = async ({ const response = await KibanaServices.get().http.fetch(`${CASES_URL}/_find`, { method: 'GET', query, + signal, }); return convertAllCasesToCamel(decodeCasesFindResponse(response)); }; -export const postCase = async (newCase: CaseRequest): Promise => { +export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'POST', body: JSON.stringify(newCase), + signal, }); return convertToCamelCase(decodeCaseResponse(response)); }; export const patchCase = async ( caseId: string, - updatedCase: Partial, - version: string + updatedCase: Pick, + version: string, + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases: [{ ...updatedCase, id: caseId, version }] }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const patchCasesStatus = async (cases: BulkUpdateStatus[]): Promise => { +export const patchCasesStatus = async ( + cases: BulkUpdateStatus[], + signal: AbortSignal +): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'PATCH', body: JSON.stringify({ cases }), + signal, }); return convertToCamelCase(decodeCasesResponse(response)); }; -export const postComment = async (newComment: CommentRequest, caseId: string): Promise => { - const response = await KibanaServices.get().http.fetch( +export const postComment = async ( + newComment: CommentRequest, + caseId: string, + signal: AbortSignal +): Promise => { + const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'POST', body: JSON.stringify(newComment), + signal, } ); - return convertToCamelCase(decodeCommentResponse(response)); + return convertToCamelCase(decodeCaseResponse(response)); }; export const patchComment = async ( caseId: string, commentId: string, commentUpdate: string, - version: string -): Promise> => { - const response = await KibanaServices.get().http.fetch( + version: string, + signal: AbortSignal +): Promise => { + const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'PATCH', body: JSON.stringify({ comment: commentUpdate, id: commentId, version }), + signal, } ); - return convertToCamelCase(decodeCommentResponse(response)); + return convertToCamelCase(decodeCaseResponse(response)); }; -export const deleteCases = async (caseIds: string[]): Promise => { +export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise => { const response = await KibanaServices.get().http.fetch(CASES_URL, { method: 'DELETE', query: { ids: JSON.stringify(caseIds) }, + signal, }); return response === 'true' ? true : false; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx index a24f8303824c5..b25667f070fdf 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx @@ -10,6 +10,7 @@ import { getCaseConfigure, patchCaseConfigure, postCaseConfigure } from './api'; import { useStateToaster, errorToToaster } from '../../../components/toasters'; import * as i18n from '../translations'; import { ClosureType } from './types'; +import { CurrentConfiguration } from '../../../pages/case/components/configure_cases/reducer'; interface PersistCaseConfigure { connectorId: string; @@ -27,14 +28,17 @@ export interface ReturnUseCaseConfigure { interface UseCaseConfigure { setConnector: (newConnectorId: string, newConnectorName?: string) => void; setClosureType?: (newClosureType: ClosureType) => void; + setCurrentConfiguration?: (configuration: CurrentConfiguration) => void; } export const useCaseConfigure = ({ setConnector, setClosureType, + setCurrentConfiguration, }: UseCaseConfigure): ReturnUseCaseConfigure => { const [, dispatchToaster] = useStateToaster(); const [loading, setLoading] = useState(true); + const [firstLoad, setFirstLoad] = useState(false); const [persistLoading, setPersistLoading] = useState(false); const [version, setVersion] = useState(''); @@ -54,6 +58,16 @@ export const useCaseConfigure = ({ setClosureType(res.closureType); } setVersion(res.version); + + if (!firstLoad) { + setFirstLoad(true); + if (setCurrentConfiguration != null) { + setCurrentConfiguration({ + connectorId: res.connectorId, + closureType: res.closureType, + }); + } + } } } } catch (error) { @@ -104,6 +118,12 @@ export const useCaseConfigure = ({ setClosureType(res.closureType); } setVersion(res.version); + if (setCurrentConfiguration != null) { + setCurrentConfiguration({ + connectorId: res.connectorId, + closureType: res.closureType, + }); + } } } catch (error) { if (!didCancel) { diff --git a/x-pack/legacy/plugins/siem/public/containers/case/types.ts b/x-pack/legacy/plugins/siem/public/containers/case/types.ts index bbbb13788d53a..bb215d6ac271c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/types.ts @@ -93,7 +93,7 @@ export interface ElasticUser { readonly username: string; } -export interface FetchCasesProps { +export interface FetchCasesProps extends ApiProps { queryParams?: QueryParams; filterOptions?: FilterOptions; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx index 77d779ab906cf..f1129bae9f537 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx @@ -66,10 +66,12 @@ export const useUpdateCases = (): UseUpdateCase => { const dispatchUpdateCases = useCallback((cases: BulkUpdateStatus[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const patchData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await patchCasesStatus(cases); + await patchCasesStatus(cases, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -87,6 +89,7 @@ export const useUpdateCases = (): UseUpdateCase => { patchData(); return () => { cancel = true; + abortCtrl.abort(); }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx index d5a3b3cf9314c..b44e01d06acaf 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx @@ -74,10 +74,12 @@ export const useDeleteCases = (): UseDeleteCase => { const dispatchDeleteCases = useCallback((caseIds: string[]) => { let cancel = false; + const abortCtrl = new AbortController(); + const deleteData = async () => { try { dispatch({ type: 'FETCH_INIT' }); - await deleteCases(caseIds); + await deleteCases(caseIds, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', payload: true }); } @@ -94,6 +96,7 @@ export const useDeleteCases = (): UseDeleteCase => { }; deleteData(); return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx index 02b41c9fc720f..835fb7153dc95 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useEffect, useReducer } from 'react'; +import { useEffect, useReducer, useCallback } from 'react'; import { Case } from './types'; import * as i18n from './translations'; @@ -20,7 +20,8 @@ interface CaseState { type Action = | { type: 'FETCH_INIT' } | { type: 'FETCH_SUCCESS'; payload: Case } - | { type: 'FETCH_FAILURE' }; + | { type: 'FETCH_FAILURE' } + | { type: 'UPDATE_CASE'; payload: Case }; const dataFetchReducer = (state: CaseState, action: Action): CaseState => { switch (action.type) { @@ -43,6 +44,11 @@ const dataFetchReducer = (state: CaseState, action: Action): CaseState => { isLoading: false, isError: true, }; + case 'UPDATE_CASE': + return { + ...state, + data: action.payload, + }; default: return state; } @@ -67,7 +73,12 @@ const initialData: Case = { version: '', }; -export const useGetCase = (caseId: string): CaseState => { +interface UseGetCase extends CaseState { + fetchCase: () => void; + updateCase: (newCase: Case) => void; +} + +export const useGetCase = (caseId: string): UseGetCase => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: true, isError: false, @@ -75,12 +86,18 @@ export const useGetCase = (caseId: string): CaseState => { }); const [, dispatchToaster] = useStateToaster(); - const callFetch = () => { + const updateCase = useCallback((newCase: Case) => { + dispatch({ type: 'UPDATE_CASE', payload: newCase }); + }, []); + + const callFetch = useCallback(async () => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getCase(caseId); + const response = await getCase(caseId, true, abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -98,11 +115,12 @@ export const useGetCase = (caseId: string): CaseState => { fetchData(); return () => { didCancel = true; + abortCtrl.abort(); }; - }; + }, [caseId]); useEffect(() => { callFetch(); }, [caseId]); - return state; + return { ...state, fetchCase: callFetch, updateCase }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx index ae7b8f3c043fa..323dc23e1b24e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx @@ -149,12 +149,15 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const fetchCases = useCallback((filterOptions: FilterOptions, queryParams: QueryParams) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'cases' }); try { const response = await getCases({ filterOptions, queryParams, + signal: abortCtrl.signal, }); if (!didCancel) { dispatch({ @@ -175,6 +178,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); @@ -187,13 +191,17 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { const dispatchUpdateCaseProperty = useCallback( ({ updateKey, updateValue, caseId, refetchCasesStatus, version }: UpdateCase) => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT', payload: 'caseUpdate' }); try { await patchCase( caseId, { [updateKey]: updateValue }, - version ?? '' // saved object versions are typed as string | undefined, hope that's not true + // saved object versions are typed as string | undefined, hope that's not true + version ?? '', + abortCtrl.signal ); if (!didCancel) { dispatch({ type: 'FETCH_UPDATE_CASE_SUCCESS' }); @@ -209,6 +217,7 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx index e3657f5b09da9..b41d5aab5c07a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx @@ -57,10 +57,12 @@ export const useGetTags = (): TagsState => { useEffect(() => { let didCancel = false; + const abortCtrl = new AbortController(); + const fetchData = async () => { dispatch({ type: 'FETCH_INIT' }); try { - const response = await getTags(); + const response = await getTags(abortCtrl.signal); if (!didCancel) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); } @@ -77,6 +79,7 @@ export const useGetTags = (): TagsState => { }; fetchData(); return () => { + abortCtrl.abort(); didCancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx index 817101cf5e663..0e01364721dc5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx @@ -6,7 +6,7 @@ import { useReducer, useCallback } from 'react'; -import { CaseRequest } from '../../../../../../plugins/case/common/api'; +import { CasePostRequest } from '../../../../../../plugins/case/common/api'; import { errorToToaster, useStateToaster } from '../../components/toasters'; import { postCase } from './api'; import * as i18n from './translations'; @@ -49,7 +49,7 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => }; interface UsePostCase extends NewCaseState { - postCase: (data: CaseRequest) => void; + postCase: (data: CasePostRequest) => void; } export const usePostCase = (): UsePostCase => { const [state, dispatch] = useReducer(dataFetchReducer, { @@ -59,11 +59,13 @@ export const usePostCase = (): UsePostCase => { }); const [, dispatchToaster] = useStateToaster(); - const postMyCase = useCallback(async (data: CaseRequest) => { + const postMyCase = useCallback(async (data: CasePostRequest) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT' }); - const response = await postCase({ ...data, status: 'open' }); + const response = await postCase(data, abortCtrl.signal); if (!cancel) { dispatch({ type: 'FETCH_SUCCESS', @@ -81,6 +83,7 @@ export const usePostCase = (): UsePostCase => { } } return () => { + abortCtrl.abort(); cancel = true; }; }, []); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx index a96cb97d7cc7b..207b05814717f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx @@ -11,43 +11,28 @@ import { errorToToaster, useStateToaster } from '../../components/toasters'; import { postComment } from './api'; import * as i18n from './translations'; -import { Comment } from './types'; +import { Case } from './types'; interface NewCommentState { - commentData: Comment | null; isLoading: boolean; isError: boolean; - caseId: string; } -type Action = - | { type: 'RESET_COMMENT_DATA' } - | { type: 'FETCH_INIT' } - | { type: 'FETCH_SUCCESS'; payload: Comment } - | { type: 'FETCH_FAILURE' }; +type Action = { type: 'FETCH_INIT' } | { type: 'FETCH_SUCCESS' } | { type: 'FETCH_FAILURE' }; const dataFetchReducer = (state: NewCommentState, action: Action): NewCommentState => { switch (action.type) { - case 'RESET_COMMENT_DATA': - return { - ...state, - commentData: null, - }; case 'FETCH_INIT': return { - ...state, isLoading: true, isError: false, }; case 'FETCH_SUCCESS': return { - ...state, isLoading: false, isError: false, - commentData: action.payload ?? null, }; case 'FETCH_FAILURE': return { - ...state, isLoading: false, isError: true, }; @@ -57,43 +42,45 @@ const dataFetchReducer = (state: NewCommentState, action: Action): NewCommentSta }; interface UsePostComment extends NewCommentState { - postComment: (data: CommentRequest) => void; - resetCommentData: () => void; + postComment: (data: CommentRequest, updateCase: (newCase: Case) => void) => void; } export const usePostComment = (caseId: string): UsePostComment => { const [state, dispatch] = useReducer(dataFetchReducer, { - commentData: null, isLoading: false, isError: false, - caseId, }); const [, dispatchToaster] = useStateToaster(); - const postMyComment = useCallback(async (data: CommentRequest) => { - let cancel = false; - try { - dispatch({ type: 'FETCH_INIT' }); - const response = await postComment(data, state.caseId); - if (!cancel) { - dispatch({ type: 'FETCH_SUCCESS', payload: response }); - } - } catch (error) { - if (!cancel) { - errorToToaster({ - title: i18n.ERROR_TITLE, - error: error.body && error.body.message ? new Error(error.body.message) : error, - dispatchToaster, - }); - dispatch({ type: 'FETCH_FAILURE' }); - } - } - return () => { - cancel = true; - }; - }, []); + const postMyComment = useCallback( + async (data: CommentRequest, updateCase: (newCase: Case) => void) => { + let cancel = false; + const abortCtrl = new AbortController(); - const resetCommentData = useCallback(() => dispatch({ type: 'RESET_COMMENT_DATA' }), []); + try { + dispatch({ type: 'FETCH_INIT' }); + const response = await postComment(data, caseId, abortCtrl.signal); + if (!cancel) { + dispatch({ type: 'FETCH_SUCCESS' }); + updateCase(response); + } + } catch (error) { + if (!cancel) { + errorToToaster({ + title: i18n.ERROR_TITLE, + error: error.body && error.body.message ? new Error(error.body.message) : error, + dispatchToaster, + }); + dispatch({ type: 'FETCH_FAILURE' }); + } + } + return () => { + abortCtrl.abort(); + cancel = true; + }; + }, + [caseId] + ); - return { ...state, postComment: postMyComment, resetCommentData }; + return { ...state, postComment: postMyComment }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx index b6fb15f4fa083..03e10249317ee 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx @@ -87,7 +87,7 @@ export const usePostPushToService = (): UsePostPushToService => { const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT' }); - const casePushData = await getCase(caseId); + const casePushData = await getCase(caseId, true, abortCtrl.signal); const responseService = await pushToService( connectorId, formatServiceRequestData(casePushData), @@ -143,7 +143,6 @@ const formatServiceRequestData = (myCase: Case): ServiceConnectorCaseParams => { updatedAt, updatedBy, } = myCase; - return { caseId, createdAt, @@ -151,23 +150,35 @@ const formatServiceRequestData = (myCase: Case): ServiceConnectorCaseParams => { fullName: createdBy.fullName ?? null, username: createdBy?.username, }, - comments: comments.map(c => ({ - commentId: c.id, - comment: c.comment, - createdAt: c.createdAt, - createdBy: { - fullName: c.createdBy.fullName ?? null, - username: c.createdBy.username, - }, - updatedAt: c.updatedAt, - updatedBy: - c.updatedBy != null - ? { - fullName: c.updatedBy.fullName ?? null, - username: c.updatedBy.username, - } - : null, - })), + comments: comments + .filter(c => { + const lastPush = c.pushedAt != null ? new Date(c.pushedAt) : null; + const lastUpdate = c.updatedAt != null ? new Date(c.updatedAt) : null; + if ( + lastPush === null || + (lastPush != null && lastUpdate != null && lastPush.getTime() < lastUpdate?.getTime()) + ) { + return true; + } + return false; + }) + .map(c => ({ + commentId: c.id, + comment: c.comment, + createdAt: c.createdAt, + createdBy: { + fullName: c.createdBy.fullName ?? null, + username: c.createdBy.username, + }, + updatedAt: c.updatedAt, + updatedBy: + c.updatedBy != null + ? { + fullName: c.updatedBy.fullName ?? null, + username: c.updatedBy.username, + } + : null, + })), description, incidentId: externalService?.externalId ?? null, title, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx index f8af088f7e03b..85ad4fd3fc47a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx @@ -5,18 +5,16 @@ */ import { useReducer, useCallback } from 'react'; -import { cloneDeep } from 'lodash/fp'; -import { CaseRequest } from '../../../../../../plugins/case/common/api'; +import { CasePatchRequest } from '../../../../../../plugins/case/common/api'; import { errorToToaster, useStateToaster } from '../../components/toasters'; import { patchCase } from './api'; import * as i18n from './translations'; import { Case } from './types'; -type UpdateKey = keyof CaseRequest; +type UpdateKey = keyof Pick; interface NewCaseState { - caseData: Case; isLoading: boolean; isError: boolean; updateKey: UpdateKey | null; @@ -24,13 +22,15 @@ interface NewCaseState { export interface UpdateByKey { updateKey: UpdateKey; - updateValue: CaseRequest[UpdateKey]; + updateValue: CasePatchRequest[UpdateKey]; fetchCaseUserActions?: (caseId: string) => void; + updateCase?: (newCase: Case) => void; + version: string; } type Action = | { type: 'FETCH_INIT'; payload: UpdateKey } - | { type: 'FETCH_SUCCESS'; payload: Case } + | { type: 'FETCH_SUCCESS' } | { type: 'FETCH_FAILURE' }; const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => { @@ -48,7 +48,6 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => ...state, isLoading: false, isError: false, - caseData: cloneDeep(action.payload), updateKey: null, }; case 'FETCH_FAILURE': @@ -65,36 +64,36 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => interface UseUpdateCase extends NewCaseState { updateCaseProperty: (updates: UpdateByKey) => void; - updateCase: (newCase: Case) => void; } -export const useUpdateCase = (caseId: string, initialData: Case): UseUpdateCase => { +export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, - caseData: initialData, updateKey: null, }); const [, dispatchToaster] = useStateToaster(); - const updateCase = useCallback((newCase: Case) => { - dispatch({ type: 'FETCH_SUCCESS', payload: newCase }); - }, []); - const dispatchUpdateCaseProperty = useCallback( - async ({ fetchCaseUserActions, updateKey, updateValue }: UpdateByKey) => { + async ({ fetchCaseUserActions, updateKey, updateValue, updateCase, version }: UpdateByKey) => { let cancel = false; + const abortCtrl = new AbortController(); + try { dispatch({ type: 'FETCH_INIT', payload: updateKey }); const response = await patchCase( caseId, { [updateKey]: updateValue }, - state.caseData.version + version, + abortCtrl.signal ); if (!cancel) { if (fetchCaseUserActions != null) { fetchCaseUserActions(caseId); } - dispatch({ type: 'FETCH_SUCCESS', payload: response[0] }); + if (updateCase != null) { + updateCase(response[0]); + } + dispatch({ type: 'FETCH_SUCCESS' }); } } catch (error) { if (!cancel) { @@ -108,10 +107,11 @@ export const useUpdateCase = (caseId: string, initialData: Case): UseUpdateCase } return () => { cancel = true; + abortCtrl.abort(); }; }, - [state] + [] ); - return { ...state, updateCase, updateCaseProperty: dispatchUpdateCaseProperty }; + return { ...state, updateCaseProperty: dispatchUpdateCaseProperty }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx index c1b2bfde30126..faf9649a705c5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx @@ -4,38 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useReducer, useCallback, Dispatch } from 'react'; +import { useReducer, useCallback } from 'react'; import { errorToToaster, useStateToaster } from '../../components/toasters'; import { patchComment } from './api'; import * as i18n from './translations'; -import { Comment } from './types'; +import { Case } from './types'; interface CommentUpdateState { - comments: Comment[]; isLoadingIds: string[]; isError: boolean; } - interface CommentUpdate { - update: Partial; commentId: string; } type Action = - | { type: 'APPEND_COMMENT'; payload: Comment } | { type: 'FETCH_INIT'; payload: string } | { type: 'FETCH_SUCCESS'; payload: CommentUpdate } | { type: 'FETCH_FAILURE'; payload: string }; const dataFetchReducer = (state: CommentUpdateState, action: Action): CommentUpdateState => { switch (action.type) { - case 'APPEND_COMMENT': - return { - ...state, - comments: [...state.comments, action.payload], - }; case 'FETCH_INIT': return { ...state, @@ -44,20 +35,10 @@ const dataFetchReducer = (state: CommentUpdateState, action: Action): CommentUpd }; case 'FETCH_SUCCESS': - const updatePayload = action.payload; - const foundIndex = state.comments.findIndex( - comment => comment.id === updatePayload.commentId - ); - const newComments = state.comments; - if (foundIndex !== -1) { - newComments[foundIndex] = { ...state.comments[foundIndex], ...updatePayload.update }; - } - return { ...state, - isLoadingIds: state.isLoadingIds.filter(id => updatePayload.commentId !== id), + isLoadingIds: state.isLoadingIds.filter(id => action.payload.commentId !== id), isError: false, - comments: newComments, }; case 'FETCH_FAILURE': return { @@ -75,38 +56,45 @@ interface UpdateComment { commentId: string; commentUpdate: string; fetchUserActions: () => void; + updateCase: (newCase: Case) => void; + version: string; } interface UseUpdateComment extends CommentUpdateState { - updateComment: ({ caseId, commentId, commentUpdate, fetchUserActions }: UpdateComment) => void; - addPostedComment: Dispatch; + patchComment: ({ caseId, commentId, commentUpdate, fetchUserActions }: UpdateComment) => void; } -export const useUpdateComment = (comments: Comment[]): UseUpdateComment => { +export const useUpdateComment = (): UseUpdateComment => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoadingIds: [], isError: false, - comments, }); const [, dispatchToaster] = useStateToaster(); const dispatchUpdateComment = useCallback( - async ({ caseId, commentId, commentUpdate, fetchUserActions }: UpdateComment) => { + async ({ + caseId, + commentId, + commentUpdate, + fetchUserActions, + updateCase, + version, + }: UpdateComment) => { let cancel = false; + const abortCtrl = new AbortController(); try { dispatch({ type: 'FETCH_INIT', payload: commentId }); - const currentComment = state.comments.find(comment => comment.id === commentId) ?? { - version: '', - }; const response = await patchComment( caseId, commentId, commentUpdate, - currentComment.version + version, + abortCtrl.signal ); if (!cancel) { + updateCase(response); fetchUserActions(); - dispatch({ type: 'FETCH_SUCCESS', payload: { update: response, commentId } }); + dispatch({ type: 'FETCH_SUCCESS', payload: { commentId } }); } } catch (error) { if (!cancel) { @@ -120,14 +108,11 @@ export const useUpdateComment = (comments: Comment[]): UseUpdateComment => { } return () => { cancel = true; + abortCtrl.abort(); }; }, - [state] - ); - const addPostedComment = useCallback( - (comment: Comment) => dispatch({ type: 'APPEND_COMMENT', payload: comment }), [] ); - return { ...state, updateComment: dispatchUpdateComment, addPostedComment }; + return { ...state, patchComment: dispatchUpdateComment }; }; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/utils.ts b/x-pack/legacy/plugins/siem/public/containers/case/utils.ts index ce23ac6c440b6..1ec98bf5b5f1f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/utils.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/utils.ts @@ -19,8 +19,6 @@ import { CasesStatusResponseRt, CasesStatusResponse, throwErrors, - CommentResponse, - CommentResponseRt, CasesConfigureResponse, CaseConfigureResponseRt, CaseUserActionsResponse, @@ -82,9 +80,6 @@ export const decodeCasesResponse = (respCase?: CasesResponse) => export const decodeCasesFindResponse = (respCases?: CasesFindResponse) => pipe(CasesFindResponseRt.decode(respCases), fold(throwErrors(createToasterPlainError), identity)); -export const decodeCommentResponse = (respComment?: CommentResponse) => - pipe(CommentResponseRt.decode(respComment), fold(throwErrors(createToasterPlainError), identity)); - export const decodeCaseConfigureResponse = (respCase?: CasesConfigureResponse) => pipe( CaseConfigureResponseRt.decode(respCase), diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/__mocks__/api.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/__mocks__/api.ts index 9f37f3fecd508..6c9964af25430 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/__mocks__/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/__mocks__/api.ts @@ -52,6 +52,36 @@ export const getRuleStatusById = async ({ last_success_at: 'mm/dd/yyyyTHH:MM:sssz', last_failure_message: null, last_success_message: 'it is a success', + gap: null, + bulk_create_time_durations: ['2235.01'], + search_after_time_durations: ['616.97'], + last_look_back_date: '2020-03-19T00:32:07.996Z', + }, + failures: [], + }, + }); + +export const getRulesStatusByIds = async ({ + ids, + signal, +}: { + ids: string[]; + signal: AbortSignal; +}): Promise => + Promise.resolve({ + '12345678987654321': { + current_status: { + alert_id: 'alertId', + status_date: 'mm/dd/yyyyTHH:MM:sssz', + status: 'succeeded', + last_failure_at: null, + last_success_at: 'mm/dd/yyyyTHH:MM:sssz', + last_failure_message: null, + last_success_message: 'it is a success', + gap: null, + bulk_create_time_durations: ['2235.01'], + search_after_time_durations: ['616.97'], + last_look_back_date: '2020-03-19T00:32:07.996Z', }, failures: [], }, diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.test.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.test.ts index 8fdc6a67f7d71..e8019659d49c6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.test.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.test.ts @@ -39,7 +39,7 @@ describe('Detections Rules API', () => { await addRule({ rule: ruleMock, signal: abortCtrl.signal }); expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules', { body: - '{"description":"some desc","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"bbd3106e-b4b5-4d7c-a1a2-47531d6a2baf","language":"kuery","risk_score":75,"name":"Test rule","query":"user.email: \'root@elastic.co\'","references":[],"severity":"high","tags":["APM"],"to":"now","type":"query","threat":[]}', + '{"description":"some desc","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"bbd3106e-b4b5-4d7c-a1a2-47531d6a2baf","language":"kuery","risk_score":75,"name":"Test rule","query":"user.email: \'root@elastic.co\'","references":[],"severity":"high","tags":["APM"],"to":"now","type":"query","threat":[],"throttle":null}', method: 'POST', signal: abortCtrl.signal, }); @@ -291,7 +291,7 @@ describe('Detections Rules API', () => { await duplicateRules({ rules: rulesMock.data }); expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_bulk_create', { body: - '[{"description":"Elastic Endpoint detected Credential Dumping. Click the Elastic Endpoint icon in the event.module column or the link in the rule.reference column in the External Alerts tab of the SIEM Detections page for additional information.","enabled":false,"false_positives":[],"from":"now-660s","index":["endgame-*"],"interval":"10m","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":73,"name":"Credential Dumping - Detected - Elastic Endpoint [Duplicate]","query":"event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:detection","filters":[],"references":[],"severity":"high","tags":["Elastic","Endpoint"],"to":"now","type":"query","threat":[],"version":1},{"description":"Elastic Endpoint detected an Adversary Behavior. Click the Elastic Endpoint icon in the event.module column or the link in the rule.reference column in the External Alerts tab of the SIEM Detections page for additional information.","enabled":false,"false_positives":[],"from":"now-660s","index":["endgame-*"],"interval":"10m","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":47,"name":"Adversary Behavior - Detected - Elastic Endpoint [Duplicate]","query":"event.kind:alert and event.module:endgame and event.action:rules_engine_event","filters":[],"references":[],"severity":"medium","tags":["Elastic","Endpoint"],"to":"now","type":"query","threat":[],"version":1}]', + '[{"actions":[],"description":"Elastic Endpoint detected Credential Dumping. Click the Elastic Endpoint icon in the event.module column or the link in the rule.reference column in the External Alerts tab of the SIEM Detections page for additional information.","enabled":false,"false_positives":[],"from":"now-660s","index":["endgame-*"],"interval":"10m","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":73,"name":"Credential Dumping - Detected - Elastic Endpoint [Duplicate]","query":"event.kind:alert and event.module:endgame and event.action:cred_theft_event and endgame.metadata.type:detection","filters":[],"references":[],"severity":"high","tags":["Elastic","Endpoint"],"to":"now","type":"query","threat":[],"throttle":null,"version":1},{"actions":[],"description":"Elastic Endpoint detected an Adversary Behavior. Click the Elastic Endpoint icon in the event.module column or the link in the rule.reference column in the External Alerts tab of the SIEM Detections page for additional information.","enabled":false,"false_positives":[],"from":"now-660s","index":["endgame-*"],"interval":"10m","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":47,"name":"Adversary Behavior - Detected - Elastic Endpoint [Duplicate]","query":"event.kind:alert and event.module:endgame and event.action:rules_engine_event","filters":[],"references":[],"severity":"medium","tags":["Elastic","Endpoint"],"to":"now","type":"query","threat":[],"throttle":null,"version":1}]', method: 'POST', }); }); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts index 126de9762a696..2dd6955581eff 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/api.ts @@ -15,10 +15,10 @@ import { Rule, FetchRuleProps, BasicFetchProps, - ImportRulesProps, + ImportDataProps, ExportDocumentsProps, RuleStatusResponse, - ImportRulesResponse, + ImportDataResponse, PrePackagedRulesStatusResponse, BulkRuleResponse, } from './types'; @@ -204,11 +204,11 @@ export const importRules = async ({ fileToImport, overwrite = false, signal, -}: ImportRulesProps): Promise => { +}: ImportDataProps): Promise => { const formData = new FormData(); formData.append('file', fileToImport); - return KibanaServices.get().http.fetch( + return KibanaServices.get().http.fetch( `${DETECTION_ENGINE_RULES_URL}/_import`, { method: 'POST', @@ -271,6 +271,32 @@ export const getRuleStatusById = async ({ signal, }); +/** + * Return rule statuses given list of alert ids + * + * @param ids array of string of Rule ID's (not rule_id) + * @param signal AbortSignal for cancelling request + * + * @throws An error if response is not OK + */ +export const getRulesStatusByIds = async ({ + ids, + signal, +}: { + ids: string[]; + signal: AbortSignal; +}): Promise => { + const res = await KibanaServices.get().http.fetch( + DETECTION_ENGINE_RULES_STATUS_URL, + { + method: 'GET', + query: { ids: JSON.stringify(ids) }, + signal, + } + ); + return res; +}; + /** * Fetch all unique Tags used by Rules * diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/mock.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/mock.ts index 51526c0ab9949..59782e8a36338 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/mock.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/mock.ts @@ -32,9 +32,11 @@ export const ruleMock: NewRule = { to: 'now', type: 'query', threat: [], + throttle: null, }; export const savedRuleMock: Rule = { + actions: [], created_at: 'mm/dd/yyyyTHH:MM:sssz', created_by: 'mockUser', description: 'some desc', @@ -65,6 +67,7 @@ export const savedRuleMock: Rule = { to: 'now', type: 'query', threat: [], + throttle: null, updated_at: 'mm/dd/yyyyTHH:MM:sssz', updated_by: 'mockUser', }; @@ -75,6 +78,7 @@ export const rulesMock: FetchRulesResponse = { total: 2, data: [ { + actions: [], created_at: '2020-02-14T19:49:28.178Z', updated_at: '2020-02-14T19:49:28.320Z', created_by: 'elastic', @@ -103,9 +107,11 @@ export const rulesMock: FetchRulesResponse = { to: 'now', type: 'query', threat: [], + throttle: null, version: 1, }, { + actions: [], created_at: '2020-02-14T19:49:28.189Z', updated_at: '2020-02-14T19:49:28.326Z', created_by: 'elastic', @@ -133,6 +139,7 @@ export const rulesMock: FetchRulesResponse = { to: 'now', type: 'query', threat: [], + throttle: null, version: 1, }, ], diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts index c75d7b78cf92f..f676ab944fce4 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/types.ts @@ -13,6 +13,19 @@ export const RuleTypeSchema = t.keyof({ }); export type RuleType = t.TypeOf; +/** + * Params is an "record", since it is a type of AlertActionParams which is action templates. + * @see x-pack/plugins/alerting/common/alert.ts + */ +export const action = t.exact( + t.type({ + group: t.string, + id: t.string, + action_type_id: t.string, + params: t.record(t.string, t.any), + }) +); + export const NewRuleSchema = t.intersection([ t.type({ description: t.string, @@ -24,6 +37,7 @@ export const NewRuleSchema = t.intersection([ type: RuleTypeSchema, }), t.partial({ + actions: t.array(action), anomaly_threshold: t.number, created_by: t.string, false_positives: t.array(t.string), @@ -40,6 +54,7 @@ export const NewRuleSchema = t.intersection([ saved_id: t.string, tags: t.array(t.string), threat: t.array(t.unknown), + throttle: t.union([t.string, t.null]), to: t.string, updated_by: t.string, note: t.string, @@ -54,9 +69,15 @@ export interface AddRulesProps { signal: AbortSignal; } -const MetaRule = t.type({ - from: t.string, -}); +const MetaRule = t.intersection([ + t.type({ + from: t.string, + }), + t.partial({ + throttle: t.string, + kibanaSiemAppUrl: t.string, + }), +]); export const RuleSchema = t.intersection([ t.type({ @@ -81,6 +102,8 @@ export const RuleSchema = t.intersection([ threat: t.array(t.unknown), updated_at: t.string, updated_by: t.string, + actions: t.array(action), + throttle: t.union([t.string, t.null]), }), t.partial({ anomaly_threshold: t.number, @@ -171,7 +194,7 @@ export interface BasicFetchProps { signal: AbortSignal; } -export interface ImportRulesProps { +export interface ImportDataProps { fileToImport: File; overwrite?: boolean; signal: AbortSignal; @@ -185,7 +208,7 @@ export interface ImportRulesResponseError { }; } -export interface ImportRulesResponse { +export interface ImportDataResponse { success: boolean; success_count: number; errors: ImportRulesResponseError[]; @@ -212,6 +235,10 @@ export interface RuleInfoStatus { last_success_at: string | null; last_failure_message: string | null; last_success_message: string | null; + last_look_back_date: string | null | undefined; + gap: string | null | undefined; + bulk_create_time_durations: string[] | null | undefined; + search_after_time_durations: string[] | null | undefined; } export type RuleStatusResponse = Record; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule.test.tsx index e0bf2c4907370..ab09f796ad49b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule.test.tsx @@ -31,6 +31,7 @@ describe('useRule', () => { expect(result.current).toEqual([ false, { + actions: [], created_at: 'mm/dd/yyyyTHH:MM:sssz', created_by: 'mockUser', description: 'some desc', @@ -59,6 +60,7 @@ describe('useRule', () => { severity: 'high', tags: ['APM'], threat: [], + throttle: null, to: 'now', type: 'query', updated_at: 'mm/dd/yyyyTHH:MM:sssz', diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.test.tsx index 25011adcfe98b..7269bf1baa5e5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.test.tsx @@ -4,13 +4,74 @@ * you may not use this file except in compliance with the Elastic License. */ -import { renderHook, act } from '@testing-library/react-hooks'; -import { useRuleStatus, ReturnRuleStatus } from './use_rule_status'; +import { renderHook, act, cleanup } from '@testing-library/react-hooks'; +import { + useRuleStatus, + ReturnRuleStatus, + useRulesStatuses, + ReturnRulesStatuses, +} from './use_rule_status'; import * as api from './api'; +import { RuleType, Rule } from '../rules/types'; jest.mock('./api'); +const testRule: Rule = { + actions: [ + { + group: 'fake group', + id: 'fake id', + action_type_id: 'fake action_type_id', + params: { + someKey: 'someVal', + }, + }, + ], + created_at: 'mm/dd/yyyyTHH:MM:sssz', + created_by: 'mockUser', + description: 'some desc', + enabled: true, + false_positives: [], + filters: [], + from: 'now-360s', + id: '12345678987654321', + immutable: false, + index: [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + interval: '5m', + language: 'kuery', + name: 'Test rule', + max_signals: 100, + query: "user.email: 'root@elastic.co'", + references: [], + risk_score: 75, + rule_id: 'bbd3106e-b4b5-4d7c-a1a2-47531d6a2baf', + severity: 'high', + tags: ['APM'], + threat: [], + throttle: null, + to: 'now', + type: 'query' as RuleType, + updated_at: 'mm/dd/yyyyTHH:MM:sssz', + updated_by: 'mockUser', +}; + describe('useRuleStatus', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + }); + afterEach(async () => { + cleanup(); + }); + test('init', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook(() => @@ -39,6 +100,10 @@ describe('useRuleStatus', () => { last_success_message: 'it is a success', status: 'succeeded', status_date: 'mm/dd/yyyyTHH:MM:sssz', + gap: null, + bulk_create_time_durations: ['2235.01'], + search_after_time_durations: ['616.97'], + last_look_back_date: '2020-03-19T00:32:07.996Z', }, failures: [], }, @@ -62,4 +127,50 @@ describe('useRuleStatus', () => { expect(spyOngetRuleStatusById).toHaveBeenCalledTimes(2); }); }); + + test('init rules statuses', async () => { + const payload = [testRule]; + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useRulesStatuses(payload) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ loading: false, rulesStatuses: [] }); + }); + }); + + test('fetch rules statuses', async () => { + const payload = [testRule]; + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useRulesStatuses(payload) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: false, + rulesStatuses: [ + { + current_status: { + alert_id: 'alertId', + bulk_create_time_durations: ['2235.01'], + gap: null, + last_failure_at: null, + last_failure_message: null, + last_look_back_date: '2020-03-19T00:32:07.996Z', + last_success_at: 'mm/dd/yyyyTHH:MM:sssz', + last_success_message: 'it is a success', + search_after_time_durations: ['616.97'], + status: 'succeeded', + status_date: 'mm/dd/yyyyTHH:MM:sssz', + }, + failures: [], + id: '12345678987654321', + activate: true, + name: 'Test rule', + }, + ], + }); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.tsx index 8d06e037e0979..0d37cce1fd85c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rule_status.tsx @@ -7,12 +7,17 @@ import { useEffect, useRef, useState } from 'react'; import { errorToToaster, useStateToaster } from '../../../components/toasters'; -import { getRuleStatusById } from './api'; +import { RuleStatusRowItemType } from '../../../pages/detection_engine/rules/all/columns'; +import { getRuleStatusById, getRulesStatusByIds } from './api'; import * as i18n from './translations'; -import { RuleStatus } from './types'; +import { RuleStatus, Rules } from './types'; type Func = (ruleId: string) => void; export type ReturnRuleStatus = [boolean, RuleStatus | null, Func | null]; +export interface ReturnRulesStatuses { + loading: boolean; + rulesStatuses: RuleStatusRowItemType[] | null; +} /** * Hook for using to get a Rule from the Detection Engine API @@ -33,7 +38,6 @@ export const useRuleStatus = (id: string | undefined | null): ReturnRuleStatus = const fetchData = async (idToFetch: string) => { try { setLoading(true); - const ruleStatusResponse = await getRuleStatusById({ id: idToFetch, signal: abortCtrl.signal, @@ -64,3 +68,58 @@ export const useRuleStatus = (id: string | undefined | null): ReturnRuleStatus = return [loading, ruleStatus, fetchRuleStatus.current]; }; + +/** + * Hook for using to get all the statuses for all given rule ids + * + * @param ids desired Rule ID's (not rule_id) + * + */ +export const useRulesStatuses = (rules: Rules): ReturnRulesStatuses => { + const [rulesStatuses, setRuleStatuses] = useState([]); + const [loading, setLoading] = useState(false); + const [, dispatchToaster] = useStateToaster(); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + const fetchData = async (ids: string[]) => { + try { + setLoading(true); + const ruleStatusesResponse = await getRulesStatusByIds({ + ids, + signal: abortCtrl.signal, + }); + + if (isSubscribed) { + setRuleStatuses( + rules.map(rule => ({ + id: rule.id, + activate: rule.enabled, + name: rule.name, + ...ruleStatusesResponse[rule.id], + })) + ); + } + } catch (error) { + if (isSubscribed) { + setRuleStatuses([]); + errorToToaster({ title: i18n.RULE_FETCH_FAILURE, error, dispatchToaster }); + } + } + if (isSubscribed) { + setLoading(false); + } + }; + if (rules != null && rules.length > 0) { + fetchData(rules.map(r => r.id)); + } + return () => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [rules]); + + return { loading, rulesStatuses }; +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.test.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.test.tsx index 242d715e20f77..5d13b57f862bc 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.test.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/use_rules.test.tsx @@ -58,6 +58,7 @@ describe('useRules', () => { { data: [ { + actions: [], created_at: '2020-02-14T19:49:28.178Z', created_by: 'elastic', description: @@ -82,6 +83,7 @@ describe('useRules', () => { severity: 'high', tags: ['Elastic', 'Endpoint'], threat: [], + throttle: null, to: 'now', type: 'query', updated_at: '2020-02-14T19:49:28.320Z', @@ -89,6 +91,7 @@ describe('useRules', () => { version: 1, }, { + actions: [], created_at: '2020-02-14T19:49:28.189Z', created_by: 'elastic', description: @@ -113,6 +116,7 @@ describe('useRules', () => { severity: 'medium', tags: ['Elastic', 'Endpoint'], threat: [], + throttle: null, to: 'now', type: 'query', updated_at: '2020-02-14T19:49:28.326Z', diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/all/api.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/all/api.ts index edda2e30ea400..4c8e2384de585 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/all/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/all/api.ts @@ -4,9 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ImportDataProps, ImportDataResponse } from '../../detection_engine/rules'; import { KibanaServices } from '../../../lib/kibana'; +import { TIMELINE_IMPORT_URL, TIMELINE_EXPORT_URL } from '../../../../common/constants'; import { ExportSelectedData } from '../../../components/generic_downloader'; -import { TIMELINE_EXPORT_URL } from '../../../../common/constants'; + +export const importTimelines = async ({ + fileToImport, + overwrite = false, + signal, +}: ImportDataProps): Promise => { + const formData = new FormData(); + formData.append('file', fileToImport); + + return KibanaServices.get().http.fetch(`${TIMELINE_IMPORT_URL}`, { + method: 'POST', + headers: { 'Content-Type': undefined }, + query: { overwrite }, + body: formData, + signal, + }); +}; export const exportSelectedTimeline: ExportSelectedData = async ({ excludeExportDetails = false, diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts index c54238c5d8687..53d0b98570bcb 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.gql_query.ts @@ -206,6 +206,7 @@ export const timelineQuery = gql` query to filters + note } } suricata { diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json index 5d43024625d0d..2a9dd8f2aacfe 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json @@ -4696,6 +4696,14 @@ "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "note", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts index a5d1e3fbcba27..e15c099a007ad 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts @@ -1012,6 +1012,8 @@ export interface RuleField { updated_by?: Maybe; version?: Maybe; + + note?: Maybe; } export interface SuricataEcsFields { @@ -4660,6 +4662,8 @@ export namespace GetTimelineQuery { to: Maybe; filters: Maybe; + + note: Maybe; }; export type Suricata = { diff --git a/x-pack/legacy/plugins/siem/public/lib/connectors/servicenow.tsx b/x-pack/legacy/plugins/siem/public/lib/connectors/servicenow.tsx index 8e947fbc0f9bb..d67007399abea 100644 --- a/x-pack/legacy/plugins/siem/public/lib/connectors/servicenow.tsx +++ b/x-pack/legacy/plugins/siem/public/lib/connectors/servicenow.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, ChangeEvent } from 'react'; +import React, { useCallback, ChangeEvent, useEffect } from 'react'; import { EuiFieldText, EuiFlexGroup, @@ -98,6 +98,21 @@ const ServiceNowConnectorFields: React.FunctionComponent 0 && username != null; const isPasswordInvalid: boolean = errors.password.length > 0 && password != null; + /** + * We need to distinguish between the add flyout and the edit flyout. + * useEffect will run only once on component mount. + * This guarantees that the function below will run only once. + * On the first render of the component the apiUrl can be either undefined or filled. + * If it is filled then we are on the edit flyout. Otherwise we are on the add flyout. + */ + + useEffect(() => { + if (!isEmpty(apiUrl)) { + editActionSecrets('username', ''); + editActionSecrets('password', ''); + } + }, []); + if (isEmpty(mapping)) { editActionConfig('casesConfiguration', { ...action.config.casesConfiguration, @@ -169,7 +184,7 @@ const ServiceNowConnectorFields: React.FunctionComponent diff --git a/x-pack/legacy/plugins/siem/public/mock/index.ts b/x-pack/legacy/plugins/siem/public/mock/index.ts index dbf5f2e55e713..bdad0ab1712ab 100644 --- a/x-pack/legacy/plugins/siem/public/mock/index.ts +++ b/x-pack/legacy/plugins/siem/public/mock/index.ts @@ -13,3 +13,5 @@ export * from './mock_detail_item'; export * from './netflow'; export * from './test_providers'; export * from './utils'; +export * from './mock_ecs'; +export * from './timeline_results'; diff --git a/x-pack/legacy/plugins/siem/public/mock/mock_ecs.ts b/x-pack/legacy/plugins/siem/public/mock/mock_ecs.ts index 5d32d95804e69..59e26039e6bff 100644 --- a/x-pack/legacy/plugins/siem/public/mock/mock_ecs.ts +++ b/x-pack/legacy/plugins/siem/public/mock/mock_ecs.ts @@ -1280,3 +1280,69 @@ export const mockEcsData: Ecs[] = [ zeek: null, }, ]; + +export const mockEcsDataWithSignal: Ecs = { + _id: '1', + timestamp: '2018-11-05T19:03:25.937Z', + host: { + name: ['apache'], + ip: ['192.168.0.1'], + }, + event: { + id: ['1'], + action: ['Action'], + category: ['Access'], + module: ['nginx'], + severity: [3], + }, + source: { + ip: ['192.168.0.1'], + port: [80], + }, + destination: { + ip: ['192.168.0.3'], + port: [6343], + }, + user: { + id: ['1'], + name: ['john.dee'], + }, + geo: { + region_name: ['xx'], + country_iso_code: ['xx'], + }, + signal: { + rule: { + created_at: ['2020-01-10T21:11:45.839Z'], + updated_at: ['2020-01-10T21:11:45.839Z'], + created_by: ['elastic'], + description: ['24/7'], + enabled: [true], + false_positives: ['test-1'], + filters: [], + from: ['now-300s'], + id: ['b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea'], + immutable: [false], + index: ['auditbeat-*'], + interval: ['5m'], + rule_id: ['rule-id-1'], + language: ['kuery'], + output_index: ['.siem-signals-default'], + max_signals: [100], + risk_score: ['21'], + query: ['user.name: root or user.name: admin'], + references: ['www.test.co'], + saved_id: ["Garrett's IP"], + timeline_id: ['1234-2136-11ea-9864-ebc8cc1cb8c2'], + timeline_title: ['Untitled timeline'], + severity: ['low'], + updated_by: ['elastic'], + tags: [], + to: ['now'], + type: ['saved_query'], + threat: [], + note: ['# this is some markdown documentation'], + version: ['1'], + }, + }, +}; diff --git a/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts b/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts index d6dc0ae131391..363281e563317 100644 --- a/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts +++ b/x-pack/legacy/plugins/siem/public/mock/timeline_results.ts @@ -7,7 +7,10 @@ import { OpenTimelineResult } from '../components/open_timeline/types'; import { GetAllTimeline, SortFieldTimeline, TimelineResult, Direction } from '../graphql/types'; import { allTimelinesQuery } from '../containers/timeline/all/index.gql_query'; - +import { CreateTimelineProps } from '../pages/detection_engine/components/signals/types'; +import { TimelineModel } from '../store/timeline/model'; +import { timelineDefaults } from '../store/timeline/defaults'; +import { FilterStateStore } from '../../../../../../src/plugins/data/common/es_query/filters/meta_filter'; export interface MockedProvidedQuery { request: { query: GetAllTimeline.Query; @@ -2006,3 +2009,196 @@ export const mockTimelineResults: OpenTimelineResult[] = [ updatedBy: 'karen', }, ]; + +export const mockTimelineModel: TimelineModel = { + columns: [ + { + columnHeaderType: 'not-filtered', + id: '@timestamp', + width: 190, + }, + { + columnHeaderType: 'not-filtered', + id: 'message', + width: 180, + }, + { + columnHeaderType: 'not-filtered', + id: 'event.category', + width: 180, + }, + { + columnHeaderType: 'not-filtered', + id: 'host.name', + width: 180, + }, + { + columnHeaderType: 'not-filtered', + id: 'source.ip', + width: 180, + }, + { + columnHeaderType: 'not-filtered', + id: 'destination.ip', + width: 180, + }, + { + columnHeaderType: 'not-filtered', + id: 'user.name', + width: 180, + }, + ], + dataProviders: [], + dateRange: { + end: 1584539558929, + start: 1584539198929, + }, + deletedEventIds: [], + description: 'This is a sample rule description', + eventIdToNoteIds: {}, + eventType: 'all', + filters: [ + { + $state: { + store: FilterStateStore.APP_STATE, + }, + meta: { + alias: null, + disabled: true, + key: 'host.name', + negate: false, + params: '"{"query":"placeholder"}"', + type: 'phrase', + }, + query: '"{"match_phrase":{"host.name":"placeholder"}}"', + }, + ], + highlightedDropAndProviderId: '', + historyIds: [], + id: 'ef579e40-jibber-jabber', + isFavorite: false, + isLive: false, + isLoading: false, + isSaving: false, + isSelectAllChecked: false, + kqlMode: 'filter', + kqlQuery: { + filterQuery: null, + filterQueryDraft: null, + }, + itemsPerPage: 25, + itemsPerPageOptions: [10, 25, 50, 100], + loadingEventIds: [], + noteIds: [], + pinnedEventIds: {}, + pinnedEventsSaveObject: {}, + savedObjectId: 'ef579e40-jibber-jabber', + selectedEventIds: {}, + show: false, + showCheckboxes: false, + showRowRenderers: true, + sort: { + columnId: '@timestamp', + sortDirection: Direction.desc, + }, + title: 'Test rule', + version: '1', + width: 1100, +}; + +export const mockTimelineResult: TimelineResult = { + savedObjectId: 'ef579e40-jibber-jabber', + columns: timelineDefaults.columns.filter(column => column.id !== 'event.action'), + dateRange: { start: 1584539198929, end: 1584539558929 }, + description: 'This is a sample rule description', + eventType: 'all', + filters: [ + { + meta: { + key: 'host.name', + negate: false, + params: '"{"query":"placeholder"}"', + type: 'phrase', + }, + query: '"{"match_phrase":{"host.name":"placeholder"}}"', + }, + ], + kqlMode: 'filter', + title: 'Test rule', + savedQueryId: null, + sort: { columnId: '@timestamp', sortDirection: 'desc' }, + version: '1', +}; + +export const mockTimelineApolloResult = { + data: { + getOneTimeline: mockTimelineResult, + }, + loading: false, + networkStatus: 7, + stale: false, +}; + +export const defaultTimelineProps: CreateTimelineProps = { + from: 1541444305937, + timeline: { + columns: [ + { columnHeaderType: 'not-filtered', id: '@timestamp', width: 190 }, + { columnHeaderType: 'not-filtered', id: 'message', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'event.category', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'event.action', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'host.name', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'source.ip', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'destination.ip', width: 180 }, + { columnHeaderType: 'not-filtered', id: 'user.name', width: 180 }, + ], + dataProviders: [ + { + and: [], + enabled: true, + excluded: false, + id: + 'send-signal-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-signal-id-1', + kqlQuery: '', + name: '1', + queryMatch: { field: '_id', operator: ':', value: '1' }, + }, + ], + dateRange: { end: 1541444605937, start: 1541444305937 }, + deletedEventIds: [], + description: '', + eventIdToNoteIds: {}, + eventType: 'all', + filters: [], + highlightedDropAndProviderId: '', + historyIds: [], + id: 'timeline-1', + isFavorite: false, + isLive: false, + isLoading: false, + isSaving: false, + isSelectAllChecked: false, + itemsPerPage: 25, + itemsPerPageOptions: [10, 25, 50, 100], + kqlMode: 'filter', + kqlQuery: { + filterQuery: { kuery: { expression: '', kind: 'kuery' }, serializedQuery: '' }, + filterQueryDraft: { expression: '', kind: 'kuery' }, + }, + loadingEventIds: [], + noteIds: [], + pinnedEventIds: {}, + pinnedEventsSaveObject: {}, + savedObjectId: null, + selectedEventIds: {}, + show: false, + showCheckboxes: false, + showRowRenderers: true, + sort: { columnId: '@timestamp', sortDirection: Direction.desc }, + title: '', + version: null, + width: 1100, + }, + to: 1541444605937, + ruleNote: '# this is some markdown documentation', +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx index 836595c7c45d9..46a777984c6e0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx @@ -10,13 +10,14 @@ import styled from 'styled-components'; import { CommentRequest } from '../../../../../../../../plugins/case/common/api'; import { usePostComment } from '../../../../containers/case/use_post_comment'; +import { Case } from '../../../../containers/case/types'; import { MarkdownEditorForm } from '../../../../components/markdown_editor/form'; +import { InsertTimelinePopover } from '../../../../components/timeline/insert_timeline_popover'; +import { useInsertTimeline } from '../../../../components/timeline/insert_timeline_popover/use_insert_timeline'; import { Form, useForm, UseField } from '../../../../shared_imports'; + import * as i18n from '../../translations'; import { schema } from './schema'; -import { InsertTimelinePopover } from '../../../../components/timeline/insert_timeline_popover'; -import { useInsertTimeline } from '../../../../components/timeline/insert_timeline_popover/use_insert_timeline'; -import { Comment } from '../../../../containers/case/types'; const MySpinner = styled(EuiLoadingSpinner)` position: absolute; @@ -30,14 +31,15 @@ const initialCommentValue: CommentRequest = { interface AddCommentProps { caseId: string; + insertQuote: string | null; onCommentSaving?: () => void; - onCommentPosted: (commentResponse: Comment) => void; + onCommentPosted: (newCase: Case) => void; showLoading?: boolean; } export const AddComment = React.memo( - ({ caseId, showLoading = true, onCommentPosted, onCommentSaving }) => { - const { commentData, isLoading, postComment, resetCommentData } = usePostComment(caseId); + ({ caseId, insertQuote, showLoading = true, onCommentPosted, onCommentSaving }) => { + const { isLoading, postComment } = usePostComment(caseId); const { form } = useForm({ defaultValue: initialCommentValue, options: { stripEmptyFields: false }, @@ -49,12 +51,14 @@ export const AddComment = React.memo( ); useEffect(() => { - if (commentData !== null) { - onCommentPosted(commentData); - form.reset(); - resetCommentData(); + if (insertQuote !== null) { + const { comment } = form.getFormData(); + form.setFieldValue( + 'comment', + `${comment}${comment.length > 0 ? '\n\n' : ''}${insertQuote}` + ); } - }, [commentData]); + }, [insertQuote]); const onSubmit = useCallback(async () => { const { isValid, data } = await form.submit(); @@ -62,12 +66,13 @@ export const AddComment = React.memo( if (onCommentSaving != null) { onCommentSaving(); } - await postComment(data); + await postComment(data, onCommentPosted); + form.reset(); } - }, [form]); + }, [form, onCommentPosted, onCommentSaving]); return ( - <> + {isLoading && showLoading && }
( }} /> - +
); } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx index 32a29483e9c75..7c61d7eb034dc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx @@ -3,13 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { EuiBadge, EuiTableFieldDataColumnType, EuiTableComputedColumnType, EuiTableActionsColumnType, EuiAvatar, + EuiLink, } from '@elastic/eui'; import styled from 'styled-components'; import { DefaultItemIconButtonAction } from '@elastic/eui/src/components/basic_table/action_types'; @@ -60,7 +61,6 @@ export const getCasesColumns = ( } return getEmptyTagValue(); }, - width: '25%', }, { field: 'createdBy', @@ -105,7 +105,6 @@ export const getCasesColumns = ( return getEmptyTagValue(); }, truncateText: true, - width: '20%', }, { align: 'right', @@ -148,8 +147,52 @@ export const getCasesColumns = ( return getEmptyTagValue(); }, }, + { + name: 'ServiceNow Incident', + render: (theCase: Case) => { + if (theCase.id != null) { + return ; + } + return getEmptyTagValue(); + }, + }, { name: 'Actions', actions, }, ]; + +interface Props { + theCase: Case; +} + +const ServiceNowColumn: React.FC = ({ theCase }) => { + const handleRenderDataToPush = useCallback(() => { + const lastCaseUpdate = theCase.updatedAt != null ? new Date(theCase.updatedAt) : null; + const lastCasePush = + theCase.externalService?.pushedAt != null + ? new Date(theCase.externalService?.pushedAt) + : null; + const hasDataToPush = + lastCasePush === null || + (lastCasePush != null && + lastCaseUpdate != null && + lastCasePush.getTime() < lastCaseUpdate?.getTime()); + return ( +

+ + {theCase.externalService?.externalTitle} + + {hasDataToPush ? i18n.REQUIRES_UPDATE : i18n.UP_TO_DATE} +

+ ); + }, [theCase]); + if (theCase.externalService !== null) { + return handleRenderDataToPush(); + } + return renderStringField(i18n.NOT_PUSHED, `case-table-column-external-notPushed`); +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx index cbb9ddae22d04..27316ab8427cb 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx @@ -109,19 +109,21 @@ export const AllCases = React.memo(() => { const { dispatchResetIsUpdated, isUpdated, updateBulkStatus } = useUpdateCases(); + const refreshCases = useCallback(() => { + refetchCases(filterOptions, queryParams); + fetchCasesStatus(); + }, [filterOptions, queryParams]); + useEffect(() => { if (isDeleted) { - refetchCases(filterOptions, queryParams); - fetchCasesStatus(); + refreshCases(); dispatchResetIsDeleted(); } if (isUpdated) { - refetchCases(filterOptions, queryParams); - fetchCasesStatus(); + refreshCases(); dispatchResetIsUpdated(); } - }, [isDeleted, isUpdated, filterOptions, queryParams]); - + }, [isDeleted, isUpdated]); const [deleteThisCase, setDeleteThisCase] = useState({ title: '', id: '', @@ -327,6 +329,10 @@ export const AllCases = React.memo(() => { > {i18n.BULK_ACTIONS} + + + {i18n.REFRESH} + diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts index b18134f6d093e..e8459454576e3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts @@ -62,3 +62,17 @@ export const CLOSED = i18n.translate('xpack.siem.case.caseTable.closed', { export const DELETE = i18n.translate('xpack.siem.case.caseTable.delete', { defaultMessage: 'Delete', }); +export const REQUIRES_UPDATE = i18n.translate('xpack.siem.case.caseTable.requiresUpdate', { + defaultMessage: ' requires update', +}); + +export const UP_TO_DATE = i18n.translate('xpack.siem.case.caseTable.upToDate', { + defaultMessage: ' is up to date', +}); +export const NOT_PUSHED = i18n.translate('xpack.siem.case.caseTable.notPushed', { + defaultMessage: 'Not pushed', +}); + +export const REFRESH = i18n.translate('xpack.siem.case.caseTable.refreshTitle', { + defaultMessage: 'Refresh', +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx index 0420a71fea907..5037987845326 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx @@ -8,6 +8,7 @@ import React from 'react'; import styled, { css } from 'styled-components'; import { EuiBadge, + EuiButtonEmpty, EuiButtonToggle, EuiDescriptionList, EuiDescriptionListDescription, @@ -18,6 +19,7 @@ import { import * as i18n from '../case_view/translations'; import { FormattedRelativePreferenceDate } from '../../../../components/formatted_date'; import { CaseViewActions } from '../case_view/actions'; +import { Case } from '../../../../containers/case/types'; const MyDescriptionList = styled(EuiDescriptionList)` ${({ theme }) => css` @@ -32,11 +34,11 @@ interface CaseStatusProps { 'data-test-subj': string; badgeColor: string; buttonLabel: string; - caseId: string; - caseTitle: string; + caseData: Case; icon: string; isLoading: boolean; isSelected: boolean; + onRefresh: () => void; status: string; title: string; toggleStatusCase: (evt: unknown) => void; @@ -46,11 +48,11 @@ const CaseStatusComp: React.FC = ({ 'data-test-subj': dataTestSubj, badgeColor, buttonLabel, - caseId, - caseTitle, + caseData, icon, isLoading, isSelected, + onRefresh, status, title, toggleStatusCase, @@ -79,6 +81,11 @@ const CaseStatusComp: React.FC = ({
+ + + {i18n.CASE_REFRESH} + + = ({ /> - + diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx index 7aadea1a453a7..c4f1888df39e9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx @@ -7,9 +7,12 @@ import { CaseProps } from '../index'; import { Case } from '../../../../../containers/case/types'; +const updateCase = jest.fn(); +const fetchCase = jest.fn(); + export const caseProps: CaseProps = { caseId: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', - initialData: { + caseData: { closedAt: null, closedBy: null, id: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', @@ -46,12 +49,14 @@ export const caseProps: CaseProps = { }, version: 'WzQ3LDFd', }, + fetchCase, + updateCase, }; export const caseClosedProps: CaseProps = { ...caseProps, - initialData: { - ...caseProps.initialData, + caseData: { + ...caseProps.caseData, closedAt: '2020-02-20T23:06:33.798Z', closedBy: { username: 'elastic', @@ -61,11 +66,11 @@ export const caseClosedProps: CaseProps = { }; export const data: Case = { - ...caseProps.initialData, + ...caseProps.caseData, }; export const dataClosed: Case = { - ...caseClosedProps.initialData, + ...caseClosedProps.caseData, }; export const caseUserActions = [ diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx index 4e1e5ba753c36..1be0d6a3b5fcc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx @@ -6,15 +6,15 @@ import React from 'react'; import { mount } from 'enzyme'; -import { CaseViewActions } from './actions'; -import { TestProviders } from '../../../../mock'; + import { useDeleteCases } from '../../../../containers/case/use_delete_cases'; +import { TestProviders } from '../../../../mock'; +import { data } from './__mock__'; +import { CaseViewActions } from './actions'; jest.mock('../../../../containers/case/use_delete_cases'); const useDeleteCasesMock = useDeleteCases as jest.Mock; describe('CaseView actions', () => { - const caseTitle = 'Cool title'; - const caseId = 'cool-id'; const handleOnDeleteConfirm = jest.fn(); const handleToggleModal = jest.fn(); const dispatchResetIsDeleted = jest.fn(); @@ -34,7 +34,7 @@ describe('CaseView actions', () => { it('clicking trash toggles modal', () => { const wrapper = mount( - + ); @@ -54,12 +54,12 @@ describe('CaseView actions', () => { })); const wrapper = mount( - + ); expect(wrapper.find('[data-test-subj="confirm-delete-case-modal"]').exists()).toBeTruthy(); wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([caseId]); + expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([data.id]); }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx index 88a717ac5fa6a..1d90470eab0e1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx @@ -12,13 +12,13 @@ import { useDeleteCases } from '../../../../containers/case/use_delete_cases'; import { ConfirmDeleteCaseModal } from '../confirm_delete_case'; import { SiemPageName } from '../../../home/types'; import { PropertyActions } from '../property_actions'; +import { Case } from '../../../../containers/case/types'; interface CaseViewActions { - caseId: string; - caseTitle: string; + caseData: Case; } -const CaseViewActionsComponent: React.FC = ({ caseId, caseTitle }) => { +const CaseViewActionsComponent: React.FC = ({ caseData }) => { // Delete case const { handleToggleModal, @@ -30,14 +30,14 @@ const CaseViewActionsComponent: React.FC = ({ caseId, caseTitle const confirmDeleteModal = useMemo( () => ( ), - [isDisplayConfirmDeleteModal] + [isDisplayConfirmDeleteModal, caseData] ); // TO DO refactor each of these const's into their own components const propertyActions = useMemo( @@ -47,18 +47,17 @@ const CaseViewActionsComponent: React.FC = ({ caseId, caseTitle label: i18n.DELETE_CASE, onClick: handleToggleModal, }, - { - iconType: 'popout', - label: 'View ServiceNow incident', - onClick: () => null, - }, - { - iconType: 'importAction', - label: 'Update ServiceNow incident', - onClick: () => null, - }, + ...(caseData.externalService?.externalUrl !== null + ? [ + { + iconType: 'popout', + label: i18n.VIEW_INCIDENT(caseData.externalService?.externalTitle ?? ''), + onClick: () => window.open(caseData.externalService?.externalUrl, '_blank'), + }, + ] + : []), ], - [handleToggleModal] + [handleToggleModal, caseData] ); if (isDeleted) { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx index 18cc33d8a6d4d..92fc43eff53e9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx @@ -67,7 +67,6 @@ describe('CaseView ', () => { /* eslint-enable no-console */ const defaultUpdateCaseState = { - caseData: data, isLoading: false, isError: false, updateKey: null, @@ -186,12 +185,7 @@ describe('CaseView ', () => { wrapper .find('input[data-test-subj="toggle-case-status"]') .simulate('change', { target: { checked: true } }); - - expect(updateCaseProperty).toBeCalledWith({ - fetchCaseUserActions, - updateKey: 'status', - updateValue: 'closed', - }); + expect(updateCaseProperty).toHaveBeenCalled(); }); it('should render comments', async () => { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx index 5c20b53f5fcb9..07834c3fb0678 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx @@ -57,230 +57,252 @@ const MyEuiHorizontalRule = styled(EuiHorizontalRule)` export interface CaseProps { caseId: string; - initialData: Case; + fetchCase: () => void; + caseData: Case; + updateCase: (newCase: Case) => void; } -export const CaseComponent = React.memo(({ caseId, initialData }) => { - const basePath = window.location.origin + useBasePath(); - const caseLink = `${basePath}/app/siem#/case/${caseId}`; - const search = useGetUrlSearch(navTabs.case); +export const CaseComponent = React.memo( + ({ caseId, caseData, fetchCase, updateCase }) => { + const basePath = window.location.origin + useBasePath(); + const caseLink = `${basePath}/app/siem#/case/${caseId}`; + const search = useGetUrlSearch(navTabs.case); - const [initLoadingData, setInitLoadingData] = useState(true); - const { - caseUserActions, - fetchCaseUserActions, - firstIndexPushToService, - hasDataToPush, - isLoading: isLoadingUserActions, - lastIndexPushToService, - participants, - } = useGetCaseUserActions(caseId); - const { caseData, isLoading, updateKey, updateCase, updateCaseProperty } = useUpdateCase( - caseId, - initialData - ); + const [initLoadingData, setInitLoadingData] = useState(true); + const { + caseUserActions, + fetchCaseUserActions, + firstIndexPushToService, + hasDataToPush, + isLoading: isLoadingUserActions, + lastIndexPushToService, + participants, + } = useGetCaseUserActions(caseId); + const { isLoading, updateKey, updateCaseProperty } = useUpdateCase({ + caseId, + }); - // Update Fields - const onUpdateField = useCallback( - (newUpdateKey: keyof Case, updateValue: Case[keyof Case]) => { - switch (newUpdateKey) { - case 'title': - const titleUpdate = getTypedPayload(updateValue); - if (titleUpdate.length > 0) { - updateCaseProperty({ - fetchCaseUserActions, - updateKey: 'title', - updateValue: titleUpdate, - }); - } - break; - case 'description': - const descriptionUpdate = getTypedPayload(updateValue); - if (descriptionUpdate.length > 0) { + // Update Fields + const onUpdateField = useCallback( + (newUpdateKey: keyof Case, updateValue: Case[keyof Case]) => { + const handleUpdateNewCase = (newCase: Case) => + updateCase({ ...newCase, comments: caseData.comments }); + switch (newUpdateKey) { + case 'title': + const titleUpdate = getTypedPayload(updateValue); + if (titleUpdate.length > 0) { + updateCaseProperty({ + fetchCaseUserActions, + updateKey: 'title', + updateValue: titleUpdate, + updateCase: handleUpdateNewCase, + version: caseData.version, + }); + } + break; + case 'description': + const descriptionUpdate = getTypedPayload(updateValue); + if (descriptionUpdate.length > 0) { + updateCaseProperty({ + fetchCaseUserActions, + updateKey: 'description', + updateValue: descriptionUpdate, + updateCase: handleUpdateNewCase, + version: caseData.version, + }); + } + break; + case 'tags': + const tagsUpdate = getTypedPayload(updateValue); updateCaseProperty({ fetchCaseUserActions, - updateKey: 'description', - updateValue: descriptionUpdate, + updateKey: 'tags', + updateValue: tagsUpdate, + updateCase: handleUpdateNewCase, + version: caseData.version, }); - } - break; - case 'tags': - const tagsUpdate = getTypedPayload(updateValue); - updateCaseProperty({ - fetchCaseUserActions, - updateKey: 'tags', - updateValue: tagsUpdate, - }); - break; - case 'status': - const statusUpdate = getTypedPayload(updateValue); - if (caseData.status !== updateValue) { - updateCaseProperty({ - fetchCaseUserActions, - updateKey: 'status', - updateValue: statusUpdate, - }); - } - default: - return null; - } - }, - [fetchCaseUserActions, updateCaseProperty, caseData.status] - ); - const handleUpdateCase = useCallback( - (newCase: Case) => { - updateCase(newCase); - fetchCaseUserActions(newCase.id); - }, - [updateCase, fetchCaseUserActions] - ); + break; + case 'status': + const statusUpdate = getTypedPayload(updateValue); + if (caseData.status !== updateValue) { + updateCaseProperty({ + fetchCaseUserActions, + updateKey: 'status', + updateValue: statusUpdate, + updateCase: handleUpdateNewCase, + version: caseData.version, + }); + } + default: + return null; + } + }, + [fetchCaseUserActions, updateCaseProperty, updateCase, caseData] + ); + const handleUpdateCase = useCallback( + (newCase: Case) => { + updateCase(newCase); + fetchCaseUserActions(newCase.id); + }, + [updateCase, fetchCaseUserActions] + ); - const { pushButton, pushCallouts } = usePushToService({ - caseId: caseData.id, - caseStatus: caseData.status, - isNew: caseUserActions.filter(cua => cua.action === 'push-to-service').length === 0, - updateCase: handleUpdateCase, - }); + const { pushButton, pushCallouts } = usePushToService({ + caseId: caseData.id, + caseStatus: caseData.status, + isNew: caseUserActions.filter(cua => cua.action === 'push-to-service').length === 0, + updateCase: handleUpdateCase, + }); - const onSubmitTags = useCallback(newTags => onUpdateField('tags', newTags), [onUpdateField]); - const onSubmitTitle = useCallback(newTitle => onUpdateField('title', newTitle), [onUpdateField]); - const toggleStatusCase = useCallback( - e => onUpdateField('status', e.target.checked ? 'closed' : 'open'), - [onUpdateField] - ); - const spyState = useMemo(() => ({ caseTitle: caseData.title }), [caseData.title]); + const onSubmitTags = useCallback(newTags => onUpdateField('tags', newTags), [onUpdateField]); + const onSubmitTitle = useCallback(newTitle => onUpdateField('title', newTitle), [ + onUpdateField, + ]); + const toggleStatusCase = useCallback( + e => onUpdateField('status', e.target.checked ? 'closed' : 'open'), + [onUpdateField] + ); + const handleRefresh = useCallback(() => { + fetchCaseUserActions(caseData.id); + fetchCase(); + }, [caseData.id, fetchCase, fetchCaseUserActions]); - const caseStatusData = useMemo( - () => - caseData.status === 'open' - ? { - 'data-test-subj': 'case-view-createdAt', - value: caseData.createdAt, - title: i18n.CASE_OPENED, - buttonLabel: i18n.CLOSE_CASE, - status: caseData.status, - icon: 'folderCheck', - badgeColor: 'secondary', - isSelected: false, - } - : { - 'data-test-subj': 'case-view-closedAt', - value: caseData.closedAt ?? '', - title: i18n.CASE_CLOSED, - buttonLabel: i18n.REOPEN_CASE, - status: caseData.status, - icon: 'folderExclamation', - badgeColor: 'danger', - isSelected: true, - }, - [caseData.closedAt, caseData.createdAt, caseData.status] - ); - const emailContent = useMemo( - () => ({ - subject: i18n.EMAIL_SUBJECT(caseData.title), - body: i18n.EMAIL_BODY(caseLink), - }), - [caseLink, caseData.title] - ); + const spyState = useMemo(() => ({ caseTitle: caseData.title }), [caseData.title]); - useEffect(() => { - if (initLoadingData && !isLoadingUserActions) { - setInitLoadingData(false); - } - }, [initLoadingData, isLoadingUserActions]); + const caseStatusData = useMemo( + () => + caseData.status === 'open' + ? { + 'data-test-subj': 'case-view-createdAt', + value: caseData.createdAt, + title: i18n.CASE_OPENED, + buttonLabel: i18n.CLOSE_CASE, + status: caseData.status, + icon: 'folderCheck', + badgeColor: 'secondary', + isSelected: false, + } + : { + 'data-test-subj': 'case-view-closedAt', + value: caseData.closedAt ?? '', + title: i18n.CASE_CLOSED, + buttonLabel: i18n.REOPEN_CASE, + status: caseData.status, + icon: 'folderExclamation', + badgeColor: 'danger', + isSelected: true, + }, + [caseData.closedAt, caseData.createdAt, caseData.status] + ); + const emailContent = useMemo( + () => ({ + subject: i18n.EMAIL_SUBJECT(caseData.title), + body: i18n.EMAIL_BODY(caseLink), + }), + [caseLink, caseData.title] + ); - return ( - <> - - - } - title={caseData.title} - > - - - - + useEffect(() => { + if (initLoadingData && !isLoadingUserActions) { + setInitLoadingData(false); + } + }, [initLoadingData, isLoadingUserActions]); + + return ( + <> - {pushCallouts != null && pushCallouts} - - - {initLoadingData && } - {!initLoadingData && ( - <> - - - - - - - {hasDataToPush && {pushButton}} - - - )} - - - - - - - + } + title={caseData.title} + > + + - - - - ); -}); + + + {pushCallouts != null && pushCallouts} + + + {initLoadingData && } + {!initLoadingData && ( + <> + + + + + + + {hasDataToPush && {pushButton}} + + + )} + + + + + + + + + + + + ); + } +); export const CaseView = React.memo(({ caseId }: Props) => { - const { data, isLoading, isError } = useGetCase(caseId); + const { data, isLoading, isError, fetchCase, updateCase } = useGetCase(caseId); if (isError) { return null; } @@ -294,7 +316,9 @@ export const CaseView = React.memo(({ caseId }: Props) => { ); } - return ; + return ( + + ); }); CaseComponent.displayName = 'CaseComponent'; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts index beba80ccd934c..3fc963fc23102 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts @@ -34,6 +34,14 @@ export const REMOVED_FIELD = i18n.translate('xpack.siem.case.caseView.actionLabe defaultMessage: 'removed', }); +export const VIEW_INCIDENT = (incidentNumber: string) => + i18n.translate('xpack.siem.case.caseView.actionLabel.viewIncident', { + defaultMessage: 'View {incidentNumber}', + values: { + incidentNumber, + }, + }); + export const PUSHED_NEW_INCIDENT = i18n.translate( 'xpack.siem.case.caseView.actionLabel.pushedNewIncident', { @@ -59,6 +67,10 @@ export const EDIT_DESCRIPTION = i18n.translate('xpack.siem.case.caseView.edit.de defaultMessage: 'Edit description', }); +export const QUOTE = i18n.translate('xpack.siem.case.caseView.edit.quote', { + defaultMessage: 'Quote', +}); + export const EDIT_COMMENT = i18n.translate('xpack.siem.case.caseView.edit.comment', { defaultMessage: 'Edit comment', }); @@ -91,6 +103,10 @@ export const CASE_CLOSED = i18n.translate('xpack.siem.case.caseView.caseClosed', defaultMessage: 'Case closed', }); +export const CASE_REFRESH = i18n.translate('xpack.siem.case.caseView.caseRefresh', { + defaultMessage: 'Refresh case', +}); + export const EMAIL_SUBJECT = (caseTitle: string) => i18n.translate('xpack.siem.case.caseView.emailSubject', { values: { caseTitle }, diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/index.tsx index 5f99ec362cd5e..a1f24275df6cd 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/index.tsx @@ -4,7 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useReducer, useCallback, useEffect, useState } from 'react'; +import React, { + useReducer, + useCallback, + useEffect, + useState, + Dispatch, + SetStateAction, +} from 'react'; import styled, { css } from 'styled-components'; import { @@ -14,8 +21,9 @@ import { EuiCallOut, EuiBottomBar, EuiButtonEmpty, + EuiText, } from '@elastic/eui'; -import { isEmpty } from 'lodash/fp'; +import { isEmpty, difference } from 'lodash/fp'; import { useKibana } from '../../../../lib/kibana'; import { useConnectors } from '../../../../containers/case/configure/use_connectors'; import { useCaseConfigure } from '../../../../containers/case/configure/use_configure'; @@ -40,7 +48,7 @@ import { ClosureOptions } from '../configure_cases/closure_options'; import { Mapping } from '../configure_cases/mapping'; import { SectionWrapper } from '../wrappers'; import { navTabs } from '../../../../pages/home/home_navigations'; -import { configureCasesReducer, State } from './reducer'; +import { configureCasesReducer, State, CurrentConfiguration } from './reducer'; import * as i18n from './translations'; const FormWrapper = styled.div` @@ -58,6 +66,7 @@ const initialState: State = { connectorId: 'none', closureType: 'close-by-user', mapping: null, + currentConfiguration: { connectorId: 'none', closureType: 'close-by-user' }, }; const actionTypes: ActionType[] = [ @@ -83,14 +92,20 @@ const ConfigureCasesComponent: React.FC = () => { ); const [actionBarVisible, setActionBarVisible] = useState(false); + const [totalConfigurationChanges, setTotalConfigurationChanges] = useState(0); - const handleShowAddFlyout = useCallback(() => setAddFlyoutVisibility(true), []); - - const [{ connectorId, closureType, mapping }, dispatch] = useReducer( + const [{ connectorId, closureType, mapping, currentConfiguration }, dispatch] = useReducer( configureCasesReducer(), initialState ); + const setCurrentConfiguration = useCallback((configuration: CurrentConfiguration) => { + dispatch({ + type: 'setCurrentConfiguration', + currentConfiguration: { ...configuration }, + }); + }, []); + const setConnectorId = useCallback((newConnectorId: string) => { dispatch({ type: 'setConnectorId', @@ -115,6 +130,7 @@ const ConfigureCasesComponent: React.FC = () => { const { loading: loadingCaseConfigure, persistLoading, persistCaseConfigure } = useCaseConfigure({ setConnector: setConnectorId, setClosureType, + setCurrentConfiguration, }); const { loading: isLoadingConnectors, connectors, refetchConnectors } = useConnectors(); @@ -137,16 +153,47 @@ const ConfigureCasesComponent: React.FC = () => { [connectorId, connectors, closureType, mapping] ); - const onChangeConnector = useCallback((newConnectorId: string) => { - setActionBarVisible(true); - setConnectorId(newConnectorId); + const onClickAddConnector = useCallback(() => { + setActionBarVisible(false); + setAddFlyoutVisibility(true); }, []); - const onChangeClosureType = useCallback((newClosureType: ClosureType) => { - setActionBarVisible(true); - setClosureType(newClosureType); + const onClickUpdateConnector = useCallback(() => { + setActionBarVisible(false); + setEditFlyoutVisibility(true); }, []); + const handleActionBar = useCallback(() => { + const unsavedChanges = difference(Object.values(currentConfiguration), [ + connectorId, + closureType, + ]).length; + + if (unsavedChanges === 0) { + setActionBarVisible(false); + } else { + setActionBarVisible(true); + } + + setTotalConfigurationChanges(unsavedChanges); + }, [currentConfiguration, connectorId, closureType]); + + const handleSetAddFlyoutVisibility = useCallback( + (isVisible: boolean) => { + handleActionBar(); + setAddFlyoutVisibility(isVisible); + }, + [currentConfiguration, connectorId, closureType] + ); + + const handleSetEditFlyoutVisibility = useCallback( + (isVisible: boolean) => { + handleActionBar(); + setEditFlyoutVisibility(isVisible); + }, + [currentConfiguration, connectorId, closureType] + ); + useEffect(() => { if ( !isEmpty(connectors) && @@ -188,6 +235,10 @@ const ConfigureCasesComponent: React.FC = () => { } }, [connectors, connectorId]); + useEffect(() => { + handleActionBar(); + }, [connectors, connectorId, closureType, currentConfiguration]); + return ( {!connectorIsValid && ( @@ -202,8 +253,8 @@ const ConfigureCasesComponent: React.FC = () => { connectors={connectors ?? []} disabled={persistLoading || isLoadingConnectors} isLoading={isLoadingConnectors} - onChangeConnector={onChangeConnector} - handleShowAddFlyout={handleShowAddFlyout} + onChangeConnector={setConnectorId} + handleShowAddFlyout={onClickAddConnector} selectedConnector={connectorId} /> @@ -211,7 +262,7 @@ const ConfigureCasesComponent: React.FC = () => { @@ -220,12 +271,17 @@ const ConfigureCasesComponent: React.FC = () => { updateConnectorDisabled={updateConnectorDisabled} mapping={mapping} onChangeMapping={setMapping} - setEditFlyoutVisibility={setEditFlyoutVisibility} + setEditFlyoutVisibility={onClickUpdateConnector} /> {actionBarVisible && ( - + + + + {i18n.UNSAVED_CHANGES(totalConfigurationChanges)} + + @@ -269,7 +325,7 @@ const ConfigureCasesComponent: React.FC = () => { > >} actionTypes={actionTypes} /> {editedConnectorItem && ( @@ -277,7 +333,9 @@ const ConfigureCasesComponent: React.FC = () => { key={editedConnectorItem.id} initialConnector={editedConnectorItem} editFlyoutVisible={editFlyoutVisible} - setEditFlyoutVisibility={setEditFlyoutVisibility} + setEditFlyoutVisibility={ + handleSetEditFlyoutVisibility as Dispatch> + } /> )} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/mapping.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/mapping.tsx index 2600a9f4e13ac..8cba73d1249df 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/mapping.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/mapping.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback } from 'react'; +import React from 'react'; import styled from 'styled-components'; import { @@ -25,7 +25,7 @@ interface MappingProps { updateConnectorDisabled: boolean; mapping: CasesConfigurationMapping[] | null; onChangeMapping: (newMapping: CasesConfigurationMapping[]) => void; - setEditFlyoutVisibility: React.Dispatch>; + setEditFlyoutVisibility: () => void; } const EuiButtonEmptyExtended = styled(EuiButtonEmpty)` @@ -40,8 +40,6 @@ const MappingComponent: React.FC = ({ onChangeMapping, setEditFlyoutVisibility, }) => { - const onClick = useCallback(() => setEditFlyoutVisibility(true), []); - return ( = ({ - + {i18n.UPDATE_CONNECTOR} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/reducer.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/reducer.ts index f9e4a73b3c396..f6b9d38a76de3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/reducer.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/reducer.ts @@ -13,9 +13,19 @@ export interface State { mapping: CasesConfigurationMapping[] | null; connectorId: string; closureType: ClosureType; + currentConfiguration: CurrentConfiguration; +} + +export interface CurrentConfiguration { + connectorId: State['connectorId']; + closureType: State['closureType']; } export type Action = + | { + type: 'setCurrentConfiguration'; + currentConfiguration: CurrentConfiguration; + } | { type: 'setConnectorId'; connectorId: string; @@ -31,6 +41,12 @@ export type Action = export const configureCasesReducer = () => (state: State, action: Action) => { switch (action.type) { + case 'setCurrentConfiguration': { + return { + ...state, + currentConfiguration: { ...action.currentConfiguration }, + }; + } case 'setConnectorId': { return { ...state, diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/translations.ts index dd9bf82fb0b0d..d1f04a34b7bad 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/configure_cases/translations.ts @@ -104,7 +104,7 @@ export const FIELD_MAPPING_FIRST_COL = i18n.translate( export const FIELD_MAPPING_SECOND_COL = i18n.translate( 'xpack.siem.case.configureCases.fieldMappingSecondCol', { - defaultMessage: 'Third-party incident field', + defaultMessage: 'External incident field', } ); @@ -190,3 +190,10 @@ export const FIELD_MAPPING_FIELD_COMMENTS = i18n.translate( export const UPDATE_CONNECTOR = i18n.translate('xpack.siem.case.configureCases.updateConnector', { defaultMessage: 'Update connector', }); + +export const UNSAVED_CHANGES = (unsavedChanges: number): string => { + return i18n.translate('xpack.siem.case.configureCases.unsavedChanges', { + values: { unsavedChanges }, + defaultMessage: '{unsavedChanges} unsaved changes', + }); +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx index 20712c3c5a815..740909db408ec 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx @@ -15,7 +15,7 @@ import { import styled, { css } from 'styled-components'; import { Redirect } from 'react-router-dom'; -import { CaseRequest } from '../../../../../../../../plugins/case/common/api'; +import { CasePostRequest } from '../../../../../../../../plugins/case/common/api'; import { Field, Form, getUseField, useForm, UseField } from '../../../../shared_imports'; import { usePostCase } from '../../../../containers/case/use_post_case'; import { schema } from './schema'; @@ -45,9 +45,8 @@ const MySpinner = styled(EuiLoadingSpinner)` z-index: 99; `; -const initialCaseValue: CaseRequest = { +const initialCaseValue: CasePostRequest = { description: '', - status: 'open', tags: [], title: '', }; @@ -55,12 +54,12 @@ const initialCaseValue: CaseRequest = { export const Create = React.memo(() => { const { caseData, isLoading, postCase } = usePostCase(); const [isCancel, setIsCancel] = useState(false); - const { form } = useForm({ + const { form } = useForm({ defaultValue: initialCaseValue, options: { stripEmptyFields: false }, schema, }); - const { handleCursorChange, handleOnTimelineChange } = useInsertTimeline( + const { handleCursorChange, handleOnTimelineChange } = useInsertTimeline( form, 'description' ); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/create/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/create/schema.tsx index 91d3b77493b03..4653dbc67d5a1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/create/schema.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/create/schema.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CaseRequest } from '../../../../../../../../plugins/case/common/api'; +import { CasePostRequest } from '../../../../../../../../plugins/case/common/api'; import { FIELD_TYPES, fieldValidators, FormSchema } from '../../../../shared_imports'; import * as i18n from '../../translations'; @@ -18,7 +18,7 @@ export const schemaTags = { labelAppend: OptionalFieldLabel, }; -export const schema: FormSchema = { +export const schema: FormSchema = { title: { type: FIELD_TYPES.TEXT, label: i18n.NAME, diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx index 01ccf3c510b60..25332982dca1a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/property_actions/index.tsx @@ -45,7 +45,7 @@ export const PropertyActions = React.memo(({ propertyActio const onClosePopover = useCallback((cb?: () => void) => { setShowActions(false); - if (cb) { + if (cb != null) { cb(); } }, []); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx index 8b77186f76f77..75013c0afde5d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx @@ -11,7 +11,7 @@ import styled from 'styled-components'; import * as i18n from '../case_view/translations'; -import { Case, CaseUserActions, Comment } from '../../../../containers/case/types'; +import { Case, CaseUserActions } from '../../../../containers/case/types'; import { useUpdateComment } from '../../../../containers/case/use_update_comment'; import { useCurrentUser } from '../../../../lib/kibana'; import { AddComment } from '../add_comment'; @@ -28,6 +28,7 @@ export interface UserActionTreeProps { isLoadingUserActions: boolean; lastIndexPushToService: number; onUpdateField: (updateKey: keyof Case, updateValue: string | string[]) => void; + updateCase: (newCase: Case) => void; } const MyEuiFlexGroup = styled(EuiFlexGroup)` @@ -47,16 +48,16 @@ export const UserActionTree = React.memo( isLoadingUserActions, lastIndexPushToService, onUpdateField, + updateCase, }: UserActionTreeProps) => { const { commentId } = useParams(); const handlerTimeoutId = useRef(0); const [initLoading, setInitLoading] = useState(true); const [selectedOutlineCommentId, setSelectedOutlineCommentId] = useState(''); - const { comments, isLoadingIds, updateComment, addPostedComment } = useUpdateComment( - caseData.comments - ); + const { isLoadingIds, patchComment } = useUpdateComment(); const currentUser = useCurrentUser(); const [manageMarkdownEditIds, setManangeMardownEditIds] = useState([]); + const [insertQuote, setInsertQuote] = useState(null); const handleManageMarkdownEditId = useCallback( (id: string) => { @@ -70,16 +71,18 @@ export const UserActionTree = React.memo( ); const handleSaveComment = useCallback( - (id: string, content: string) => { + ({ id, version }: { id: string; version: string }, content: string) => { handleManageMarkdownEditId(id); - updateComment({ + patchComment({ caseId: caseData.id, commentId: id, commentUpdate: content, fetchUserActions, + version, + updateCase, }); }, - [handleManageMarkdownEditId, updateComment] + [caseData, handleManageMarkdownEditId, patchComment, updateCase] ); const handleOutlineComment = useCallback( @@ -92,6 +95,9 @@ export const UserActionTree = React.memo( top: y, behavior: 'smooth', }); + if (id === 'add-comment') { + moveToTarget.getElementsByTagName('textarea')[0].focus(); + } } window.clearTimeout(handlerTimeoutId.current); setSelectedOutlineCommentId(id); @@ -103,12 +109,21 @@ export const UserActionTree = React.memo( [handlerTimeoutId.current] ); + const handleManageQuote = useCallback( + (quote: string) => { + const addCarrots = quote.replace(new RegExp('\r?\n', 'g'), ' \n> '); + setInsertQuote(`> ${addCarrots} \n`); + handleOutlineComment('add-comment'); + }, + [handleOutlineComment] + ); + const handleUpdate = useCallback( - (comment: Comment) => { - addPostedComment(comment); + (newCase: Case) => { + updateCase(newCase); fetchUserActions(); }, - [addPostedComment, fetchUserActions] + [fetchUserActions, updateCase] ); const MarkdownDescription = useMemo( @@ -131,12 +146,13 @@ export const UserActionTree = React.memo( () => ( ), - [caseData.id, handleUpdate] + [caseData.id, handleUpdate, insertQuote] ); useEffect(() => { @@ -156,16 +172,18 @@ export const UserActionTree = React.memo( isEditable={manageMarkdownEditIds.includes(DESCRIPTION_ID)} isLoading={isLoadingDescription} labelEditAction={i18n.EDIT_DESCRIPTION} + labelQuoteAction={i18n.QUOTE} labelTitle={<>{i18n.ADDED_DESCRIPTION}} fullName={caseData.createdBy.fullName ?? caseData.createdBy.username} markdown={MarkdownDescription} onEdit={handleManageMarkdownEditId.bind(null, DESCRIPTION_ID)} - userName={caseData.createdBy.username} + onQuote={handleManageQuote.bind(null, caseData.description)} + username={caseData.createdBy.username} /> {caseUserActions.map((action, index) => { if (action.commentId != null && action.action === 'create') { - const comment = comments.find(c => c.id === action.commentId); + const comment = caseData.comments.find(c => c.id === action.commentId); if (comment != null) { return ( {i18n.ADDED_COMMENT}} fullName={comment.createdBy.fullName ?? comment.createdBy.username} markdown={ @@ -184,12 +203,16 @@ export const UserActionTree = React.memo( content={comment.comment} isEditable={manageMarkdownEditIds.includes(comment.id)} onChangeEditable={handleManageMarkdownEditId} - onSaveContent={handleSaveComment.bind(null, comment.id)} + onSaveContent={handleSaveComment.bind(null, { + id: comment.id, + version: comment.version, + })} /> } onEdit={handleManageMarkdownEditId.bind(null, comment.id)} + onQuote={handleManageQuote.bind(null, comment.comment)} outlineComment={handleOutlineComment} - userName={comment.createdBy.username} + username={comment.createdBy.username} updatedAt={comment.updatedAt} /> ); @@ -225,7 +248,7 @@ export const UserActionTree = React.memo( index === lastIndexPushToService && index < caseUserActions.length - 1 } - userName={action.actionBy.username} + username={action.actionBy.username} /> ); } @@ -245,7 +268,7 @@ export const UserActionTree = React.memo( isLoading={isLoadingIds.includes(NEW_ID)} fullName={currentUser != null ? currentUser.fullName : ''} markdown={MarkdownNewComment} - userName={currentUser != null ? currentUser.username : ''} + username={currentUser != null ? currentUser.username : ''} /> ); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx index 10a7c56e2eb2d..cc36e791e35b4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx @@ -25,12 +25,14 @@ interface UserActionItemProps { isEditable: boolean; isLoading: boolean; labelEditAction?: string; + labelQuoteAction?: string; labelTitle?: JSX.Element; linkId?: string | null; - fullName: string; + fullName?: string | null; markdown?: React.ReactNode; onEdit?: (id: string) => void; - userName: string; + onQuote?: (id: string) => void; + username: string; updatedAt?: string | null; outlineComment?: (id: string) => void; showBottomFooter?: boolean; @@ -113,23 +115,25 @@ export const UserActionItem = ({ isEditable, isLoading, labelEditAction, + labelQuoteAction, labelTitle, linkId, fullName, markdown, onEdit, + onQuote, outlineComment, showBottomFooter, showTopFooter, - userName, + username, updatedAt, }: UserActionItemProps) => ( - {fullName.length > 0 || userName.length > 0 ? ( - + {(fullName && fullName.length > 0) || username.length > 0 ? ( + ) : ( )} @@ -147,11 +151,13 @@ export const UserActionItem = ({ id={id} isLoading={isLoading} labelEditAction={labelEditAction} + labelQuoteAction={labelQuoteAction} labelTitle={labelTitle ?? <>} linkId={linkId} - userName={userName} + username={username} updatedAt={updatedAt} onEdit={onEdit} + onQuote={onQuote} outlineComment={outlineComment} /> {markdown} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx index 6ca81667d9712..94185cb4d130c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx @@ -30,11 +30,13 @@ interface UserActionTitleProps { id: string; isLoading: boolean; labelEditAction?: string; + labelQuoteAction?: string; labelTitle: JSX.Element; linkId?: string | null; updatedAt?: string | null; - userName: string; + username: string; onEdit?: (id: string) => void; + onQuote?: (id: string) => void; outlineComment?: (id: string) => void; } @@ -43,27 +45,39 @@ export const UserActionTitle = ({ id, isLoading, labelEditAction, + labelQuoteAction, labelTitle, linkId, - userName, + username, updatedAt, onEdit, + onQuote, outlineComment, }: UserActionTitleProps) => { const { detailName: caseId } = useParams(); const urlSearch = useGetUrlSearch(navTabs.case); const propertyActions = useMemo(() => { - if (labelEditAction != null && onEdit != null) { - return [ - { - iconType: 'pencil', - label: labelEditAction, - onClick: () => onEdit(id), - }, - ]; - } - return []; - }, [id, labelEditAction, onEdit]); + return [ + ...(labelEditAction != null && onEdit != null + ? [ + { + iconType: 'pencil', + label: labelEditAction, + onClick: () => onEdit(id), + }, + ] + : []), + ...(labelQuoteAction != null && onQuote != null + ? [ + { + iconType: 'quote', + label: labelQuoteAction, + onClick: () => onQuote(id), + }, + ] + : []), + ]; + }, [id, labelEditAction, onEdit, labelQuoteAction, onQuote]); const handleAnchorLink = useCallback(() => { copy( @@ -91,7 +105,7 @@ export const UserActionTitle = ({ - {userName} + {username} {labelTitle} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_list/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_list/index.tsx index 9ace36eea1e9e..3109f2382c362 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_list/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_list/index.tsx @@ -12,6 +12,7 @@ import { EuiAvatar, EuiFlexGroup, EuiFlexItem, + EuiLoadingSpinner, } from '@elastic/eui'; import styled, { css } from 'styled-components'; import { ElasticUser } from '../../../../containers/case/types'; @@ -22,6 +23,7 @@ interface UserListProps { body: string; }; headline: string; + loading?: boolean; users: ElasticUser[]; } @@ -67,7 +69,7 @@ const renderUsers = ( )); }; -export const UserList = React.memo(({ email, headline, users }: UserListProps) => { +export const UserList = React.memo(({ email, headline, loading, users }: UserListProps) => { const handleSendEmail = useCallback( (emailAddress: string | undefined | null) => { if (emailAddress && emailAddress != null) { @@ -80,6 +82,13 @@ export const UserList = React.memo(({ email, headline, users }: UserListProps) =

{headline}

+ {loading && ( + + + + + + )} {renderUsers(users, handleSendEmail)}
); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.test.tsx new file mode 100644 index 0000000000000..8aaed08a0a0a1 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.test.tsx @@ -0,0 +1,380 @@ +/* + * 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 sinon from 'sinon'; +import moment from 'moment'; + +import { sendSignalToTimelineAction, determineToAndFrom } from './actions'; +import { + mockEcsDataWithSignal, + defaultTimelineProps, + apolloClient, + mockTimelineApolloResult, +} from '../../../../mock/'; +import { CreateTimeline, UpdateTimelineLoading } from './types'; +import { Ecs } from '../../../../graphql/types'; + +jest.mock('apollo-client'); + +describe('signals actions', () => { + const anchor = '2020-03-01T17:59:46.349Z'; + const unix = moment(anchor).valueOf(); + let createTimeline: CreateTimeline; + let updateTimelineIsLoading: UpdateTimelineLoading; + let clock: sinon.SinonFakeTimers; + + beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + + createTimeline = jest.fn() as jest.Mocked; + updateTimelineIsLoading = jest.fn() as jest.Mocked; + + jest.spyOn(apolloClient, 'query').mockResolvedValue(mockTimelineApolloResult); + + clock = sinon.useFakeTimers(unix); + }); + + afterEach(() => { + clock.restore(); + }); + + describe('sendSignalToTimelineAction', () => { + describe('timeline id is NOT empty string and apollo client exists', () => { + test('it invokes updateTimelineIsLoading to set to true', async () => { + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: mockEcsDataWithSignal, + updateTimelineIsLoading, + }); + + expect(updateTimelineIsLoading).toHaveBeenCalledTimes(1); + expect(updateTimelineIsLoading).toHaveBeenCalledWith({ id: 'timeline-1', isLoading: true }); + }); + + test('it invokes createTimeline with designated timeline template if "timelineTemplate" exists', async () => { + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: mockEcsDataWithSignal, + updateTimelineIsLoading, + }); + const expected = { + from: 1541444305937, + timeline: { + columns: [ + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: '@timestamp', + placeholder: undefined, + type: undefined, + width: 190, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'message', + placeholder: undefined, + type: undefined, + width: 180, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'event.category', + placeholder: undefined, + type: undefined, + width: 180, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'host.name', + placeholder: undefined, + type: undefined, + width: 180, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'source.ip', + placeholder: undefined, + type: undefined, + width: 180, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'destination.ip', + placeholder: undefined, + type: undefined, + width: 180, + }, + { + aggregatable: undefined, + category: undefined, + columnHeaderType: 'not-filtered', + description: undefined, + example: undefined, + id: 'user.name', + placeholder: undefined, + type: undefined, + width: 180, + }, + ], + dataProviders: [], + dateRange: { + end: 1541444605937, + start: 1541444305937, + }, + deletedEventIds: [], + description: 'This is a sample rule description', + eventIdToNoteIds: {}, + eventType: 'all', + filters: [ + { + $state: { + store: 'appState', + }, + meta: { + key: 'host.name', + negate: false, + params: { + query: 'apache', + }, + type: 'phrase', + }, + query: { + match_phrase: { + 'host.name': 'apache', + }, + }, + }, + ], + highlightedDropAndProviderId: '', + historyIds: [], + id: '', + isFavorite: false, + isLive: false, + isLoading: false, + isSaving: false, + isSelectAllChecked: false, + itemsPerPage: 25, + itemsPerPageOptions: [10, 25, 50, 100], + kqlMode: 'filter', + kqlQuery: { + filterQuery: { + kuery: { + expression: '', + kind: 'kuery', + }, + serializedQuery: '', + }, + filterQueryDraft: { + expression: '', + kind: 'kuery', + }, + }, + loadingEventIds: [], + noteIds: [], + pinnedEventIds: {}, + pinnedEventsSaveObject: {}, + savedObjectId: null, + selectedEventIds: {}, + show: true, + showCheckboxes: false, + showRowRenderers: true, + sort: { + columnId: '@timestamp', + sortDirection: 'desc', + }, + title: '', + version: null, + width: 1100, + }, + to: 1541444605937, + ruleNote: '# this is some markdown documentation', + }; + + expect(createTimeline).toHaveBeenCalledWith(expected); + }); + + test('it invokes createTimeline with kqlQuery.filterQuery.kuery.kind as "kuery" if not specified in returned timeline template', async () => { + const mockTimelineApolloResultModified = { + ...mockTimelineApolloResult, + kqlQuery: { + filterQuery: { + kuery: { + expression: [''], + }, + }, + filterQueryDraft: { + expression: [''], + }, + }, + }; + jest.spyOn(apolloClient, 'query').mockResolvedValue(mockTimelineApolloResultModified); + + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: mockEcsDataWithSignal, + updateTimelineIsLoading, + }); + // @ts-ignore + const createTimelineArg = createTimeline.mock.calls[0][0]; + + expect(createTimeline).toHaveBeenCalledTimes(1); + expect(createTimelineArg.timeline.kqlQuery.filterQuery.kuery.kind).toEqual('kuery'); + }); + + test('it invokes createTimeline with kqlQuery.filterQueryDraft.kuery.kind as "kuery" if not specified in returned timeline template', async () => { + const mockTimelineApolloResultModified = { + ...mockTimelineApolloResult, + kqlQuery: { + filterQuery: { + kuery: { + expression: [''], + }, + }, + filterQueryDraft: { + expression: [''], + }, + }, + }; + jest.spyOn(apolloClient, 'query').mockResolvedValue(mockTimelineApolloResultModified); + + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: mockEcsDataWithSignal, + updateTimelineIsLoading, + }); + // @ts-ignore + const createTimelineArg = createTimeline.mock.calls[0][0]; + + expect(createTimeline).toHaveBeenCalledTimes(1); + expect(createTimelineArg.timeline.kqlQuery.filterQueryDraft.kind).toEqual('kuery'); + }); + + test('it invokes createTimeline with default timeline if apolloClient throws', async () => { + jest.spyOn(apolloClient, 'query').mockImplementation(() => { + throw new Error('Test error'); + }); + + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: mockEcsDataWithSignal, + updateTimelineIsLoading, + }); + + expect(updateTimelineIsLoading).toHaveBeenCalledWith({ id: 'timeline-1', isLoading: true }); + expect(updateTimelineIsLoading).toHaveBeenCalledWith({ + id: 'timeline-1', + isLoading: false, + }); + expect(createTimeline).toHaveBeenCalledTimes(1); + expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps); + }); + }); + + describe('timelineId is empty string', () => { + test('it invokes createTimeline with timelineDefaults', async () => { + const ecsDataMock: Ecs = { + ...mockEcsDataWithSignal, + signal: { + rule: { + ...mockEcsDataWithSignal.signal?.rule!, + timeline_id: null, + }, + }, + }; + + await sendSignalToTimelineAction({ + apolloClient, + createTimeline, + ecsData: ecsDataMock, + updateTimelineIsLoading, + }); + + expect(updateTimelineIsLoading).not.toHaveBeenCalled(); + expect(createTimeline).toHaveBeenCalledTimes(1); + expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps); + }); + }); + + describe('apolloClient is not defined', () => { + test('it invokes createTimeline with timelineDefaults', async () => { + const ecsDataMock: Ecs = { + ...mockEcsDataWithSignal, + signal: { + rule: { + ...mockEcsDataWithSignal.signal?.rule!, + timeline_id: [''], + }, + }, + }; + + await sendSignalToTimelineAction({ + createTimeline, + ecsData: ecsDataMock, + updateTimelineIsLoading, + }); + + expect(updateTimelineIsLoading).not.toHaveBeenCalled(); + expect(createTimeline).toHaveBeenCalledTimes(1); + expect(createTimeline).toHaveBeenCalledWith(defaultTimelineProps); + }); + }); + }); + + describe('determineToAndFrom', () => { + test('it uses ecs.Data.timestamp if one is provided', () => { + const ecsDataMock: Ecs = { + ...mockEcsDataWithSignal, + timestamp: '2020-03-20T17:59:46.349Z', + }; + const result = determineToAndFrom({ ecsData: ecsDataMock }); + + expect(result.from).toEqual(1584726886349); + expect(result.to).toEqual(1584727186349); + }); + + test('it uses current time timestamp if ecsData.timestamp is not provided', () => { + const { timestamp, ...ecsDataMock } = { + ...mockEcsDataWithSignal, + }; + const result = determineToAndFrom({ ecsData: ecsDataMock }); + + expect(result.from).toEqual(1583085286349); + expect(result.to).toEqual(1583085586349); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx index b23b051e8b2e8..c71ede32d8403 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/actions.tsx @@ -10,7 +10,7 @@ import moment from 'moment'; import { updateSignalStatus } from '../../../../containers/detection_engine/signals/api'; import { SendSignalToTimelineActionProps, UpdateSignalStatusActionProps } from './types'; -import { TimelineNonEcsData, GetOneTimeline, TimelineResult } from '../../../../graphql/types'; +import { TimelineNonEcsData, GetOneTimeline, TimelineResult, Ecs } from '../../../../graphql/types'; import { oneTimelineQuery } from '../../../../containers/timeline/one/index.gql_query'; import { omitTypenameInTimeline, @@ -72,16 +72,7 @@ export const updateSignalStatusAction = async ({ } }; -export const sendSignalToTimelineAction = async ({ - apolloClient, - createTimeline, - ecsData, - updateTimelineIsLoading, -}: SendSignalToTimelineActionProps) => { - let openSignalInBasicTimeline = true; - const timelineId = - ecsData.signal?.rule?.timeline_id != null ? ecsData.signal?.rule?.timeline_id[0] : ''; - +export const determineToAndFrom = ({ ecsData }: { ecsData: Ecs }) => { const ellapsedTimeRule = moment.duration( moment().diff( dateMath.parse(ecsData.signal?.rule?.from != null ? ecsData.signal?.rule?.from[0] : 'now-0s') @@ -93,6 +84,21 @@ export const sendSignalToTimelineAction = async ({ .valueOf(); const to = moment(ecsData.timestamp ?? new Date()).valueOf(); + return { to, from }; +}; + +export const sendSignalToTimelineAction = async ({ + apolloClient, + createTimeline, + ecsData, + updateTimelineIsLoading, +}: SendSignalToTimelineActionProps) => { + let openSignalInBasicTimeline = true; + const noteContent = ecsData.signal?.rule?.note != null ? ecsData.signal?.rule?.note[0] : ''; + const timelineId = + ecsData.signal?.rule?.timeline_id != null ? ecsData.signal?.rule?.timeline_id[0] : ''; + const { to, from } = determineToAndFrom({ ecsData }); + if (timelineId !== '' && apolloClient != null) { try { updateTimelineIsLoading({ id: 'timeline-1', isLoading: true }); @@ -106,10 +112,10 @@ export const sendSignalToTimelineAction = async ({ id: timelineId, }, }); - const timelineTemplate: TimelineResult = omitTypenameInTimeline( - getOr({}, 'data.getOneTimeline', responseTimeline) - ); - if (!isEmpty(timelineTemplate)) { + const resultingTimeline: TimelineResult = getOr({}, 'data.getOneTimeline', responseTimeline); + + if (!isEmpty(resultingTimeline)) { + const timelineTemplate: TimelineResult = omitTypenameInTimeline(resultingTimeline); openSignalInBasicTimeline = false; const { timeline } = formatTimelineResultToModel(timelineTemplate, true); const query = replaceTemplateFieldFromQuery( @@ -148,6 +154,7 @@ export const sendSignalToTimelineAction = async ({ show: true, }, to, + ruleNote: noteContent, }); } } catch { @@ -197,6 +204,7 @@ export const sendSignalToTimelineAction = async ({ }, }, to, + ruleNote: noteContent, }); } }; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.test.tsx new file mode 100644 index 0000000000000..6212cad7e1845 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.test.tsx @@ -0,0 +1,193 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { mount, ReactWrapper } from 'enzyme'; +import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; + +import { Filter } from '../../../../../../../../../src/plugins/data/common/es_query'; +import { TimelineAction } from '../../../../components/timeline/body/actions'; +import { buildSignalsRuleIdFilter, getSignalsActions } from './default_config'; +import { + CreateTimeline, + SetEventsDeletedProps, + SetEventsLoadingProps, + UpdateTimelineLoading, +} from './types'; +import { mockEcsDataWithSignal } from '../../../../mock/mock_ecs'; +import { sendSignalToTimelineAction, updateSignalStatusAction } from './actions'; +import * as i18n from './translations'; + +jest.mock('./actions'); + +describe('signals default_config', () => { + describe('buildSignalsRuleIdFilter', () => { + test('given a rule id this will return an array with a single filter', () => { + const filters: Filter[] = buildSignalsRuleIdFilter('rule-id-1'); + const expectedFilter: Filter = { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'signal.rule.id', + params: { + query: 'rule-id-1', + }, + }, + query: { + match_phrase: { + 'signal.rule.id': 'rule-id-1', + }, + }, + }; + expect(filters).toHaveLength(1); + expect(filters[0]).toEqual(expectedFilter); + }); + }); + + describe('getSignalsActions', () => { + let setEventsLoading: ({ eventIds, isLoading }: SetEventsLoadingProps) => void; + let setEventsDeleted: ({ eventIds, isDeleted }: SetEventsDeletedProps) => void; + let createTimeline: CreateTimeline; + let updateTimelineIsLoading: UpdateTimelineLoading; + + beforeEach(() => { + setEventsLoading = jest.fn(); + setEventsDeleted = jest.fn(); + createTimeline = jest.fn(); + updateTimelineIsLoading = jest.fn(); + }); + + describe('timeline tooltip', () => { + test('it invokes sendSignalToTimelineAction when button clicked', () => { + const signalsActions = getSignalsActions({ + canUserCRUD: true, + hasIndexWrite: true, + setEventsLoading, + setEventsDeleted, + createTimeline, + status: 'open', + updateTimelineIsLoading, + }); + const timelineAction = signalsActions[0].getAction({ + eventId: 'even-id', + ecsData: mockEcsDataWithSignal, + }); + const wrapper = mount(timelineAction as React.ReactElement); + wrapper.find(EuiButtonIcon).simulate('click'); + + expect(sendSignalToTimelineAction).toHaveBeenCalled(); + }); + }); + + describe('signal open action', () => { + let signalsActions: TimelineAction[]; + let signalOpenAction: JSX.Element; + let wrapper: ReactWrapper; + + beforeEach(() => { + signalsActions = getSignalsActions({ + canUserCRUD: true, + hasIndexWrite: true, + setEventsLoading, + setEventsDeleted, + createTimeline, + status: 'open', + updateTimelineIsLoading, + }); + + signalOpenAction = signalsActions[1].getAction({ + eventId: 'event-id', + ecsData: mockEcsDataWithSignal, + }); + + wrapper = mount(signalOpenAction as React.ReactElement); + }); + + afterEach(() => { + wrapper.unmount(); + }); + + test('it invokes updateSignalStatusAction when button clicked', () => { + wrapper.find(EuiButtonIcon).simulate('click'); + + expect(updateSignalStatusAction).toHaveBeenCalledWith({ + signalIds: ['event-id'], + status: 'open', + setEventsLoading, + setEventsDeleted, + }); + }); + + test('it displays expected text on hover', () => { + const openSignal = wrapper.find(EuiToolTip); + openSignal.simulate('mouseOver'); + const tooltip = wrapper.find('.euiToolTipPopover').text(); + + expect(tooltip).toEqual(i18n.ACTION_OPEN_SIGNAL); + }); + + test('it displays expected icon', () => { + const icon = wrapper.find(EuiButtonIcon).props().iconType; + + expect(icon).toEqual('securitySignalDetected'); + }); + }); + + describe('signal close action', () => { + let signalsActions: TimelineAction[]; + let signalCloseAction: JSX.Element; + let wrapper: ReactWrapper; + + beforeEach(() => { + signalsActions = getSignalsActions({ + canUserCRUD: true, + hasIndexWrite: true, + setEventsLoading, + setEventsDeleted, + createTimeline, + status: 'closed', + updateTimelineIsLoading, + }); + + signalCloseAction = signalsActions[1].getAction({ + eventId: 'event-id', + ecsData: mockEcsDataWithSignal, + }); + + wrapper = mount(signalCloseAction as React.ReactElement); + }); + + afterEach(() => { + wrapper.unmount(); + }); + + test('it invokes updateSignalStatusAction when status button clicked', () => { + wrapper.find(EuiButtonIcon).simulate('click'); + + expect(updateSignalStatusAction).toHaveBeenCalledWith({ + signalIds: ['event-id'], + status: 'closed', + setEventsLoading, + setEventsDeleted, + }); + }); + + test('it displays expected text on hover', () => { + const closeSignal = wrapper.find(EuiToolTip); + closeSignal.simulate('mouseOver'); + const tooltip = wrapper.find('.euiToolTipPopover').text(); + expect(tooltip).toEqual(i18n.ACTION_CLOSE_SIGNAL); + }); + + test('it displays expected icon', () => { + const icon = wrapper.find(EuiButtonIcon).props().iconType; + + expect(icon).toEqual('securitySignalResolved'); + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx index 44c48b1879e89..fd3b9a6f68e82 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/default_config.tsx @@ -23,7 +23,12 @@ import { timelineDefaults } from '../../../../store/timeline/defaults'; import { FILTER_OPEN } from './signals_filter_group'; import { sendSignalToTimelineAction, updateSignalStatusAction } from './actions'; import * as i18n from './translations'; -import { CreateTimeline, SetEventsDeletedProps, SetEventsLoadingProps } from './types'; +import { + CreateTimeline, + SetEventsDeletedProps, + SetEventsLoadingProps, + UpdateTimelineLoading, +} from './types'; export const signalsOpenFilters: Filter[] = [ { @@ -198,13 +203,13 @@ export const getSignalsActions = ({ setEventsDeleted: ({ eventIds, isDeleted }: SetEventsDeletedProps) => void; createTimeline: CreateTimeline; status: 'open' | 'closed'; - updateTimelineIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => void; + updateTimelineIsLoading: UpdateTimelineLoading; }): TimelineAction[] => [ { getAction: ({ ecsData }: TimelineActionProps): JSX.Element => ( { let localValueToChange = valueToChange; - if (keuryNode.function === 'is' && templateFields.includes(keuryNode.arguments[0].value)) { + if (kueryNode.function === 'is' && templateFields.includes(kueryNode.arguments[0].value)) { localValueToChange = [ ...localValueToChange, { - field: keuryNode.arguments[0].value, - valueToChange: keuryNode.arguments[1].value, + field: kueryNode.arguments[0].value, + valueToChange: kueryNode.arguments[1].value, }, ]; } - return keuryNode.arguments.reduce( + return kueryNode.arguments.reduce( (addValueToChange: FindValueToChangeInQuery[], ast: KueryNode) => { if (ast.function === 'is' && templateFields.includes(ast.arguments[0].value)) { return [ diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx index afd325f539966..6cdb2f326901e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx @@ -114,7 +114,7 @@ const SignalsTableComponent: React.FC = ({ // Callback for creating a new timeline -- utilized by row/batch actions const createTimelineCallback = useCallback( - ({ from: fromTimeline, timeline, to: toTimeline }: CreateTimelineProps) => { + ({ from: fromTimeline, timeline, to: toTimeline, ruleNote }: CreateTimelineProps) => { updateTimelineIsLoading({ id: 'timeline-1', isLoading: false }); updateTimeline({ duplicate: true, @@ -126,6 +126,7 @@ const SignalsTableComponent: React.FC = ({ show: true, }, to: toTimeline, + ruleNote, })(); }, [updateTimeline, updateTimelineIsLoading] diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts index c2807db179780..f68dcd932bc32 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts @@ -95,9 +95,9 @@ export const ACTION_CLOSE_SIGNAL = i18n.translate( } ); -export const ACTION_VIEW_IN_TIMELINE = i18n.translate( - 'xpack.siem.detectionEngine.signals.actions.viewInTimelineTitle', +export const ACTION_INVESTIGATE_IN_TIMELINE = i18n.translate( + 'xpack.siem.detectionEngine.signals.actions.investigateInTimelineTitle', { - defaultMessage: 'View in timeline', + defaultMessage: 'Investigate in timeline', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts index b3e7ed75cfb99..909b217646746 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/types.ts @@ -45,13 +45,16 @@ export interface SendSignalToTimelineActionProps { apolloClient?: ApolloClient<{}>; createTimeline: CreateTimeline; ecsData: Ecs; - updateTimelineIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => void; + updateTimelineIsLoading: UpdateTimelineLoading; } +export type UpdateTimelineLoading = ({ id, isLoading }: { id: string; isLoading: boolean }) => void; + export interface CreateTimelineProps { from: number; timeline: TimelineModel; to: number; + ruleNote?: string; } export type CreateTimeline = ({ from, timeline, to }: CreateTimelineProps) => void; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts index a6aefefedd5c3..6d76fde49634d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/__mocks__/mock.ts @@ -6,7 +6,7 @@ import { esFilters } from '../../../../../../../../../../src/plugins/data/public'; import { Rule, RuleError } from '../../../../../containers/detection_engine/rules'; -import { AboutStepRule, DefineStepRule, ScheduleStepRule } from '../../types'; +import { AboutStepRule, ActionsStepRule, DefineStepRule, ScheduleStepRule } from '../../types'; import { FieldValueQueryBar } from '../../components/query_bar'; export const mockQueryBar: FieldValueQueryBar = { @@ -40,6 +40,7 @@ export const mockQueryBar: FieldValueQueryBar = { }; export const mockRule = (id: string): Rule => ({ + actions: [], created_at: '2020-01-10T21:11:45.839Z', updated_at: '2020-01-10T21:11:45.839Z', created_by: 'elastic', @@ -70,11 +71,13 @@ export const mockRule = (id: string): Rule => ({ to: 'now', type: 'saved_query', threat: [], + throttle: null, note: '# this is some markdown documentation', version: 1, }); export const mockRuleWithEverything = (id: string): Rule => ({ + actions: [], created_at: '2020-01-10T21:11:45.839Z', updated_at: '2020-01-10T21:11:45.839Z', created_by: 'elastic', @@ -142,6 +145,7 @@ export const mockRuleWithEverything = (id: string): Rule => ({ ], }, ], + throttle: null, note: '# this is some markdown documentation', version: 1, }); @@ -175,6 +179,14 @@ export const mockAboutStepRule = (isNew = false): AboutStepRule => ({ note: '# this is some markdown documentation', }); +export const mockActionsStepRule = (isNew = false, enabled = false): ActionsStepRule => ({ + isNew, + actions: [], + kibanaSiemAppUrl: 'http://localhost:5601/app/siem', + enabled, + throttle: null, +}); + export const mockDefineStepRule = (isNew = false): DefineStepRule => ({ isNew, ruleType: 'query', @@ -188,9 +200,8 @@ export const mockDefineStepRule = (isNew = false): DefineStepRule => ({ }, }); -export const mockScheduleStepRule = (isNew = false, enabled = false): ScheduleStepRule => ({ +export const mockScheduleStepRule = (isNew = false): ScheduleStepRule => ({ isNew, - enabled, interval: '5m', from: '6m', to: 'now', diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/batch_actions.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/batch_actions.tsx index a0942d7f6534a..60ad68b8c9141 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/batch_actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/batch_actions.tsx @@ -108,6 +108,7 @@ export const getBatchItems = ({ {i18n.BATCH_ACTION_DUPLICATE_SELECTED} , , @@ -65,6 +67,7 @@ export const getActions = ( enabled: (rowItem: Rule) => !rowItem.immutable, }, { + 'data-test-subj': 'deleteRuleAction', description: i18n.DELETE_RULE, icon: 'trash', name: i18n.DELETE_RULE, @@ -75,7 +78,12 @@ export const getActions = ( }, ]; +export type RuleStatusRowItemType = RuleStatus & { + name: string; + id: string; +}; type RulesColumns = EuiBasicTableColumn | EuiTableActionsColumnType; +type RulesStatusesColumns = EuiBasicTableColumn; interface GetColumns { dispatch: React.Dispatch; @@ -132,7 +140,9 @@ export const getColumns = ({ return value == null ? ( getEmptyTagValue() ) : ( - + + + ); }, sortable: true, @@ -196,3 +206,114 @@ export const getColumns = ({ return hasNoPermissions ? cols : [...cols, ...actions]; }; + +export const getMonitoringColumns = (): RulesStatusesColumns[] => { + const cols: RulesStatusesColumns[] = [ + { + field: 'name', + name: i18n.COLUMN_RULE, + render: (value: RuleStatus['current_status']['status'], item: RuleStatusRowItemType) => { + return ( + + {value} + + ); + }, + truncateText: true, + width: '24%', + }, + { + field: 'current_status.bulk_create_time_durations', + name: i18n.COLUMN_INDEXING_TIMES, + render: (value: RuleStatus['current_status']['bulk_create_time_durations']) => ( + + {value != null && value.length > 0 + ? Math.max(...value?.map(item => Number.parseFloat(item))) + : null} + + ), + truncateText: true, + width: '14%', + }, + { + field: 'current_status.search_after_time_durations', + name: i18n.COLUMN_QUERY_TIMES, + render: (value: RuleStatus['current_status']['search_after_time_durations']) => ( + + {value != null && value.length > 0 + ? Math.max(...value?.map(item => Number.parseFloat(item))) + : null} + + ), + truncateText: true, + width: '14%', + }, + { + field: 'current_status.gap', + name: i18n.COLUMN_GAP, + render: (value: RuleStatus['current_status']['gap']) => ( + + {value} + + ), + truncateText: true, + width: '14%', + }, + { + field: 'current_status.last_look_back_date', + name: i18n.COLUMN_LAST_LOOKBACK_DATE, + render: (value: RuleStatus['current_status']['last_look_back_date']) => { + return value == null ? ( + getEmptyTagValue() + ) : ( + + ); + }, + truncateText: true, + width: '16%', + }, + { + field: 'current_status.status_date', + name: i18n.COLUMN_LAST_COMPLETE_RUN, + render: (value: RuleStatus['current_status']['status_date']) => { + return value == null ? ( + getEmptyTagValue() + ) : ( + + + + ); + }, + sortable: true, + truncateText: true, + width: '20%', + }, + { + field: 'current_status.status', + name: i18n.COLUMN_LAST_RESPONSE, + render: (value: RuleStatus['current_status']['status']) => { + return ( + <> + + {value ?? getEmptyTagValue()} + + + ); + }, + width: '16%', + truncateText: true, + }, + { + field: 'activate', + name: i18n.COLUMN_ACTIVATE, + render: (value: Rule['enabled']) => ( + + {value ? i18n.ACTIVE : i18n.INACTIVE} + + ), + width: '95px', + }, + ]; + + return cols; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx index 621c70e391319..4003b71b95d77 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx @@ -4,20 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiBasicTable, - EuiContextMenuPanel, - EuiEmptyPrompt, - EuiLoadingContent, - EuiSpacer, -} from '@elastic/eui'; +import { EuiBasicTable, EuiContextMenuPanel, EuiLoadingContent, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import styled from 'styled-components'; import uuid from 'uuid'; import { useRules, + useRulesStatuses, CreatePreBuiltRules, FilterOptions, Rule, @@ -37,20 +31,16 @@ import { Loader } from '../../../../components/loader'; import { Panel } from '../../../../components/panel'; import { PrePackagedRulesPrompt } from '../components/pre_packaged_rules/load_empty_prompt'; import { GenericDownloader } from '../../../../components/generic_downloader'; +import { AllRulesTables } from '../components/all_rules_tables'; import { getPrePackagedRuleStatus } from '../helpers'; import * as i18n from '../translations'; import { EuiBasicTableOnChange } from '../types'; import { getBatchItems } from './batch_actions'; -import { getColumns } from './columns'; +import { getColumns, getMonitoringColumns } from './columns'; import { showRulesTable } from './helpers'; import { allRulesReducer, State } from './reducer'; import { RulesTableFilters } from './rules_table_filters/rules_table_filters'; -// EuiBasicTable give me a hardtime with adding the ref attributes so I went the easy way -// after few hours of fight with typescript !!!! I lost :( -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const MyEuiBasicTable = styled(EuiBasicTable as any)`` as any; - const initialState: State = { exportRuleIds: [], filterOptions: { @@ -117,6 +107,7 @@ export const AllRules = React.memo( }, dispatch, ] = useReducer(allRulesReducer(tableRef), initialState); + const { loading: isLoadingRulesStatuses, rulesStatuses } = useRulesStatuses(rules); const history = useHistory(); const [, dispatchToaster] = useStateToaster(); @@ -135,6 +126,13 @@ export const AllRules = React.memo( dispatchRulesInReducer: setRules, }); + const sorting = useMemo( + () => ({ + sort: { field: 'enabled', direction: filterOptions.sortOrder }, + }), + [filterOptions.sortOrder] + ); + const prePackagedRuleStatus = getPrePackagedRuleStatus( rulesInstalled, rulesNotInstalled, @@ -158,6 +156,16 @@ export const AllRules = React.memo( [dispatch, dispatchToaster, loadingRuleIds, reFetchRulesData, rules, selectedRuleIds] ); + const paginationMemo = useMemo( + () => ({ + pageIndex: pagination.page - 1, + pageSize: pagination.perPage, + totalItemCount: pagination.total, + pageSizeOptions: [5, 10, 20, 50, 100, 200, 300], + }), + [pagination] + ); + const tableOnChangeCallback = useCallback( ({ page, sort }: EuiBasicTableOnChange) => { dispatch({ @@ -172,7 +180,7 @@ export const AllRules = React.memo( [dispatch] ); - const columns = useMemo(() => { + const rulesColumns = useMemo(() => { return getColumns({ dispatch, dispatchToaster, @@ -187,6 +195,8 @@ export const AllRules = React.memo( }); }, [dispatch, dispatchToaster, history, loadingRuleIds, loadingRulesAction, reFetchRulesData]); + const monitoringColumns = useMemo(() => getMonitoringColumns(), []); + useEffect(() => { if (reFetchRulesData != null) { setRefreshRulesData(reFetchRulesData); @@ -194,10 +204,10 @@ export const AllRules = React.memo( }, [reFetchRulesData, setRefreshRulesData]); useEffect(() => { - if (initLoading && !loading && !isLoadingRules) { + if (initLoading && !loading && !isLoadingRules && !isLoadingRulesStatuses) { setInitLoading(false); } - }, [initLoading, loading, isLoadingRules]); + }, [initLoading, loading, isLoadingRules, isLoadingRulesStatuses]); const handleCreatePrePackagedRules = useCallback(async () => { if (createPrePackagedRules != null && reFetchRulesData != null) { @@ -225,12 +235,6 @@ export const AllRules = React.memo( }); }, []); - const emptyPrompt = useMemo(() => { - return ( - {i18n.NO_RULES}} titleSize="xs" body={i18n.NO_RULES_BODY} /> - ); - }, []); - const isLoadingAnActionOnRule = useMemo(() => { if ( loadingRuleIds.length > 0 && @@ -264,7 +268,7 @@ export const AllRules = React.memo( /> - + <> ( /> - {(loading || isLoadingRules || isLoadingAnActionOnRule) && !initLoading && ( - - )} + {(loading || isLoadingRules || isLoadingAnActionOnRule || isLoadingRulesStatuses) && + !initLoading && ( + + )} {rulesCustomInstalled != null && rulesCustomInstalled === 0 && - prePackagedRuleStatus === 'ruleNotInstalled' && ( + prePackagedRuleStatus === 'ruleNotInstalled' && + !initLoading && ( ( - {i18n.SHOWING_RULES(pagination.total ?? 0)} + + {i18n.SHOWING_RULES(pagination.total ?? 0)} + {i18n.SELECTED_RULES(selectedRuleIds.length)} {!hasNoPermissions && ( ( - )} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx new file mode 100644 index 0000000000000..92ccbc864ab5a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx @@ -0,0 +1,121 @@ +/* + * 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 { EuiBasicTable, EuiTab, EuiTabs, EuiEmptyPrompt } from '@elastic/eui'; +import React, { useMemo, memo, useState } from 'react'; +import styled from 'styled-components'; + +import * as i18n from '../../translations'; +import { RuleStatusRowItemType } from '../../../../../pages/detection_engine/rules/all/columns'; +import { Rules } from '../../../../../containers/detection_engine/rules'; + +// EuiBasicTable give me a hardtime with adding the ref attributes so I went the easy way +// after few hours of fight with typescript !!!! I lost :( +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const MyEuiBasicTable = styled(EuiBasicTable as any)`` as any; + +interface AllRulesTablesProps { + euiBasicTableSelectionProps: unknown; + hasNoPermissions: boolean; + monitoringColumns: unknown; + paginationMemo: unknown; + rules: Rules; + rulesColumns: unknown; + rulesStatuses: RuleStatusRowItemType[] | null; + sorting: unknown; + tableOnChangeCallback: unknown; + tableRef?: unknown; +} + +enum AllRulesTabs { + rules = 'rules', + monitoring = 'monitoring', +} + +const allRulesTabs = [ + { + id: AllRulesTabs.rules, + name: i18n.RULES_TAB, + disabled: false, + }, + { + id: AllRulesTabs.monitoring, + name: i18n.MONITORING_TAB, + disabled: false, + }, +]; + +const AllRulesTablesComponent: React.FC = ({ + euiBasicTableSelectionProps, + hasNoPermissions, + monitoringColumns, + paginationMemo, + rules, + rulesColumns, + rulesStatuses, + sorting, + tableOnChangeCallback, + tableRef, +}) => { + const [allRulesTab, setAllRulesTab] = useState(AllRulesTabs.rules); + const emptyPrompt = useMemo(() => { + return ( + {i18n.NO_RULES}} titleSize="xs" body={i18n.NO_RULES_BODY} /> + ); + }, []); + const tabs = useMemo( + () => ( + + {allRulesTabs.map(tab => ( + setAllRulesTab(tab.id)} + isSelected={tab.id === allRulesTab} + disabled={tab.disabled} + key={tab.id} + > + {tab.name} + + ))} + + ), + [allRulesTabs, allRulesTab, setAllRulesTab] + ); + return ( + <> + {tabs} + {allRulesTab === AllRulesTabs.rules && ( + + )} + {allRulesTab === AllRulesTabs.monitoring && ( + + )} + + ); +}; + +export const AllRulesTables = memo(AllRulesTablesComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/anomaly_threshold_slider/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/anomaly_threshold_slider/index.tsx index 1e18023e0c326..19d1c698cbd9b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/anomaly_threshold_slider/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/anomaly_threshold_slider/index.tsx @@ -5,7 +5,7 @@ */ import React, { useCallback } from 'react'; -import { EuiFlexGrid, EuiFlexItem, EuiRange, EuiFormRow } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiRange, EuiFormRow } from '@elastic/eui'; import { FieldHook } from '../../../../../shared_imports'; @@ -31,12 +31,11 @@ export const AnomalyThresholdSlider: React.FC = ({ return ( - + = ({ tickInterval={25} /> - +
); }; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/__snapshots__/index.test.tsx.snap index 9a534297e5e29..31abea53462fa 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/__snapshots__/index.test.tsx.snap @@ -145,7 +145,7 @@ exports[`description_step StepRuleDescriptionComponent renders correctly against # this is some markdown documentation
, - "title": "Investigation notes", + "title": "Investigation guide", }, ] } @@ -287,7 +287,7 @@ exports[`description_step StepRuleDescriptionComponent renders correctly against # this is some markdown documentation
, - "title": "Investigation notes", + "title": "Investigation guide", }, ] } @@ -430,7 +430,7 @@ exports[`description_step StepRuleDescriptionComponent renders correctly against # this is some markdown documentation
, - "title": "Investigation notes", + "title": "Investigation guide", }, ] } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.test.tsx index 7a3f0105d3d15..af946c6f02cbb 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.test.tsx @@ -22,6 +22,7 @@ import { buildSeverityDescription, buildUrlsDescription, buildNoteDescription, + buildRuleTypeDescription, } from './helpers'; import { ListItems } from './types'; @@ -385,4 +386,30 @@ describe('helpers', () => { expect(result).toHaveLength(0); }); }); + + describe('buildRuleTypeDescription', () => { + it('returns the label for a machine_learning type', () => { + const [result]: ListItems[] = buildRuleTypeDescription('Test label', 'machine_learning'); + + expect(result.title).toEqual('Test label'); + }); + + it('returns a humanized description for a machine_learning type', () => { + const [result]: ListItems[] = buildRuleTypeDescription('Test label', 'machine_learning'); + + expect(result.description).toEqual('Machine Learning'); + }); + + it('returns the label for a query type', () => { + const [result]: ListItems[] = buildRuleTypeDescription('Test label', 'query'); + + expect(result.title).toEqual('Test label'); + }); + + it('returns a humanized description for a query type', () => { + const [result]: ListItems[] = buildRuleTypeDescription('Test label', 'query'); + + expect(result.description).toEqual('Query'); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx index 7b22078c89d1b..f9b255a95d869 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/helpers.tsx @@ -27,6 +27,8 @@ import * as i18n from './translations'; import { BuildQueryBarDescription, BuildThreatDescription, ListItems } from './types'; import { SeverityBadge } from '../severity_badge'; import ListTreeIcon from './assets/list_tree_icon.svg'; +import { RuleType } from '../../../../../containers/detection_engine/rules'; +import { assertUnreachable } from '../../../../../lib/helpers'; const NoteDescriptionContainer = styled(EuiFlexItem)` height: 105px; @@ -266,3 +268,27 @@ export const buildNoteDescription = (label: string, note: string): ListItems[] = } return []; }; + +export const buildRuleTypeDescription = (label: string, ruleType: RuleType): ListItems[] => { + switch (ruleType) { + case 'machine_learning': { + return [ + { + title: label, + description: i18n.ML_TYPE_DESCRIPTION, + }, + ]; + } + case 'query': + case 'saved_query': { + return [ + { + title: label, + description: i18n.QUERY_TYPE_DESCRIPTION, + }, + ]; + } + default: + return assertUnreachable(ruleType); + } +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.test.tsx index 557da8677f777..8e8927cb7bbd1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.test.tsx @@ -27,6 +27,8 @@ import { schema } from '../step_about_rule/schema'; import { ListItems } from './types'; import { AboutStepRule } from '../../types'; +jest.mock('../../../../../lib/kibana'); + describe('description_step', () => { const setupMock = coreMock.createSetup(); const uiSettingsMock = (pinnedByDefault: boolean) => (key: string) => { @@ -41,13 +43,6 @@ describe('description_step', () => { let mockAboutStep: AboutStepRule; beforeEach(() => { - // jest carries state between mocked implementations when using - // spyOn. So now we're doing all three of these. - // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 - jest.resetAllMocks(); - jest.restoreAllMocks(); - jest.clearAllMocks(); - setupMock.uiSettings.get.mockImplementation(uiSettingsMock(true)); mockFilterManager = new FilterManager(setupMock.uiSettings); mockAboutStep = mockAboutStepRule(); @@ -466,12 +461,12 @@ describe('description_step', () => { test('returns default "note" description', () => { const result: ListItems[] = getDescriptionItem( 'note', - 'Investigation notes', + 'Investigation guide', mockAboutStep, mockFilterManager ); - expect(result[0].title).toEqual('Investigation notes'); + expect(result[0].title).toEqual('Investigation guide'); expect(React.isValidElement(result[0].description)).toBeTruthy(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx index 43b4a5f781b89..69c4ee1017155 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/index.tsx @@ -15,6 +15,7 @@ import { esFilters, FilterManager, } from '../../../../../../../../../../src/plugins/data/public'; +import { RuleType } from '../../../../../containers/detection_engine/rules'; import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/translations'; import { useKibana } from '../../../../../lib/kibana'; import { IMitreEnterpriseAttack } from '../../types'; @@ -29,7 +30,10 @@ import { buildUnorderedListArrayDescription, buildUrlsDescription, buildNoteDescription, + buildRuleTypeDescription, } from './helpers'; +import { useSiemJobs } from '../../../../../components/ml_popover/hooks/use_siem_jobs'; +import { buildMlJobDescription } from './ml_job_description'; const DescriptionListContainer = styled(EuiDescriptionList)` &.euiDescriptionList--column .euiDescriptionList__title { @@ -55,15 +59,22 @@ export const StepRuleDescriptionComponent: React.FC = }) => { const kibana = useKibana(); const [filterManager] = useState(new FilterManager(kibana.services.uiSettings)); + const [, siemJobs] = useSiemJobs(true); const keys = Object.keys(schema); - const listItems = keys.reduce( - (acc: ListItems[], key: string) => [ - ...acc, - ...buildListItems(data, pick(key, schema), filterManager, indexPatterns), - ], - [] - ); + const listItems = keys.reduce((acc: ListItems[], key: string) => { + if (key === 'machineLearningJobId') { + return [ + ...acc, + buildMlJobDescription( + get(key, data) as string, + (get(key, schema) as { label: string }).label, + siemJobs + ), + ]; + } + return [...acc, ...buildListItems(data, pick(key, schema), filterManager, indexPatterns)]; + }, []); if (columns === 'multi') { return ( @@ -176,6 +187,9 @@ export const getDescriptionItem = ( } else if (field === 'note') { const val: string = get(field, data); return buildNoteDescription(label, val); + } else if (field === 'ruleType') { + const ruleType: RuleType = get(field, data); + return buildRuleTypeDescription(label, ruleType); } const description: string = get(field, data); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/ml_job_description.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/ml_job_description.tsx new file mode 100644 index 0000000000000..947bf29c07148 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/ml_job_description.tsx @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import styled from 'styled-components'; +import { EuiBadge, EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; + +import { useKibana } from '../../../../../lib/kibana'; +import { SiemJob } from '../../../../../components/ml_popover/types'; +import { ListItems } from './types'; +import { isJobStarted } from '../../../../../components/ml/helpers'; +import { ML_JOB_STARTED, ML_JOB_STOPPED } from './translations'; + +enum MessageLevels { + info = 'info', + warning = 'warning', + error = 'error', +} + +const AuditIcon: React.FC<{ + message: SiemJob['auditMessage']; +}> = ({ message }) => { + if (!message) { + return null; + } + + let color = 'primary'; + let icon = 'alert'; + + if (message.level === MessageLevels.info) { + icon = 'iInCircle'; + } else if (message.level === MessageLevels.warning) { + color = 'warning'; + } else if (message.level === MessageLevels.error) { + color = 'danger'; + } + + return ( + + + + ); +}; + +export const JobStatusBadge: React.FC<{ job: SiemJob }> = ({ job }) => { + const isStarted = isJobStarted(job.jobState, job.datafeedState); + const color = isStarted ? 'secondary' : 'danger'; + const text = isStarted ? ML_JOB_STARTED : ML_JOB_STOPPED; + + return ( + + {text} + + ); +}; + +const JobLink = styled(EuiLink)` + margin-right: ${({ theme }) => theme.eui.euiSizeS}; +`; + +const Wrapper = styled.div` + overflow: hidden; +`; + +export const MlJobDescription: React.FC<{ job: SiemJob }> = ({ job }) => { + const jobUrl = useKibana().services.application.getUrlForApp('ml#/jobs'); + + return ( + +
+ + {job.id} + + +
+ +
+ ); +}; + +export const buildMlJobDescription = ( + jobId: string, + label: string, + siemJobs: SiemJob[] +): ListItems => { + const siemJob = siemJobs.find(job => job.id === jobId); + + return { + title: label, + description: siemJob ? : jobId, + }; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/translations.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/translations.tsx index 9695fd21067ee..b494d824679f3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/translations.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/description_step/translations.tsx @@ -17,3 +17,31 @@ export const QUERY_LABEL = i18n.translate('xpack.siem.detectionEngine.createRule export const SAVED_ID_LABEL = i18n.translate('xpack.siem.detectionEngine.createRule.savedIdLabel', { defaultMessage: 'Saved query name', }); + +export const ML_TYPE_DESCRIPTION = i18n.translate( + 'xpack.siem.detectionEngine.createRule.mlRuleTypeDescription', + { + defaultMessage: 'Machine Learning', + } +); + +export const QUERY_TYPE_DESCRIPTION = i18n.translate( + 'xpack.siem.detectionEngine.createRule.queryRuleTypeDescription', + { + defaultMessage: 'Query', + } +); + +export const ML_JOB_STARTED = i18n.translate( + 'xpack.siem.detectionEngine.ruleDescription.mlJobStartedDescription', + { + defaultMessage: 'Started', + } +); + +export const ML_JOB_STOPPED = i18n.translate( + 'xpack.siem.detectionEngine.ruleDescription.mlJobStoppedDescription', + { + defaultMessage: 'Stopped', + } +); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/translations.ts deleted file mode 100644 index dab1c9490591f..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/import_rule_modal/translations.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const IMPORT_RULE = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.importRuleTitle', - { - defaultMessage: 'Import rule', - } -); - -export const SELECT_RULE = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.selectRuleDescription', - { - defaultMessage: 'Select a SIEM rule (as exported from the Detection Engine UI) to import', - } -); - -export const INITIAL_PROMPT_TEXT = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.initialPromptTextDescription', - { - defaultMessage: 'Select or drag and drop a valid rules_export.ndjson file', - } -); - -export const OVERWRITE_WITH_SAME_NAME = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.overwriteDescription', - { - defaultMessage: 'Automatically overwrite saved objects with the same rule ID', - } -); - -export const CANCEL_BUTTON = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.cancelTitle', - { - defaultMessage: 'Cancel', - } -); - -export const SUCCESSFULLY_IMPORTED_RULES = (totalRules: number) => - i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.successfullyImportedRulesTitle', - { - values: { totalRules }, - defaultMessage: - 'Successfully imported {totalRules} {totalRules, plural, =1 {rule} other {rules}}', - } - ); - -export const IMPORT_FAILED = i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.importFailedTitle', - { - defaultMessage: 'Failed to import rules', - } -); - -export const IMPORT_FAILED_DETAILED = (ruleId: string, statusCode: number, message: string) => - i18n.translate( - 'xpack.siem.detectionEngine.components.importRuleModal.importFailedDetailedTitle', - { - values: { ruleId, statusCode, message }, - defaultMessage: 'Rule ID: {ruleId}\n Status Code: {statusCode}\n Message: {message}', - } - ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/ml_job_select/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/ml_job_select/index.tsx index bc32162c2660b..3d253b71b53d6 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/ml_job_select/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/ml_job_select/index.tsx @@ -5,12 +5,39 @@ */ import React, { useCallback } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSuperSelect, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiLink, + EuiSuperSelect, + EuiText, +} from '@elastic/eui'; import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../../shared_imports'; import { useSiemJobs } from '../../../../../components/ml_popover/hooks/use_siem_jobs'; +import { useKibana } from '../../../../../lib/kibana'; +import { ML_JOB_SELECT_PLACEHOLDER_TEXT } from '../step_define_rule/translations'; -const JobDisplay = ({ title, description }: { title: string; description: string }) => ( +const HelpText: React.FC<{ href: string }> = ({ href }) => ( + + + + ), + }} + /> +); + +const JobDisplay: React.FC<{ title: string; description: string }> = ({ title, description }) => ( <> {title} @@ -28,23 +55,32 @@ export const MlJobSelect: React.FC = ({ describedByIds = [], f const jobId = field.value as string; const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); const [isLoading, siemJobs] = useSiemJobs(false); + const mlUrl = useKibana().services.application.getUrlForApp('ml'); const handleJobChange = useCallback( (machineLearningJobId: string) => { field.setValue(machineLearningJobId); }, [field] ); + const placeholderOption = { + value: 'placeholder', + inputDisplay: ML_JOB_SELECT_PLACEHOLDER_TEXT, + dropdownDisplay: ML_JOB_SELECT_PLACEHOLDER_TEXT, + disabled: true, + }; - const options = siemJobs.map(job => ({ + const jobOptions = siemJobs.map(job => ({ value: job.id, inputDisplay: job.id, dropdownDisplay: , })); + const options = [placeholderOption, ...jobOptions]; + return ( } isInvalid={isInvalid} error={errorMessage} data-test-subj="mlJobSelect" @@ -57,7 +93,7 @@ export const MlJobSelect: React.FC = ({ describedByIds = [], f isLoading={isLoading} onChange={handleJobChange} options={options} - valueOfSelected={jobId} + valueOfSelected={jobId || 'placeholder'} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000000..433b38773c14a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/__snapshots__/index.test.tsx.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NextStep renders correctly against snapshot 1`] = ` + + + + + + Continue + + + + +`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.test.js b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.test.tsx similarity index 63% rename from x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.test.js rename to x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.test.tsx index 1cd1dc6e4d715..552ede90cd018 100644 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.test.js +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.test.tsx @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { shallow } from 'enzyme'; -import { ClickOutside } from './click_outside'; +import React from 'react'; +import { NextStep } from './index'; -describe('ClickOutside', () => { - test('snapshot', () => { - const wrapper = shallow( {}} />); +describe('NextStep', () => { + test('renders correctly against snapshot', () => { + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.tsx new file mode 100644 index 0000000000000..11332e7af9266 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/next_step/index.tsx @@ -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 React from 'react'; +import { EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; +import * as RuleI18n from '../../translations'; + +interface NextStepProps { + onClick: () => Promise; + isDisabled: boolean; + dataTestSubj?: string; +} + +export const NextStep = React.memo( + ({ onClick, isDisabled, dataTestSubj = 'nextStep-continue' }) => ( + <> + + + + + {RuleI18n.CONTINUE} + + + + + ) +); + +NextStep.displayName = 'NextStep'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx index 923ec3a7f0066..27d668dc6166c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/pick_timeline/index.tsx @@ -59,7 +59,6 @@ export const PickTimeline = ({ helpText={field.helpText} error={errorMessage} isInvalid={isInvalid} - fullWidth data-test-subj={dataTestSubj} describedByIds={idAria ? [idAria] : undefined} > diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_actions_field/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_actions_field/index.tsx new file mode 100644 index 0000000000000..a746d381c494c --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_actions_field/index.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback, useEffect, useState } from 'react'; +import deepMerge from 'deepmerge'; + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { loadActionTypes } from '../../../../../../../../../plugins/triggers_actions_ui/public/application/lib/action_connector_api'; +import { SelectField } from '../../../../../shared_imports'; +import { + ActionForm, + ActionType, +} from '../../../../../../../../../plugins/triggers_actions_ui/public'; +import { AlertAction } from '../../../../../../../../../plugins/alerting/common'; +import { useKibana } from '../../../../../lib/kibana'; +import { NOTIFICATION_SUPPORTED_ACTION_TYPES_IDS } from '../../../../../../common/constants'; + +type ThrottleSelectField = typeof SelectField; + +const DEFAULT_ACTION_GROUP_ID = 'default'; +const DEFAULT_ACTION_MESSAGE = + 'Rule {{context.rule.name}} generated {{state.signals_count}} signals'; + +export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables }) => { + const [supportedActionTypes, setSupportedActionTypes] = useState(); + const { + http, + triggers_actions_ui: { actionTypeRegistry }, + notifications, + } = useKibana().services; + + const setActionIdByIndex = useCallback( + (id: string, index: number) => { + const updatedActions = [...(field.value as Array>)]; + updatedActions[index] = deepMerge(updatedActions[index], { id }); + field.setValue(updatedActions); + }, + [field] + ); + + const setAlertProperty = useCallback( + (updatedActions: AlertAction[]) => field.setValue(updatedActions), + [field] + ); + + const setActionParamsProperty = useCallback( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (key: string, value: any, index: number) => { + const updatedActions = [...(field.value as AlertAction[])]; + updatedActions[index].params[key] = value; + field.setValue(updatedActions); + }, + [field] + ); + + useEffect(() => { + (async function() { + const actionTypes = await loadActionTypes({ http }); + const supportedTypes = actionTypes.filter(actionType => + NOTIFICATION_SUPPORTED_ACTION_TYPES_IDS.includes(actionType.id) + ); + setSupportedActionTypes(supportedTypes); + })(); + }, []); + + if (!supportedActionTypes) return <>; + + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx index 219b3d6dc4d58..4ccde78f3cda7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx @@ -48,14 +48,16 @@ interface SelectRuleTypeProps { describedByIds?: string[]; field: FieldHook; hasValidLicense?: boolean; + isMlAdmin?: boolean; isReadOnly?: boolean; } export const SelectRuleType: React.FC = ({ describedByIds = [], field, - hasValidLicense = false, isReadOnly = false, + hasValidLicense = false, + isMlAdmin = false, }) => { const ruleType = field.value as RuleType; const setType = useCallback( @@ -66,7 +68,7 @@ export const SelectRuleType: React.FC = ({ ); const setMl = useCallback(() => setType('machine_learning'), [setType]); const setQuery = useCallback(() => setType('query'), [setType]); - const mlCardDisabled = isReadOnly || !hasValidLicense; + const mlCardDisabled = isReadOnly || !hasValidLicense || !isMlAdmin; return ( = ({ } @@ -90,6 +93,7 @@ export const SelectRuleType: React.FC = ({ } icon={} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.test.tsx index 0ed479e235151..3c28e697789ac 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.test.tsx @@ -15,6 +15,17 @@ import { stepAboutDefaultValue } from './default_value'; const theme = () => ({ eui: euiDarkVars, darkMode: true }); +/* eslint-disable no-console */ +// Silence until enzyme fixed to use ReactTestUtils.act() +const originalError = console.error; +beforeAll(() => { + console.error = jest.fn(); +}); +afterAll(() => { + console.error = originalError; +}); +/* eslint-enable no-console */ + describe('StepAboutRuleComponent', () => { test('it renders StepRuleDescription if isReadOnlyView is true and "name" property exists', () => { const wrapper = shallow( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx index 58b6ca54f5bbd..eaf543780d777 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx @@ -4,22 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiAccordion, - EuiButton, - EuiHorizontalRule, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiButtonEmpty, -} from '@elastic/eui'; +import { EuiAccordion, EuiFlexItem, EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; import { setFieldValue } from '../../helpers'; import { RuleStepProps, RuleStep, AboutStepRule } from '../../types'; -import * as RuleI18n from '../../translations'; import { AddItem } from '../add_item_form'; import { StepRuleDescription } from '../description_step'; import { AddMitreThreat } from '../mitre'; @@ -38,6 +29,7 @@ import { isUrlInvalid } from './helpers'; import { schema } from './schema'; import * as I18n from './translations'; import { StepContentWrapper } from '../step_content_wrapper'; +import { NextStep } from '../next_step'; import { MarkdownEditorForm } from '../../../../../components/markdown_editor/form'; const CommonUseField = getUseField({ component: Field }); @@ -276,27 +268,9 @@ const StepAboutRuleComponent: FC = ({ + {!isUpdateView && ( - <> - - - - - {RuleI18n.CONTINUE} - - - - + )} ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx index 8cb38b9dc7393..7c088c068c9b2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/schema.tsx @@ -178,12 +178,12 @@ export const schema: FormSchema = { }, note: { type: FIELD_TYPES.TEXTAREA, - label: i18n.translate('xpack.siem.detectionEngine.createRule.stepAboutRule.noteLabel', { - defaultMessage: 'Investigation notes', + label: i18n.translate('xpack.siem.detectionEngine.createRule.stepAboutRule.guideLabel', { + defaultMessage: 'Investigation guide', }), - helpText: i18n.translate('xpack.siem.detectionEngine.createRule.stepAboutRule.noteHelpText', { + helpText: i18n.translate('xpack.siem.detectionEngine.createRule.stepAboutRule.guideHelpText', { defaultMessage: - 'Provide helpful information for analysts that are performing a signal investigation. These notes will appear on both the rule details page and in timelines created from signals generated by this rule.', + 'Provide helpful information for analysts that are performing a signal investigation. This guide will appear on both the rule details page and in timelines created from signals generated by this rule.', }), labelAppend: OptionalFieldLabel, }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts index dfa60268e903a..0b1e712c663f3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/translations.ts @@ -72,6 +72,6 @@ export const URL_FORMAT_INVALID = i18n.translate( export const ADD_RULE_NOTE_HELP_TEXT = i18n.translate( 'xpack.siem.detectionEngine.createRule.stepAboutrule.noteHelpText', { - defaultMessage: 'Add rule investigation notes...', + defaultMessage: 'Add rule investigation guide...', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.test.tsx index 4a4e96ec74902..76a3c590a62a6 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.test.tsx @@ -15,19 +15,14 @@ import { HeaderSection } from '../../../../../components/header_section'; import { StepAboutRule } from '../step_about_rule/'; import { AboutStepRule } from '../../types'; +jest.mock('../../../../../lib/kibana'); + const theme = () => ({ eui: euiDarkVars, darkMode: true }); describe('StepAboutRuleToggleDetails', () => { let mockRule: AboutStepRule; beforeEach(() => { - // jest carries state between mocked implementations when using - // spyOn. So now we're doing all three of these. - // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 - jest.resetAllMocks(); - jest.restoreAllMocks(); - jest.clearAllMocks(); - mockRule = mockAboutStepRule(); }); @@ -141,7 +136,7 @@ describe('StepAboutRuleToggleDetails', () => { expect(wrapper.find('EuiButtonGroup[idSelected="notes"]').exists()).toBeFalsy(); wrapper - .find('input[title="Investigation notes"]') + .find('input[title="Investigation guide"]') .at(0) .simulate('change', { target: { value: 'notes' } }); @@ -164,7 +159,7 @@ describe('StepAboutRuleToggleDetails', () => { ); wrapper - .find('input[title="Investigation notes"]') + .find('input[title="Investigation guide"]') .at(0) .simulate('change', { target: { value: 'notes' } }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.tsx index c61566cb841e8..5d9803214fa0a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/index.tsx @@ -15,7 +15,7 @@ import { EuiFlexGroup, EuiResizeObserver, } from '@elastic/eui'; -import React, { memo, useState } from 'react'; +import React, { memo, useCallback, useState } from 'react'; import styled from 'styled-components'; import { isEmpty } from 'lodash/fp'; @@ -71,9 +71,12 @@ const StepAboutRuleToggleDetailsComponent: React.FC = ({ const [selectedToggleOption, setToggleOption] = useState('details'); const [aboutPanelHeight, setAboutPanelHeight] = useState(0); - const onResize = (e: { height: number; width: number }) => { - setAboutPanelHeight(e.height); - }; + const onResize = useCallback( + (e: { height: number; width: number }) => { + setAboutPanelHeight(e.height); + }, + [setAboutPanelHeight] + ); return ( @@ -85,7 +88,7 @@ const StepAboutRuleToggleDetailsComponent: React.FC = ({ )} {stepData != null && stepDataDetails != null && ( - + {!isEmpty(stepDataDetails.note) && stepDataDetails.note.trim() !== '' && ( = ({ )} - + {selectedToggleOption === 'details' ? ( {resizeRef => ( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/translations.ts index fa725366210de..79c5eb12d4663 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule_details/translations.ts @@ -20,8 +20,8 @@ export const ABOUT_TEXT = i18n.translate( ); export const ABOUT_PANEL_NOTES_TAB = i18n.translate( - 'xpack.siem.detectionEngine.details.stepAboutRule.investigationNotesLabel', + 'xpack.siem.detectionEngine.details.stepAboutRule.investigationGuideLabel', { - defaultMessage: 'Investigation notes', + defaultMessage: 'Investigation guide', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx index 4027c98a52ace..6c46ab0b171a2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx @@ -4,15 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonEmpty, - EuiHorizontalRule, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiButton, -} from '@elastic/eui'; -import React, { FC, memo, useCallback, useState, useEffect, useContext } from 'react'; +import { EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; +import React, { FC, memo, useCallback, useState, useEffect } from 'react'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; @@ -20,10 +13,9 @@ import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/pu import { useFetchIndexPatterns } from '../../../../../containers/detection_engine/rules'; import { DEFAULT_INDEX_KEY } from '../../../../../../common/constants'; import { DEFAULT_TIMELINE_TITLE } from '../../../../../components/timeline/translations'; -import { MlCapabilitiesContext } from '../../../../../components/ml/permissions/ml_capabilities_provider'; +import { useMlCapabilities } from '../../../../../components/ml_popover/hooks/use_ml_capabilities'; import { useUiSetting$ } from '../../../../../lib/kibana'; import { setFieldValue, isMlRule } from '../../helpers'; -import * as RuleI18n from '../../translations'; import { DefineStepRule, RuleStep, RuleStepProps } from '../../types'; import { StepRuleDescription } from '../description_step'; import { QueryBarDefineRule } from '../query_bar'; @@ -32,6 +24,7 @@ import { AnomalyThresholdSlider } from '../anomaly_threshold_slider'; import { MlJobSelect } from '../ml_job_select'; import { PickTimeline } from '../pick_timeline'; import { StepContentWrapper } from '../step_content_wrapper'; +import { NextStep } from '../next_step'; import { Field, Form, @@ -44,6 +37,7 @@ import { import { schema } from './schema'; import * as i18n from './translations'; import { filterRuleFieldsForType, RuleFields } from '../../create/helpers'; +import { hasMlAdminPermissions } from '../../../../../components/ml/permissions/has_ml_admin_permissions'; const CommonUseField = getUseField({ component: Field }); @@ -92,7 +86,7 @@ const StepDefineRuleComponent: FC = ({ setForm, setStepData, }) => { - const mlCapabilities = useContext(MlCapabilitiesContext); + const mlCapabilities = useMlCapabilities(); const [openTimelineSearch, setOpenTimelineSearch] = useState(false); const [indexModified, setIndexModified] = useState(false); const [localIsMlRule, setIsMlRule] = useState(false); @@ -169,8 +163,9 @@ const StepDefineRuleComponent: FC = ({ component={SelectRuleType} componentProps={{ describedByIds: ['detectionEngineStepDefineRuleType'], - hasValidLicense: mlCapabilities.isPlatinumOrTrialLicense, isReadOnly: isUpdateView, + hasValidLicense: mlCapabilities.isPlatinumOrTrialLicense, + isMlAdmin: hasMlAdminPermissions(mlCapabilities), }} /> @@ -269,22 +264,9 @@ const StepDefineRuleComponent: FC = ({ + {!isUpdateView && ( - <> - - - - - {RuleI18n.CONTINUE} - - - - + )} ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/translations.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/translations.tsx index 8394f090e346c..1d8821aceb249 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/translations.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/translations.tsx @@ -55,3 +55,10 @@ export const IMPORT_TIMELINE_QUERY = i18n.translate( defaultMessage: 'Import query from saved timeline', } ); + +export const ML_JOB_SELECT_PLACEHOLDER_TEXT = i18n.translate( + 'xpack.siem.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText', + { + defaultMessage: 'Select a job', + } +); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/index.tsx new file mode 100644 index 0000000000000..9c16a61822662 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/index.tsx @@ -0,0 +1,184 @@ +/* + * 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 { EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, EuiButton, EuiSpacer } from '@elastic/eui'; +import React, { FC, memo, useCallback, useEffect, useMemo, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; + +import { setFieldValue } from '../../helpers'; +import { RuleStep, RuleStepProps, ActionsStepRule } from '../../types'; +import { StepRuleDescription } from '../description_step'; +import { Form, UseField, useForm } from '../../../../../shared_imports'; +import { StepContentWrapper } from '../step_content_wrapper'; +import { ThrottleSelectField, THROTTLE_OPTIONS } from '../throttle_select_field'; +import { RuleActionsField } from '../rule_actions_field'; +import { useKibana } from '../../../../../lib/kibana'; +import { schema } from './schema'; +import * as I18n from './translations'; + +interface StepRuleActionsProps extends RuleStepProps { + defaultValues?: ActionsStepRule | null; + actionMessageParams: string[]; +} + +const stepActionsDefaultValue = { + enabled: true, + isNew: true, + actions: [], + kibanaSiemAppUrl: '', + throttle: THROTTLE_OPTIONS[0].value, +}; + +const GhostFormField = () => <>; + +const StepRuleActionsComponent: FC = ({ + addPadding = false, + defaultValues, + isReadOnlyView, + isLoading, + isUpdateView = false, + setStepData, + setForm, + actionMessageParams, +}) => { + const [myStepData, setMyStepData] = useState(stepActionsDefaultValue); + const { + services: { application }, + } = useKibana(); + + const { form } = useForm({ + defaultValue: myStepData, + options: { stripEmptyFields: false }, + schema, + }); + + const kibanaAbsoluteUrl = useMemo(() => application.getUrlForApp('siem', { absolute: true }), [ + application, + ]); + + const onSubmit = useCallback( + async (enabled: boolean) => { + if (setStepData) { + setStepData(RuleStep.ruleActions, null, false); + const { isValid: newIsValid, data } = await form.submit(); + if (newIsValid) { + setStepData(RuleStep.ruleActions, { ...data, enabled }, newIsValid); + setMyStepData({ ...data, isNew: false } as ActionsStepRule); + } + } + }, + [form] + ); + + useEffect(() => { + const { isNew, ...initDefaultValue } = myStepData; + if (defaultValues != null && !deepEqual(initDefaultValue, defaultValues)) { + const myDefaultValues = { + ...defaultValues, + isNew: false, + }; + setMyStepData(myDefaultValues); + setFieldValue(form, schema, myDefaultValues); + } + }, [defaultValues]); + + useEffect(() => { + if (setForm != null) { + setForm(RuleStep.ruleActions, form); + } + }, [form]); + + const updateThrottle = useCallback(throttle => setMyStepData({ ...myStepData, throttle }), [ + myStepData, + setMyStepData, + ]); + + const throttleFieldComponentProps = useMemo( + () => ({ + idAria: 'detectionEngineStepRuleActionsThrottle', + isDisabled: isLoading, + dataTestSubj: 'detectionEngineStepRuleActionsThrottle', + hasNoInitialSelection: false, + handleChange: updateThrottle, + euiFieldProps: { + options: THROTTLE_OPTIONS, + }, + }), + [isLoading, updateThrottle] + ); + + return isReadOnlyView && myStepData != null ? ( + + + + ) : ( + <> + +
+ + {myStepData.throttle !== stepActionsDefaultValue.throttle && ( + <> + + + + + )} + +
+ + {!isUpdateView && ( + <> + + + + + {I18n.COMPLETE_WITHOUT_ACTIVATING} + + + + + {I18n.COMPLETE_WITH_ACTIVATING} + + + + + )} + + ); +}; + +export const StepRuleActions = memo(StepRuleActionsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/schema.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/schema.tsx new file mode 100644 index 0000000000000..511427978db3a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/schema.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +import { FormSchema } from '../../../../../shared_imports'; + +export const schema: FormSchema = { + actions: {}, + kibanaSiemAppUrl: {}, + throttle: { + label: i18n.translate( + 'xpack.siem.detectionEngine.createRule.stepRuleActions.fieldThrottleLabel', + { + defaultMessage: 'Actions frequency', + } + ), + helpText: i18n.translate( + 'xpack.siem.detectionEngine.createRule.stepRuleActions.fieldThrottleHelpText', + { + defaultMessage: + 'Select when automated actions should be performed if a rule evaluates as true.', + } + ), + }, +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/translations.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/translations.tsx new file mode 100644 index 0000000000000..67bcc1af8150b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_rule_actions/translations.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const COMPLETE_WITHOUT_ACTIVATING = i18n.translate( + 'xpack.siem.detectionEngine.createRule. stepScheduleRule.completeWithoutActivatingTitle', + { + defaultMessage: 'Create rule without activating it', + } +); + +export const COMPLETE_WITH_ACTIVATING = i18n.translate( + 'xpack.siem.detectionEngine.createRule. stepScheduleRule.completeWithActivatingTitle', + { + defaultMessage: 'Create & activate rule', + } +); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx index e365443a79fb8..de9abcefdea2e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; import deepEqual from 'fast-deep-equal'; import styled from 'styled-components'; @@ -15,8 +14,8 @@ import { StepRuleDescription } from '../description_step'; import { ScheduleItem } from '../schedule_item_form'; import { Form, UseField, useForm } from '../../../../../shared_imports'; import { StepContentWrapper } from '../step_content_wrapper'; +import { NextStep } from '../next_step'; import { schema } from './schema'; -import * as I18n from './translations'; interface StepScheduleRuleProps extends RuleStepProps { defaultValues?: ScheduleStepRule | null; @@ -27,7 +26,6 @@ const RestrictedWidthContainer = styled.div` `; const stepScheduleDefaultValue = { - enabled: true, interval: '5m', isNew: true, from: '1m', @@ -51,19 +49,16 @@ const StepScheduleRuleComponent: FC = ({ schema, }); - const onSubmit = useCallback( - async (enabled: boolean) => { - if (setStepData) { - setStepData(RuleStep.scheduleRule, null, false); - const { isValid: newIsValid, data } = await form.submit(); - if (newIsValid) { - setStepData(RuleStep.scheduleRule, { ...data, enabled }, newIsValid); - setMyStepData({ ...data, isNew: false } as ScheduleStepRule); - } + const onSubmit = useCallback(async () => { + if (setStepData) { + setStepData(RuleStep.scheduleRule, null, false); + const { isValid: newIsValid, data } = await form.submit(); + if (newIsValid) { + setStepData(RuleStep.scheduleRule, { ...data }, newIsValid); + setMyStepData({ ...data, isNew: false } as ScheduleStepRule); } - }, - [form] - ); + } + }, [form]); useEffect(() => { const { isNew, ...initDefaultValue } = myStepData; @@ -118,37 +113,7 @@ const StepScheduleRuleComponent: FC = ({ {!isUpdateView && ( - <> - - - - - {I18n.COMPLETE_WITHOUT_ACTIVATING} - - - - - {I18n.COMPLETE_WITH_ACTIVATING} - - - - + )} ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/throttle_select_field/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/throttle_select_field/index.tsx new file mode 100644 index 0000000000000..0cf15c41a0f91 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/throttle_select_field/index.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback } from 'react'; + +import { + NOTIFICATION_THROTTLE_RULE, + NOTIFICATION_THROTTLE_NO_ACTIONS, +} from '../../../../../../common/constants'; +import { SelectField } from '../../../../../shared_imports'; + +export const THROTTLE_OPTIONS = [ + { value: NOTIFICATION_THROTTLE_NO_ACTIONS, text: 'Perform no actions' }, + { value: NOTIFICATION_THROTTLE_RULE, text: 'On each rule execution' }, + { value: '1h', text: 'Hourly' }, + { value: '1d', text: 'Daily' }, + { value: '7d', text: 'Weekly' }, +]; + +type ThrottleSelectField = typeof SelectField; + +export const ThrottleSelectField: ThrottleSelectField = props => { + const onChange = useCallback( + e => { + const throttle = e.target.value; + props.field.setValue(throttle); + props.handleChange(throttle); + }, + [props.field.setValue, props.handleChange] + ); + const newEuiFieldProps = { ...props.euiFieldProps, onChange }; + return ; +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.test.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.test.ts index dc0459c54adb0..212147ec6d4d8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.test.ts @@ -9,7 +9,9 @@ import { DefineStepRuleJson, ScheduleStepRuleJson, AboutStepRuleJson, + ActionsStepRuleJson, AboutStepRule, + ActionsStepRule, ScheduleStepRule, DefineStepRule, } from '../types'; @@ -18,6 +20,7 @@ import { formatDefineStepData, formatScheduleStepData, formatAboutStepData, + formatActionsStepData, formatRule, filterRuleFieldsForType, } from './helpers'; @@ -26,6 +29,7 @@ import { mockQueryBar, mockScheduleStepRule, mockAboutStepRule, + mockActionsStepRule, } from '../all/__mocks__/mock'; describe('helpers', () => { @@ -241,7 +245,6 @@ describe('helpers', () => { test('returns formatted object as ScheduleStepRuleJson', () => { const result: ScheduleStepRuleJson = formatScheduleStepData(mockData); const expected = { - enabled: false, from: 'now-660s', to: 'now', interval: '5m', @@ -260,7 +263,6 @@ describe('helpers', () => { delete mockStepData.to; const result: ScheduleStepRuleJson = formatScheduleStepData(mockStepData); const expected = { - enabled: false, from: 'now-660s', to: 'now', interval: '5m', @@ -279,7 +281,6 @@ describe('helpers', () => { }; const result: ScheduleStepRuleJson = formatScheduleStepData(mockStepData); const expected = { - enabled: false, from: 'now-660s', to: 'now', interval: '5m', @@ -298,7 +299,6 @@ describe('helpers', () => { }; const result: ScheduleStepRuleJson = formatScheduleStepData(mockStepData); const expected = { - enabled: false, from: 'now-300s', to: 'now', interval: '5m', @@ -317,7 +317,6 @@ describe('helpers', () => { }; const result: ScheduleStepRuleJson = formatScheduleStepData(mockStepData); const expected = { - enabled: false, from: 'now-360s', to: 'now', interval: 'random', @@ -503,19 +502,164 @@ describe('helpers', () => { }); }); + describe('formatActionsStepData', () => { + let mockData: ActionsStepRule; + + beforeEach(() => { + mockData = mockActionsStepRule(); + }); + + test('returns formatted object as ActionsStepRuleJson', () => { + const result: ActionsStepRuleJson = formatActionsStepData(mockData); + const expected = { + actions: [], + enabled: false, + meta: { + throttle: 'no_actions', + kibanaSiemAppUrl: 'http://localhost:5601/app/siem', + }, + throttle: null, + }; + + expect(result).toEqual(expected); + }); + + test('returns proper throttle value for no_actions', () => { + const mockStepData = { + ...mockData, + throttle: 'no_actions', + }; + const result: ActionsStepRuleJson = formatActionsStepData(mockStepData); + const expected = { + actions: [], + enabled: false, + meta: { + throttle: mockStepData.throttle, + kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl, + }, + throttle: null, + }; + + expect(result).toEqual(expected); + }); + + test('returns proper throttle value for rule', () => { + const mockStepData = { + ...mockData, + throttle: 'rule', + actions: [ + { + group: 'default', + id: 'id', + actionTypeId: 'actionTypeId', + params: {}, + }, + ], + }; + const result: ActionsStepRuleJson = formatActionsStepData(mockStepData); + const expected = { + actions: [ + { + group: mockStepData.actions[0].group, + id: mockStepData.actions[0].id, + action_type_id: mockStepData.actions[0].actionTypeId, + params: mockStepData.actions[0].params, + }, + ], + enabled: false, + meta: { + throttle: mockStepData.throttle, + kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl, + }, + throttle: null, + }; + + expect(result).toEqual(expected); + }); + + test('returns proper throttle value for interval', () => { + const mockStepData = { + ...mockData, + throttle: '1d', + actions: [ + { + group: 'default', + id: 'id', + actionTypeId: 'actionTypeId', + params: {}, + }, + ], + }; + const result: ActionsStepRuleJson = formatActionsStepData(mockStepData); + const expected = { + actions: [ + { + group: mockStepData.actions[0].group, + id: mockStepData.actions[0].id, + action_type_id: mockStepData.actions[0].actionTypeId, + params: mockStepData.actions[0].params, + }, + ], + enabled: false, + meta: { + throttle: mockStepData.throttle, + kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl, + }, + throttle: mockStepData.throttle, + }; + + expect(result).toEqual(expected); + }); + + test('returns actions with action_type_id', () => { + const mockAction = { + group: 'default', + id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', + params: { message: 'ML Rule generated {{state.signals_count}} signals' }, + actionTypeId: '.slack', + }; + + const mockStepData = { + ...mockData, + actions: [mockAction], + }; + const result: ActionsStepRuleJson = formatActionsStepData(mockStepData); + const expected = { + actions: [ + { + group: mockAction.group, + id: mockAction.id, + params: mockAction.params, + action_type_id: mockAction.actionTypeId, + }, + ], + enabled: false, + meta: { + throttle: null, + kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl, + }, + throttle: null, + }; + + expect(result).toEqual(expected); + }); + }); + describe('formatRule', () => { let mockAbout: AboutStepRule; let mockDefine: DefineStepRule; let mockSchedule: ScheduleStepRule; + let mockActions: ActionsStepRule; beforeEach(() => { mockAbout = mockAboutStepRule(); mockDefine = mockDefineStepRule(); mockSchedule = mockScheduleStepRule(); + mockActions = mockActionsStepRule(); }); test('returns NewRule with type of saved_query when saved_id exists', () => { - const result: NewRule = formatRule(mockDefine, mockAbout, mockSchedule); + const result: NewRule = formatRule(mockDefine, mockAbout, mockSchedule, mockActions); expect(result.type).toEqual('saved_query'); }); @@ -528,13 +672,18 @@ describe('helpers', () => { saved_id: '', }, }; - const result: NewRule = formatRule(mockDefineStepRuleWithoutSavedId, mockAbout, mockSchedule); + const result: NewRule = formatRule( + mockDefineStepRuleWithoutSavedId, + mockAbout, + mockSchedule, + mockActions + ); expect(result.type).toEqual('query'); }); test('returns NewRule without id if ruleId does not exist', () => { - const result: NewRule = formatRule(mockDefine, mockAbout, mockSchedule); + const result: NewRule = formatRule(mockDefine, mockAbout, mockSchedule, mockActions); expect(result.id).toBeUndefined(); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts index f8900e6a1129e..7abe5a576c0e5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/helpers.ts @@ -6,16 +6,24 @@ import { has, isEmpty } from 'lodash/fp'; import moment from 'moment'; +import deepmerge from 'deepmerge'; +import { + NOTIFICATION_THROTTLE_RULE, + NOTIFICATION_THROTTLE_NO_ACTIONS, +} from '../../../../../common/constants'; import { NewRule, RuleType } from '../../../../containers/detection_engine/rules'; +import { transformAlertToRuleAction } from '../../../../../common/detection_engine/transform_actions'; import { AboutStepRule, DefineStepRule, ScheduleStepRule, + ActionsStepRule, DefineStepRuleJson, ScheduleStepRuleJson, AboutStepRuleJson, + ActionsStepRuleJson, } from '../types'; import { isMlRule } from '../helpers'; @@ -136,12 +144,39 @@ export const formatAboutStepData = (aboutStepData: AboutStepRule): AboutStepRule }; }; +export const getAlertThrottle = (throttle: string | null) => + throttle && ![NOTIFICATION_THROTTLE_NO_ACTIONS, NOTIFICATION_THROTTLE_RULE].includes(throttle) + ? throttle + : null; + +export const formatActionsStepData = (actionsStepData: ActionsStepRule): ActionsStepRuleJson => { + const { + actions = [], + enabled, + kibanaSiemAppUrl, + throttle = NOTIFICATION_THROTTLE_NO_ACTIONS, + } = actionsStepData; + + return { + actions: actions.map(transformAlertToRuleAction), + enabled, + throttle: actions.length ? getAlertThrottle(throttle) : null, + meta: { + throttle: actions.length ? throttle : NOTIFICATION_THROTTLE_NO_ACTIONS, + kibanaSiemAppUrl, + }, + }; +}; + export const formatRule = ( defineStepData: DefineStepRule, aboutStepData: AboutStepRule, - scheduleData: ScheduleStepRule -): NewRule => ({ - ...formatDefineStepData(defineStepData), - ...formatAboutStepData(aboutStepData), - ...formatScheduleStepData(scheduleData), -}); + scheduleData: ScheduleStepRule, + actionsData: ActionsStepRule +): NewRule => + deepmerge.all([ + formatDefineStepData(defineStepData), + formatAboutStepData(aboutStepData), + formatScheduleStepData(scheduleData), + formatActionsStepData(actionsData), + ]) as NewRule; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx index 67aaabfe70fda..0335216672915 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/create/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonEmpty, EuiAccordion, EuiHorizontalRule, EuiPanel, EuiSpacer } from '@elastic/eui'; -import React, { useCallback, useRef, useState } from 'react'; +import React, { useCallback, useRef, useState, useMemo } from 'react'; import { Redirect } from 'react-router-dom'; import styled, { StyledComponent } from 'styled-components'; @@ -21,14 +21,27 @@ import { FormData, FormHook } from '../../../../shared_imports'; import { StepAboutRule } from '../components/step_about_rule'; import { StepDefineRule } from '../components/step_define_rule'; import { StepScheduleRule } from '../components/step_schedule_rule'; +import { StepRuleActions } from '../components/step_rule_actions'; import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import * as RuleI18n from '../translations'; -import { redirectToDetections } from '../helpers'; -import { AboutStepRule, DefineStepRule, RuleStep, RuleStepData, ScheduleStepRule } from '../types'; +import { redirectToDetections, getActionMessageParams } from '../helpers'; +import { + AboutStepRule, + DefineStepRule, + RuleStep, + RuleStepData, + ScheduleStepRule, + ActionsStepRule, +} from '../types'; import { formatRule } from './helpers'; import * as i18n from './translations'; -const stepsRuleOrder = [RuleStep.defineRule, RuleStep.aboutRule, RuleStep.scheduleRule]; +const stepsRuleOrder = [ + RuleStep.defineRule, + RuleStep.aboutRule, + RuleStep.scheduleRule, + RuleStep.ruleActions, +]; const MyEuiPanel = styled(EuiPanel)<{ zindex?: number; @@ -79,22 +92,31 @@ const CreateRulePageComponent: React.FC = () => { const defineRuleRef = useRef(null); const aboutRuleRef = useRef(null); const scheduleRuleRef = useRef(null); + const ruleActionsRef = useRef(null); const stepsForm = useRef | null>>({ [RuleStep.defineRule]: null, [RuleStep.aboutRule]: null, [RuleStep.scheduleRule]: null, + [RuleStep.ruleActions]: null, }); const stepsData = useRef>({ [RuleStep.defineRule]: { isValid: false, data: {} }, [RuleStep.aboutRule]: { isValid: false, data: {} }, [RuleStep.scheduleRule]: { isValid: false, data: {} }, + [RuleStep.ruleActions]: { isValid: false, data: {} }, }); const [isStepRuleInReadOnlyView, setIsStepRuleInEditView] = useState>({ [RuleStep.defineRule]: false, [RuleStep.aboutRule]: false, [RuleStep.scheduleRule]: false, + [RuleStep.ruleActions]: false, }); const [{ isLoading, isSaved }, setRule] = usePersistRule(); + const actionMessageParams = useMemo( + () => + getActionMessageParams((stepsData.current['define-rule'].data as DefineStepRule).ruleType), + [stepsData.current['define-rule'].data] + ); const userHasNoPermissions = canUserCRUD != null && hasManageApiKey != null ? !canUserCRUD || !hasManageApiKey : false; @@ -103,7 +125,7 @@ const CreateRulePageComponent: React.FC = () => { stepsData.current[step] = { ...stepsData.current[step], data, isValid }; if (isValid) { const stepRuleIdx = stepsRuleOrder.findIndex(item => step === item); - if ([0, 1].includes(stepRuleIdx)) { + if ([0, 1, 2].includes(stepRuleIdx)) { if (isStepRuleInReadOnlyView[stepsRuleOrder[stepRuleIdx + 1]]) { setOpenAccordionId(stepsRuleOrder[stepRuleIdx + 1]); setIsStepRuleInEditView({ @@ -120,15 +142,17 @@ const CreateRulePageComponent: React.FC = () => { setOpenAccordionId(stepsRuleOrder[stepRuleIdx + 1]); } } else if ( - stepRuleIdx === 2 && + stepRuleIdx === 3 && stepsData.current[RuleStep.defineRule].isValid && - stepsData.current[RuleStep.aboutRule].isValid + stepsData.current[RuleStep.aboutRule].isValid && + stepsData.current[RuleStep.scheduleRule].isValid ) { setRule( formatRule( stepsData.current[RuleStep.defineRule].data as DefineStepRule, stepsData.current[RuleStep.aboutRule].data as AboutStepRule, - stepsData.current[RuleStep.scheduleRule].data as ScheduleStepRule + stepsData.current[RuleStep.scheduleRule].data as ScheduleStepRule, + stepsData.current[RuleStep.ruleActions].data as ActionsStepRule ) ); } @@ -177,6 +201,14 @@ const CreateRulePageComponent: React.FC = () => { /> ); + const ruleActionsButton = ( + + ); + const openCloseAccordion = (accordionId: RuleStep | null) => { if (accordionId != null) { if (accordionId === RuleStep.defineRule && defineRuleRef.current != null) { @@ -185,6 +217,8 @@ const CreateRulePageComponent: React.FC = () => { aboutRuleRef.current.onToggle(); } else if (accordionId === RuleStep.scheduleRule && scheduleRuleRef.current != null) { scheduleRuleRef.current.onToggle(); + } else if (accordionId === RuleStep.ruleActions && ruleActionsRef.current != null) { + ruleActionsRef.current.onToggle(); } } }; @@ -253,7 +287,7 @@ const CreateRulePageComponent: React.FC = () => { isLoading={isLoading || loading} title={i18n.PAGE_TITLE} /> - + { - + { - + { /> + + + + {i18n.EDIT_RULE} + + ) + } + > + + + + diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx index 8618bf9504861..f89e3206cc67d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/edit/index.tsx @@ -31,10 +31,17 @@ import { StepPanel } from '../components/step_panel'; import { StepAboutRule } from '../components/step_about_rule'; import { StepDefineRule } from '../components/step_define_rule'; import { StepScheduleRule } from '../components/step_schedule_rule'; +import { StepRuleActions } from '../components/step_rule_actions'; import { formatRule } from '../create/helpers'; -import { getStepsData, redirectToDetections } from '../helpers'; +import { getStepsData, redirectToDetections, getActionMessageParams } from '../helpers'; import * as ruleI18n from '../translations'; -import { RuleStep, DefineStepRule, AboutStepRule, ScheduleStepRule } from '../types'; +import { + RuleStep, + DefineStepRule, + AboutStepRule, + ScheduleStepRule, + ActionsStepRule, +} from '../types'; import * as i18n from './translations'; interface StepRuleForm { @@ -50,6 +57,10 @@ interface ScheduleStepRuleForm extends StepRuleForm { data: ScheduleStepRule | null; } +interface ActionsStepRuleForm extends StepRuleForm { + data: ActionsStepRule | null; +} + const EditRulePageComponent: FC = () => { const [, dispatchToaster] = useStateToaster(); const { @@ -79,14 +90,20 @@ const EditRulePageComponent: FC = () => { data: null, isValid: false, }); + const [myActionsRuleForm, setMyActionsRuleForm] = useState({ + data: null, + isValid: false, + }); const [selectedTab, setSelectedTab] = useState(); const stepsForm = useRef | null>>({ [RuleStep.defineRule]: null, [RuleStep.aboutRule]: null, [RuleStep.scheduleRule]: null, + [RuleStep.ruleActions]: null, }); const [{ isLoading, isSaved }, setRule] = usePersistRule(); const [tabHasError, setTabHasError] = useState([]); + const actionMessageParams = useMemo(() => getActionMessageParams(rule?.type), [rule]); const setStepsForm = useCallback( (step: RuleStep, form: FormHook) => { stepsForm.current[step] = form; @@ -162,6 +179,28 @@ const EditRulePageComponent: FC = () => { ), }, + { + id: RuleStep.ruleActions, + name: ruleI18n.ACTIONS, + content: ( + <> + + + {myActionsRuleForm.data != null && ( + + )} + + + + ), + }, ], [ loading, @@ -170,8 +209,10 @@ const EditRulePageComponent: FC = () => { myAboutRuleForm, myDefineRuleForm, myScheduleRuleForm, + myActionsRuleForm, setStepsForm, stepsForm, + actionMessageParams, ] ); @@ -179,14 +220,18 @@ const EditRulePageComponent: FC = () => { const activeFormId = selectedTab?.id as RuleStep; const activeForm = await stepsForm.current[activeFormId]?.submit(); - const invalidForms = [RuleStep.aboutRule, RuleStep.defineRule, RuleStep.scheduleRule].reduce< - RuleStep[] - >((acc, step) => { + const invalidForms = [ + RuleStep.aboutRule, + RuleStep.defineRule, + RuleStep.scheduleRule, + RuleStep.ruleActions, + ].reduce((acc, step) => { if ( (step === activeFormId && activeForm != null && !activeForm?.isValid) || (step === RuleStep.aboutRule && !myAboutRuleForm.isValid) || (step === RuleStep.defineRule && !myDefineRuleForm.isValid) || - (step === RuleStep.scheduleRule && !myScheduleRuleForm.isValid) + (step === RuleStep.scheduleRule && !myScheduleRuleForm.isValid) || + (step === RuleStep.ruleActions && !myActionsRuleForm.isValid) ) { return [...acc, step]; } @@ -205,21 +250,35 @@ const EditRulePageComponent: FC = () => { : myAboutRuleForm.data) as AboutStepRule, (activeFormId === RuleStep.scheduleRule ? activeForm.data - : myScheduleRuleForm.data) as ScheduleStepRule + : myScheduleRuleForm.data) as ScheduleStepRule, + (activeFormId === RuleStep.ruleActions + ? activeForm.data + : myActionsRuleForm.data) as ActionsStepRule ), ...(ruleId ? { id: ruleId } : {}), }); } else { setTabHasError(invalidForms); } - }, [stepsForm, myAboutRuleForm, myDefineRuleForm, myScheduleRuleForm, selectedTab, ruleId]); + }, [ + stepsForm, + myAboutRuleForm, + myDefineRuleForm, + myScheduleRuleForm, + myActionsRuleForm, + selectedTab, + ruleId, + ]); useEffect(() => { if (rule != null) { - const { aboutRuleData, defineRuleData, scheduleRuleData } = getStepsData({ rule }); + const { aboutRuleData, defineRuleData, scheduleRuleData, ruleActionsData } = getStepsData({ + rule, + }); setMyAboutRuleForm({ data: aboutRuleData, isValid: true }); setMyDefineRuleForm({ data: defineRuleData, isValid: true }); setMyScheduleRuleForm({ data: scheduleRuleData, isValid: true }); + setMyActionsRuleForm({ data: ruleActionsData, isValid: true }); } }, [rule]); @@ -228,6 +287,7 @@ const EditRulePageComponent: FC = () => { if (selectedTab != null) { const ruleStep = selectedTab.id as RuleStep; const respForm = await stepsForm.current[ruleStep]?.submit(); + if (respForm != null) { if (ruleStep === RuleStep.aboutRule) { setMyAboutRuleForm({ @@ -244,6 +304,11 @@ const EditRulePageComponent: FC = () => { data: respForm.data as ScheduleStepRule, isValid: respForm.isValid, }); + } else if (ruleStep === RuleStep.ruleActions) { + setMyActionsRuleForm({ + data: respForm.data as ActionsStepRule, + isValid: respForm.isValid, + }); } } } @@ -255,10 +320,13 @@ const EditRulePageComponent: FC = () => { useEffect(() => { if (rule != null) { - const { aboutRuleData, defineRuleData, scheduleRuleData } = getStepsData({ rule }); + const { aboutRuleData, defineRuleData, scheduleRuleData, ruleActionsData } = getStepsData({ + rule, + }); setMyAboutRuleForm({ data: aboutRuleData, isValid: true }); setMyDefineRuleForm({ data: defineRuleData, isValid: true }); setMyScheduleRuleForm({ data: scheduleRuleData, isValid: true }); + setMyActionsRuleForm({ data: ruleActionsData, isValid: true }); } }, [rule]); @@ -303,6 +371,8 @@ const EditRulePageComponent: FC = () => { return ruleI18n.DEFINITION; } else if (t === RuleStep.scheduleRule) { return ruleI18n.SCHEDULE; + } else if (t === RuleStep.ruleActions) { + return ruleI18n.RULE_ACTIONS; } return t; }) diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx index 3224c605192e6..fbdfcf4fc75d8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.test.tsx @@ -10,6 +10,7 @@ import { getScheduleStepsData, getStepsData, getAboutStepsData, + getActionsStepsData, getHumanizedDuration, getModifiedAboutDetailsData, determineDetailsValue, @@ -17,16 +18,23 @@ import { import { mockRuleWithEverything, mockRule } from './all/__mocks__/mock'; import { esFilters } from '../../../../../../../../src/plugins/data/public'; import { Rule } from '../../../containers/detection_engine/rules'; -import { AboutStepRule, AboutStepRuleDetails, DefineStepRule, ScheduleStepRule } from './types'; +import { + AboutStepRule, + AboutStepRuleDetails, + DefineStepRule, + ScheduleStepRule, + ActionsStepRule, +} from './types'; describe('rule helpers', () => { describe('getStepsData', () => { - test('returns object with about, define, and schedule step properties formatted', () => { + test('returns object with about, define, schedule and actions step properties formatted', () => { const { defineRuleData, modifiedAboutRuleDetailsData, aboutRuleData, scheduleRuleData, + ruleActionsData, }: GetStepsData = getStepsData({ rule: mockRuleWithEverything('test-id'), }); @@ -98,7 +106,8 @@ describe('rule helpers', () => { }, ], }; - const scheduleRuleStepData = { enabled: true, from: '0s', interval: '5m', isNew: false }; + const scheduleRuleStepData = { from: '0s', interval: '5m', isNew: false }; + const ruleActionsStepData = { enabled: true, throttle: undefined, isNew: false, actions: [] }; const aboutRuleDataDetailsData = { note: '# this is some markdown documentation', description: '24/7', @@ -107,6 +116,7 @@ describe('rule helpers', () => { expect(defineRuleData).toEqual(defineRuleStepData); expect(aboutRuleData).toEqual(aboutRuleStepData); expect(scheduleRuleData).toEqual(scheduleRuleStepData); + expect(ruleActionsData).toEqual(ruleActionsStepData); expect(modifiedAboutRuleDetailsData).toEqual(aboutRuleDataDetailsData); }); }); @@ -274,7 +284,6 @@ describe('rule helpers', () => { const result: ScheduleStepRule = getScheduleStepsData(mockedRule); const expected = { isNew: false, - enabled: mockedRule.enabled, interval: mockedRule.interval, from: '0s', }; @@ -283,6 +292,24 @@ describe('rule helpers', () => { }); }); + describe('getActionsStepsData', () => { + test('returns expected ActionsStepRule rule object', () => { + const mockedRule = { + ...mockRule('test-id'), + actions: [], + }; + const result: ActionsStepRule = getActionsStepsData(mockedRule); + const expected = { + actions: [], + enabled: mockedRule.enabled, + isNew: false, + throttle: undefined, + }; + + expect(result).toEqual(expected); + }); + }); + describe('getModifiedAboutDetailsData', () => { test('returns object with "note" and "description" being those of passed in rule', () => { const result: AboutStepRuleDetails = getModifiedAboutDetailsData( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx index 2ace154482a27..50b76552ddc8f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/helpers.tsx @@ -7,8 +7,11 @@ import dateMath from '@elastic/datemath'; import { get } from 'lodash/fp'; import moment from 'moment'; +import memoizeOne from 'memoize-one'; import { useLocation } from 'react-router-dom'; +import { RuleAlertAction } from '../../../../common/detection_engine/types'; +import { transformRuleToAlertAction } from '../../../../common/detection_engine/transform_actions'; import { Filter } from '../../../../../../../../src/plugins/data/public'; import { Rule, RuleType } from '../../../containers/detection_engine/rules'; import { FormData, FormHook, FormSchema } from '../../../shared_imports'; @@ -18,6 +21,7 @@ import { DefineStepRule, IMitreEnterpriseAttack, ScheduleStepRule, + ActionsStepRule, } from './types'; export interface GetStepsData { @@ -25,6 +29,7 @@ export interface GetStepsData { modifiedAboutRuleDetailsData: AboutStepRuleDetails; defineRuleData: DefineStepRule; scheduleRuleData: ScheduleStepRule; + ruleActionsData: ActionsStepRule; } export const getStepsData = ({ @@ -38,8 +43,29 @@ export const getStepsData = ({ const aboutRuleData: AboutStepRule = getAboutStepsData(rule, detailsView); const modifiedAboutRuleDetailsData: AboutStepRuleDetails = getModifiedAboutDetailsData(rule); const scheduleRuleData: ScheduleStepRule = getScheduleStepsData(rule); + const ruleActionsData: ActionsStepRule = getActionsStepsData(rule); - return { aboutRuleData, modifiedAboutRuleDetailsData, defineRuleData, scheduleRuleData }; + return { + aboutRuleData, + modifiedAboutRuleDetailsData, + defineRuleData, + scheduleRuleData, + ruleActionsData, + }; +}; + +export const getActionsStepsData = ( + rule: Omit & { actions: RuleAlertAction[] } +): ActionsStepRule => { + const { enabled, actions = [], meta } = rule; + + return { + actions: actions?.map(transformRuleToAlertAction), + isNew: false, + throttle: meta?.throttle, + kibanaSiemAppUrl: meta?.kibanaSiemAppUrl, + enabled, + }; }; export const getDefineStepsData = (rule: Rule): DefineStepRule => ({ @@ -60,12 +86,11 @@ export const getDefineStepsData = (rule: Rule): DefineStepRule => ({ }); export const getScheduleStepsData = (rule: Rule): ScheduleStepRule => { - const { enabled, interval, from } = rule; + const { interval, from } = rule; const fromHumanizedValue = getHumanizedDuration(from, interval); return { isNew: false, - enabled, interval, from: fromHumanizedValue, }; @@ -200,3 +225,46 @@ export const redirectToDetections = ( isAuthenticated != null && hasEncryptionKey != null && (!isSignalIndexExists || !isAuthenticated || !hasEncryptionKey); + +export const getActionMessageRuleParams = (ruleType: RuleType): string[] => { + const commonRuleParamsKeys = [ + 'id', + 'name', + 'description', + 'false_positives', + 'rule_id', + 'max_signals', + 'risk_score', + 'output_index', + 'references', + 'severity', + 'timeline_id', + 'timeline_title', + 'threat', + 'type', + 'version', + // 'lists', + ]; + + const ruleParamsKeys = [ + ...commonRuleParamsKeys, + ...(isMlRule(ruleType) + ? ['anomaly_threshold', 'machine_learning_job_id'] + : ['index', 'filters', 'language', 'query', 'saved_id']), + ].sort(); + + return ruleParamsKeys; +}; + +export const getActionMessageParams = memoizeOne((ruleType: RuleType | undefined): string[] => { + if (!ruleType) { + return []; + } + const actionMessageRuleParams = getActionMessageRuleParams(ruleType); + + return [ + 'state.signals_count', + '{context.results_link}', + ...actionMessageRuleParams.map(param => `context.rule.${param}`), + ]; +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx index b2c17fb8d38a8..2b93ec8b10112 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/index.tsx @@ -8,7 +8,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback, useRef, useState } from 'react'; import { Redirect } from 'react-router-dom'; -import { usePrePackagedRules } from '../../../containers/detection_engine/rules'; +import { usePrePackagedRules, importRules } from '../../../containers/detection_engine/rules'; import { DETECTION_ENGINE_PAGE_NAME, getDetectionEngineUrl, @@ -20,7 +20,7 @@ import { SpyRoute } from '../../../utils/route/spy_routes'; import { useUserInfo } from '../components/user_info'; import { AllRules } from './all'; -import { ImportRuleModal } from './components/import_rule_modal'; +import { ImportDataModal } from '../../../components/import_data_modal'; import { ReadOnlyCallOut } from './components/read_only_callout'; import { UpdatePrePackagedRulesCallOut } from './components/pre_packaged_rules/update_callout'; import { getPrePackagedRuleStatus, redirectToDetections } from './helpers'; @@ -96,10 +96,20 @@ const RulesPageComponent: React.FC = () => { return ( <> {userHasNoPermissions && } - setShowImportModal(false)} + description={i18n.SELECT_RULE} + errorMessage={i18n.IMPORT_FAILED} + failedDetailed={i18n.IMPORT_FAILED_DETAILED} importComplete={handleRefreshRules} + importData={importRules} + successMessage={i18n.SUCCESSFULLY_IMPORTED_RULES} + showCheckBox={true} + showModal={showImportModal} + submitBtnText={i18n.IMPORT_RULE_BTN_TITLE} + subtitle={i18n.INITIAL_PROMPT_TEXT} + title={i18n.IMPORT_RULE} /> { {prePackagedRuleStatus === 'someRuleUninstall' && ( defaultMessage: 'Reload {missingRules} deleted Elastic prebuilt {missingRules, plural, =1 {rule} other {rules}} ', }); + +export const IMPORT_RULE_BTN_TITLE = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.importRuleTitle', + { + defaultMessage: 'Import rule', + } +); + +export const SELECT_RULE = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.selectRuleDescription', + { + defaultMessage: 'Select a SIEM rule (as exported from the Detection Engine view) to import', + } +); + +export const INITIAL_PROMPT_TEXT = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.initialPromptTextDescription', + { + defaultMessage: 'Select or drag and drop a valid rules_export.ndjson file', + } +); + +export const OVERWRITE_WITH_SAME_NAME = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.overwriteDescription', + { + defaultMessage: 'Automatically overwrite saved objects with the same rule ID', + } +); + +export const SUCCESSFULLY_IMPORTED_RULES = (totalRules: number) => + i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.successfullyImportedRulesTitle', + { + values: { totalRules }, + defaultMessage: + 'Successfully imported {totalRules} {totalRules, plural, =1 {rule} other {rules}}', + } + ); + +export const IMPORT_FAILED = i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.importFailedTitle', + { + defaultMessage: 'Failed to import rules', + } +); + +export const IMPORT_FAILED_DETAILED = (ruleId: string, statusCode: number, message: string) => + i18n.translate( + 'xpack.siem.detectionEngine.components.importRuleModal.importFailedDetailedTitle', + { + values: { ruleId, statusCode, message }, + defaultMessage: 'Rule ID: {ruleId}\n Status Code: {statusCode}\n Message: {message}', + } + ); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts index d4caa4639f338..c1db24991c17c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/types.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { AlertAction } from '../../../../../../../plugins/alerting/common'; +import { RuleAlertAction } from '../../../../common/detection_engine/types'; import { Filter } from '../../../../../../../../src/plugins/data/common'; import { RuleType } from '../../../containers/detection_engine/rules/types'; import { FieldValueQueryBar } from './components/query_bar'; @@ -27,6 +29,7 @@ export enum RuleStep { defineRule = 'define-rule', aboutRule = 'about-rule', scheduleRule = 'schedule-rule', + ruleActions = 'rule-actions', } export type RuleStatusType = 'passive' | 'active' | 'valid'; @@ -76,12 +79,18 @@ export interface DefineStepRule extends StepRuleData { } export interface ScheduleStepRule extends StepRuleData { - enabled: boolean; interval: string; from: string; to?: string; } +export interface ActionsStepRule extends StepRuleData { + actions: AlertAction[]; + enabled: boolean; + kibanaSiemAppUrl?: string; + throttle?: string | null; +} + export interface DefineStepRuleJson { anomaly_threshold?: number; index?: string[]; @@ -108,16 +117,18 @@ export interface AboutStepRuleJson { } export interface ScheduleStepRuleJson { - enabled: boolean; interval: string; from: string; to?: string; meta?: unknown; } -export type MyRule = Omit & { - immutable: boolean; -}; +export interface ActionsStepRuleJson { + actions: RuleAlertAction[]; + enabled: boolean; + throttle?: string | null; + meta?: unknown; +} export interface IMitreAttack { id: string; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx index 8af4731e4dda4..a12c95b3b5a6f 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx @@ -5,7 +5,7 @@ */ import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -import React, { useContext, useEffect, useCallback, useMemo } from 'react'; +import React, { useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; @@ -15,7 +15,7 @@ import { LastEventTime } from '../../../components/last_event_time'; import { AnomalyTableProvider } from '../../../components/ml/anomaly/anomaly_table_provider'; import { hostToCriteria } from '../../../components/ml/criteria/host_to_criteria'; import { hasMlUserPermissions } from '../../../components/ml/permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../../../components/ml/permissions/ml_capabilities_provider'; +import { useMlCapabilities } from '../../../components/ml_popover/hooks/use_ml_capabilities'; import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; import { SiemNavigation } from '../../../components/navigation'; import { KpiHostsComponent } from '../../../components/page/hosts'; @@ -62,7 +62,7 @@ const HostDetailsComponent = React.memo( useEffect(() => { setHostDetailsTablesActivePageToZero(); }, [setHostDetailsTablesActivePageToZero, detailName]); - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const kibana = useKibana(); const hostDetailsPageFilters: Filter[] = useMemo(() => getHostDetailsPageFilters(detailName), [ detailName, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index a7aa9920b7d08..d574925a91600 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -14,7 +14,6 @@ import { FiltersGlobal } from '../../components/filters_global'; import { HeaderPage } from '../../components/header_page'; import { LastEventTime } from '../../components/last_event_time'; import { hasMlUserPermissions } from '../../components/ml/permissions/has_ml_user_permissions'; -import { MlCapabilitiesContext } from '../../components/ml/permissions/ml_capabilities_provider'; import { SiemNavigation } from '../../components/navigation'; import { KpiHostsComponent } from '../../components/page/hosts'; import { manageQuery } from '../../components/page/manage_query'; @@ -30,6 +29,7 @@ import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from import { SpyRoute } from '../../utils/route/spy_routes'; import { esQuery } from '../../../../../../../src/plugins/data/public'; +import { useMlCapabilities } from '../../components/ml_popover/hooks/use_ml_capabilities'; import { HostsEmptyPage } from './hosts_empty_page'; import { HostsTabs } from './hosts_tabs'; import { navTabsHosts } from './nav_tabs'; @@ -52,7 +52,7 @@ export const HostsComponent = React.memo( to, hostsPagePath, }) => { - const capabilities = React.useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const kibana = useKibana(); const { tabName } = useParams(); const tabsFilters = React.useMemo(() => { diff --git a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx index 48fc1421d90bb..babc153823b5a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/index.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { Redirect, Route, Switch, RouteComponentProps } from 'react-router-dom'; -import { MlCapabilitiesContext } from '../../components/ml/permissions/ml_capabilities_provider'; +import { useMlCapabilities } from '../../components/ml_popover/hooks/use_ml_capabilities'; import { hasMlUserPermissions } from '../../components/ml/permissions/has_ml_user_permissions'; import { FlowTarget } from '../../graphql/types'; @@ -24,7 +24,7 @@ const networkPagePath = `/:pageName(${SiemPageName.network})`; const ipDetailsPageBasePath = `${networkPagePath}/ip/:detailName`; const NetworkContainerComponent: React.FC = () => { - const capabilities = useContext(MlCapabilitiesContext); + const capabilities = useMlCapabilities(); const capabilitiesFetched = capabilities.capabilitiesFetched; const userHasMlUserPermissions = useMemo(() => hasMlUserPermissions(capabilities), [ capabilities, diff --git a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx new file mode 100644 index 0000000000000..62399891c9606 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.test.tsx @@ -0,0 +1,89 @@ +/* + * 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 { TimelinesPageComponent } from './timelines_page'; +import { useKibana } from '../../lib/kibana'; +import { shallow, ShallowWrapper } from 'enzyme'; +import React from 'react'; +import ApolloClient from 'apollo-client'; + +jest.mock('../../lib/kibana', () => { + return { + useKibana: jest.fn(), + }; +}); +describe('TimelinesPageComponent', () => { + const mockAppollloClient = {} as ApolloClient; + let wrapper: ShallowWrapper; + + describe('If the user is authorised', () => { + beforeAll(() => { + ((useKibana as unknown) as jest.Mock).mockReturnValue({ + services: { + application: { + capabilities: { + siem: { + crud: true, + }, + }, + }, + }, + }); + wrapper = shallow(); + }); + + afterAll(() => { + ((useKibana as unknown) as jest.Mock).mockReset(); + }); + + test('should not show the import timeline modal by default', () => { + expect( + wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle') + ).toEqual(false); + }); + + test('should show the import timeline button', () => { + expect(wrapper.find('[data-test-subj="open-import-data-modal-btn"]').exists()).toEqual(true); + }); + + test('should show the import timeline modal after user clicking on the button', () => { + wrapper.find('[data-test-subj="open-import-data-modal-btn"]').simulate('click'); + expect( + wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle') + ).toEqual(true); + }); + }); + + describe('If the user is not authorised', () => { + beforeAll(() => { + ((useKibana as unknown) as jest.Mock).mockReturnValue({ + services: { + application: { + capabilities: { + siem: { + crud: false, + }, + }, + }, + }, + }); + wrapper = shallow(); + }); + + afterAll(() => { + ((useKibana as unknown) as jest.Mock).mockReset(); + }); + test('should not show the import timeline modal by default', () => { + expect( + wrapper.find('[data-test-subj="stateful-open-timeline"]').prop('importDataModalToggle') + ).toEqual(false); + }); + + test('should not show the import timeline button', () => { + expect(wrapper.find('[data-test-subj="open-import-data-modal-btn"]').exists()).toEqual(false); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx index 6d30ea58089f0..73070d2b94aac 100644 --- a/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/timelines/timelines_page.tsx @@ -5,14 +5,16 @@ */ import ApolloClient from 'apollo-client'; -import React from 'react'; +import React, { useState, useCallback } from 'react'; import styled from 'styled-components'; +import { EuiButton } from '@elastic/eui'; import { HeaderPage } from '../../components/header_page'; import { StatefulOpenTimeline } from '../../components/open_timeline'; import { WrapperPage } from '../../components/wrapper_page'; import { SpyRoute } from '../../utils/route/spy_routes'; import * as i18n from './translations'; +import { useKibana } from '../../lib/kibana'; const TimelinesContainer = styled.div` width: 100%; @@ -26,18 +28,40 @@ type OwnProps = TimelinesProps; export const DEFAULT_SEARCH_RESULTS_PER_PAGE = 10; -const TimelinesPageComponent: React.FC = ({ apolloClient }) => { +export const TimelinesPageComponent: React.FC = ({ apolloClient }) => { + const [importDataModalToggle, setImportDataModalToggle] = useState(false); + const onImportTimelineBtnClick = useCallback(() => { + setImportDataModalToggle(true); + }, [setImportDataModalToggle]); + + const uiCapabilities = useKibana().services.application.capabilities; + const capabilitiesCanUserCRUD: boolean = + typeof uiCapabilities.siem.crud === 'boolean' ? uiCapabilities.siem.crud : false; + return ( <> - + + {capabilitiesCanUserCRUD && ( + + {i18n.ALL_TIMELINES_IMPORT_TIMELINE_TITLE} + + )} + diff --git a/x-pack/legacy/plugins/siem/public/shared_imports.ts b/x-pack/legacy/plugins/siem/public/shared_imports.ts index edd7812b3bd16..c83433ef129c9 100644 --- a/x-pack/legacy/plugins/siem/public/shared_imports.ts +++ b/x-pack/legacy/plugins/siem/public/shared_imports.ts @@ -18,6 +18,9 @@ export { useForm, ValidationFunc, } from '../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; -export { Field } from '../../../../../src/plugins/es_ui_shared/static/forms/components'; +export { + Field, + SelectField, +} from '../../../../../src/plugins/es_ui_shared/static/forms/components'; export { fieldValidators } from '../../../../../src/plugins/es_ui_shared/static/forms/helpers'; export { ERROR_CODE } from '../../../../../src/plugins/es_ui_shared/static/forms/helpers/field_validators/types'; diff --git a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory.ts b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig.js similarity index 55% rename from x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory.ts rename to x-pack/legacy/plugins/siem/scripts/optimize_tsconfig.js index 66e2a4eafa880..ff4002b076e5d 100644 --- a/x-pack/plugins/advanced_ui_actions/public/services/action_factory_service/action_factory.ts +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig.js @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable */ +const { optimizeTsConfig } = require('./optimize_tsconfig/optimize'); -export { - ActionFactory -} from '../../../../../../src/plugins/ui_actions/public/actions/action_factory'; +optimizeTsConfig().catch(err => { + console.error(err); + // eslint-disable-next-line no-process-exit + process.exit(1); +}); diff --git a/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/README.md b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/README.md new file mode 100644 index 0000000000000..d3615d2870ef9 --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/README.md @@ -0,0 +1,16 @@ +Hard forked from here: +x-pack/legacy/plugins/apm/scripts/optimize-tsconfig.js + + +#### Optimizing TypeScript + +Kibana and X-Pack are very large TypeScript projects, and it comes at a cost. Editor responsiveness is not great, and the CLI type check for X-Pack takes about a minute. To get faster feedback, we create a smaller SIEM TypeScript project that only type checks the SIEM project and the files it uses. This optimization consists of creating a `tsconfig.json` in SIEM that includes the Kibana/X-Pack typings, and editing the Kibana/X-Pack configurations to not include any files, or removing the configurations altogether. The script configures git to ignore any changes in these files, and has an undo script as well. + +To run the optimization: + +`$ node x-pack/legacy/plugins/siem/scripts/optimize_tsconfig` + +To undo the optimization: + +`$ node x-pack/legacy/plugins/siem/scripts/unoptimize_tsconfig` + diff --git a/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/optimize.js b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/optimize.js new file mode 100644 index 0000000000000..9c04e0b69b738 --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/optimize.js @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* eslint-disable import/no-extraneous-dependencies */ + +const fs = require('fs'); +const { promisify } = require('util'); +const path = require('path'); +const json5 = require('json5'); +const execa = require('execa'); + +const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); + +const { xpackRoot, kibanaRoot, tsconfigTpl, filesToIgnore } = require('./paths'); +const { unoptimizeTsConfig } = require('./unoptimize'); + +function prepareParentTsConfigs() { + return Promise.all( + [path.resolve(xpackRoot, 'tsconfig.json'), path.resolve(kibanaRoot, 'tsconfig.json')].map( + async filename => { + const config = json5.parse(await readFile(filename, 'utf-8')); + + await writeFile( + filename, + JSON.stringify( + { + ...config, + include: [], + }, + null, + 2 + ), + { encoding: 'utf-8' } + ); + } + ) + ); +} + +async function addFilesToXpackTsConfig() { + const template = json5.parse(await readFile(tsconfigTpl, 'utf-8')); + const xpackTsConfig = path.join(xpackRoot, 'tsconfig.json'); + const config = json5.parse(await readFile(xpackTsConfig, 'utf-8')); + + await writeFile(xpackTsConfig, JSON.stringify({ ...config, ...template }, null, 2), { + encoding: 'utf-8', + }); +} + +async function setIgnoreChanges() { + for (const filename of filesToIgnore) { + await execa('git', ['update-index', '--skip-worktree', filename]); + } +} + +async function optimizeTsConfig() { + await unoptimizeTsConfig(); + + await prepareParentTsConfigs(); + + await addFilesToXpackTsConfig(); + + await setIgnoreChanges(); + // eslint-disable-next-line no-console + console.log( + 'Created an optimized tsconfig.json for SIEM. To undo these changes, run `./scripts/unoptimize_tsconfig.js`' + ); +} + +module.exports = { + optimizeTsConfig, +}; diff --git a/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/paths.js b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/paths.js new file mode 100644 index 0000000000000..ca26203e17d2e --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/paths.js @@ -0,0 +1,23 @@ +/* + * 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. + */ +const path = require('path'); + +const xpackRoot = path.resolve(__dirname, '../../../../..'); +const kibanaRoot = path.resolve(xpackRoot, '..'); + +const tsconfigTpl = path.resolve(__dirname, './tsconfig.json'); + +const filesToIgnore = [ + path.resolve(xpackRoot, 'tsconfig.json'), + path.resolve(kibanaRoot, 'tsconfig.json'), +]; + +module.exports = { + xpackRoot, + kibanaRoot, + tsconfigTpl, + filesToIgnore, +}; diff --git a/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/tsconfig.json b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/tsconfig.json new file mode 100644 index 0000000000000..bec6988bdebd9 --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/tsconfig.json @@ -0,0 +1,15 @@ +{ + "include": [ + "typings/**/*", + "plugins/siem/**/*", + "legacy/plugins/siem/**/*", + "plugins/apm/typings/numeral.d.ts", + "legacy/plugins/canvas/types/webpack.d.ts" + ], + "exclude": [ + "test/**/*", + "**/__fixtures__/**/*", + "legacy/plugins/siem/cypress/**/*", + "**/typespec_tests.ts" + ] +} diff --git a/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/unoptimize.js b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/unoptimize.js new file mode 100644 index 0000000000000..21fc1aa2a1a33 --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/optimize_tsconfig/unoptimize.js @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable import/no-extraneous-dependencies */ + +const execa = require('execa'); + +const { filesToIgnore } = require('./paths'); + +async function unoptimizeTsConfig() { + for (const filename of filesToIgnore) { + await execa('git', ['update-index', '--no-skip-worktree', filename]); + await execa('git', ['checkout', filename]); + } +} + +module.exports = { + unoptimizeTsConfig: async () => { + await unoptimizeTsConfig(); + // eslint-disable-next-line no-console + console.log('Removed SIEM TypeScript optimizations'); + }, +}; diff --git a/x-pack/legacy/plugins/siem/scripts/unoptimize_tsconfig.js b/x-pack/legacy/plugins/siem/scripts/unoptimize_tsconfig.js new file mode 100644 index 0000000000000..d5392c76d9f8f --- /dev/null +++ b/x-pack/legacy/plugins/siem/scripts/unoptimize_tsconfig.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +const { unoptimizeTsConfig } = require('./optimize_tsconfig/unoptimize'); + +unoptimizeTsConfig().catch(err => { + console.error(err); + // eslint-disable-next-line no-process-exit + process.exit(1); +}); diff --git a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts index f897236b3470e..9bf55cfe1ed2a 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ecs/schema.gql.ts @@ -410,6 +410,7 @@ export const ecsSchema = gql` created_by: ToStringArray updated_by: ToStringArray version: ToStringArray + note: ToStringArray } type SignalField { diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index e2b365f8bfa5b..d272b7ff59b79 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -1014,6 +1014,8 @@ export interface RuleField { updated_by?: Maybe; version?: Maybe; + + note?: Maybe; } export interface SuricataEcsFields { @@ -4822,6 +4824,8 @@ export namespace RuleFieldResolvers { updated_by?: UpdatedByResolver, TypeParent, TContext>; version?: VersionResolver, TypeParent, TContext>; + + note?: NoteResolver, TypeParent, TContext>; } export type IdResolver< @@ -4974,6 +4978,11 @@ export namespace RuleFieldResolvers { Parent = RuleField, TContext = SiemContext > = Resolver; + export type NoteResolver< + R = Maybe, + Parent = RuleField, + TContext = SiemContext + > = Resolver; } export namespace SuricataEcsFieldsResolvers { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.test.ts index f83a8d40d6ae1..189c596a77125 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.test.ts @@ -39,7 +39,7 @@ describe('buildSignalsSearchQuery', () => { { range: { '@timestamp': { - gte: from, + gt: from, lte: to, }, }, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.ts index 001650e5b2005..b973d4c5f4e98 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/build_signals_query.ts @@ -30,7 +30,7 @@ export const buildSignalsSearchQuery = ({ ruleId, index, from, to }: BuildSignal { range: { '@timestamp': { - gte: from, + gt: from, lte: to, }, }, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/create_notifications.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/create_notifications.test.ts index dea42b0c852f9..073251b68f414 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/create_notifications.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/create_notifications.test.ts @@ -42,7 +42,7 @@ describe('createNotifications', () => { const action = { group: 'default', id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', - params: { message: 'Rule generated {{state.signalsCount}} signals' }, + params: { message: 'Rule generated {{state.signals_count}} signals' }, action_type_id: '.slack', }; await createNotifications({ diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/get_signals_count.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/get_signals_count.ts index 6ae7922660bd7..33cee6d074b70 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/get_signals_count.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/get_signals_count.ts @@ -21,7 +21,7 @@ interface GetSignalsCount { ruleAlertId: string; ruleId: string; index: string; - kibanaUrl: string | undefined; + kibanaSiemAppUrl: string | undefined; callCluster: NotificationExecutorOptions['services']['callCluster']; } @@ -32,7 +32,7 @@ export const getSignalsCount = async ({ ruleId, index, callCluster, - kibanaUrl = '', + kibanaSiemAppUrl = '', }: GetSignalsCount): Promise => { const fromMoment = moment.isDate(from) ? moment(from) : parseScheduleDates(from); const toMoment = moment.isDate(to) ? moment(to) : parseScheduleDates(to); @@ -53,7 +53,7 @@ export const getSignalsCount = async ({ const result = await callCluster('count', query); const resultsLink = getNotificationResultsLink({ - baseUrl: kibanaUrl, + kibanaSiemAppUrl: `${kibanaSiemAppUrl}`, id: ruleAlertId, from: fromInMs, to: toInMs, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.test.ts index ff0126b129636..50ac10347e062 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.test.ts @@ -127,7 +127,7 @@ describe('rules_notification_alert_type', () => { expect(alertInstanceFactoryMock).toHaveBeenCalled(); expect(alertInstanceMock.replaceState).toHaveBeenCalledWith( - expect.objectContaining({ signalsCount: 10 }) + expect.objectContaining({ signals_count: 10 }) ); expect(alertInstanceMock.scheduleActions).toHaveBeenCalledWith( 'default', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts index c5dc4c3a27e16..32e64138ff6e0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/rules_notification_alert_type.ts @@ -40,14 +40,14 @@ export const rulesNotificationAlertType = ({ } const { params: ruleAlertParams, name: ruleName } = ruleAlertSavedObject.attributes; - const ruleParams = { ...ruleAlertParams, name: ruleName }; + const ruleParams = { ...ruleAlertParams, name: ruleName, id: ruleAlertSavedObject.id }; const { signalsCount, resultsLink } = await getSignalsCount({ from: previousStartedAt ?? `now-${ruleParams.interval}`, to: startedAt, index: ruleParams.outputIndex, ruleId: ruleParams.ruleId!, - kibanaUrl: ruleAlertParams.meta?.kibanaUrl as string, + kibanaSiemAppUrl: ruleAlertParams.meta?.kibanaSiemAppUrl as string, ruleAlertId: ruleAlertSavedObject.id, callCluster: services.callCluster, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/schedule_notification_actions.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/schedule_notification_actions.ts index 9c38c88a12411..b858b25377ffe 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/schedule_notification_actions.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/schedule_notification_actions.ts @@ -4,11 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { mapKeys, snakeCase } from 'lodash/fp'; import { AlertInstance } from '../../../../../../../plugins/alerting/server'; import { RuleTypeParams } from '../types'; type NotificationRuleTypeParams = RuleTypeParams & { name: string; + id: string; }; interface ScheduleNotificationActions { @@ -26,9 +28,9 @@ export const scheduleNotificationActions = ({ }: ScheduleNotificationActions): AlertInstance => alertInstance .replaceState({ - signalsCount, + signals_count: signalsCount, }) .scheduleActions('default', { - resultsLink, - rule: ruleParams, + results_link: resultsLink, + rule: mapKeys(snakeCase, ruleParams), }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/update_notifications.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/update_notifications.test.ts index e1b452c911443..4c077dd9fc1fb 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/update_notifications.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/update_notifications.test.ts @@ -88,7 +88,7 @@ describe('updateNotifications', () => { const action = { group: 'default', id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', - params: { message: 'Rule generated {{state.signalsCount}} signals' }, + params: { message: 'Rule generated {{state.signals_count}} signals' }, action_type_id: '.slack', }; await updateNotifications({ diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.test.ts index 4c3f311d10acc..0d363e1f6f3c2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.test.ts @@ -9,7 +9,7 @@ import { getNotificationResultsLink } from './utils'; describe('utils', () => { it('getNotificationResultsLink', () => { const resultLink = getNotificationResultsLink({ - baseUrl: 'http://localhost:5601', + kibanaSiemAppUrl: 'http://localhost:5601/app/siem', id: 'notification-id', from: '00000', to: '1111', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.ts index ed502d31d2fb5..b8a3c4199c4f0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/notifications/utils.ts @@ -5,14 +5,14 @@ */ export const getNotificationResultsLink = ({ - baseUrl, + kibanaSiemAppUrl, id, from, to, }: { - baseUrl: string; + kibanaSiemAppUrl: string; id: string; from: string; to: string; }) => - `${baseUrl}/app/siem#/detections/rules/id/${id}?timerange=(global:(linkTo:!(timeline),timerange:(from:${from},kind:absolute,to:${to})),timeline:(linkTo:!(global),timerange:(from:${from},kind:absolute,to:${to})))`; + `${kibanaSiemAppUrl}#/detections/rules/id/${id}?timerange=(global:(linkTo:!(timeline),timerange:(from:${from},kind:absolute,to:${to})),timeline:(linkTo:!(global),timerange:(from:${from},kind:absolute,to:${to})))`; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_context.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_context.ts index ebf6b3ae79ea8..2e5c29bc0221a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_context.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_context.ts @@ -12,11 +12,13 @@ import { } from '../../../../../../../../../src/core/server/mocks'; import { alertsClientMock } from '../../../../../../../../plugins/alerting/server/mocks'; import { actionsClientMock } from '../../../../../../../../plugins/actions/server/mocks'; +import { licensingMock } from '../../../../../../../../plugins/licensing/server/mocks'; const createMockClients = () => ({ actionsClient: actionsClientMock.create(), alertsClient: alertsClientMock.create(), clusterClient: elasticsearchServiceMock.createScopedClusterClient(), + licensing: { license: licensingMock.createLicenseMock() }, savedObjectsClient: savedObjectsClientMock.create(), siemClient: { signalsIndex: 'mockSignalsIndex' }, }); @@ -33,6 +35,7 @@ const createRequestContextMock = ( elasticsearch: { ...coreContext.elasticsearch, dataClient: clients.clusterClient }, savedObjects: { client: clients.savedObjectsClient }, }, + licensing: clients.licensing, siem: { getSiemClient: jest.fn(() => clients.siemClient) }, } as unknown) as RequestHandlerContext; }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 6435410f31797..3b24b722f7356 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -295,18 +295,30 @@ export const getCreateRequest = () => body: typicalPayload(), }); -export const createMlRuleRequest = () => { +export const typicalMlRulePayload = () => { const { query, language, index, ...mlParams } = typicalPayload(); + return { + ...mlParams, + type: 'machine_learning', + anomaly_threshold: 58, + machine_learning_job_id: 'typical-ml-job-id', + }; +}; + +export const createMlRuleRequest = () => { return requestMock.create({ method: 'post', path: DETECTION_ENGINE_RULES_URL, - body: { - ...mlParams, - type: 'machine_learning', - anomaly_threshold: 50, - machine_learning_job_id: 'some-uuid', - }, + body: typicalMlRulePayload(), + }); +}; + +export const createBulkMlRuleRequest = () => { + return requestMock.create({ + method: 'post', + path: DETECTION_ENGINE_RULES_URL, + body: [typicalMlRulePayload()], }); }; @@ -323,7 +335,7 @@ export const createRuleWithActionsRequest = () => { { group: 'default', id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', - params: { message: 'Rule generated {{state.signalsCount}} signals' }, + params: { message: 'Rule generated {{state.signals_count}} signals' }, action_type_id: '.slack', }, ], @@ -502,7 +514,7 @@ export const updateActionResult = (): ActionResult => ({ config: {}, }); -export const getMockPrivileges = () => ({ +export const getMockPrivilegesResult = () => ({ username: 'test-space', has_all_requested: false, cluster: { @@ -553,8 +565,6 @@ export const getMockPrivileges = () => ({ }, }, application: {}, - is_authenticated: false, - has_encryption_key: true, }); export const getFindResultStatusEmpty = (): SavedObjectsFindResponse => ({ @@ -580,6 +590,10 @@ export const getFindResultStatus = (): SavedObjectsFindResponse ({ { actionTypeId: '.slack', params: { - message: 'Rule generated {{state.signalsCount}} signals\n\n{{rule.name}}\n{{resultsLink}}', + message: + 'Rule generated {{state.signals_count}} signals\n\n{{context.rule.name}}\n{{{context.results_link}}}', }, group: 'default', id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts index 13d75cc44992c..a2485ec477453 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts @@ -23,6 +23,21 @@ export const getSimpleRule = (ruleId = 'rule-1'): Partial = query: 'user.name: root or user.name: admin', }); +/** + * This is a typical ML rule for testing + * @param ruleId + */ +export const getSimpleMlRule = (ruleId = 'rule-1'): Partial => ({ + name: 'Simple Rule Query', + description: 'Simple Rule Query', + risk_score: 1, + rule_id: ruleId, + severity: 'high', + type: 'machine_learning', + anomaly_threshold: 44, + machine_learning_job_id: 'some_job_id', +}); + /** * This is a typical simple rule for testing that is easy for most basic testing * @param ruleId diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts index 44050f21a1259..aa4f6150889f9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts @@ -4,20 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ +import { securityMock } from '../../../../../../../../plugins/security/server/mocks'; import { readPrivilegesRoute } from './read_privileges_route'; import { serverMock, requestContextMock } from '../__mocks__'; -import { getPrivilegeRequest, getMockPrivileges } from '../__mocks__/request_responses'; +import { getPrivilegeRequest, getMockPrivilegesResult } from '../__mocks__/request_responses'; -describe('read_privileges', () => { +describe('read_privileges route', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); + let mockSecurity: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - clients.clusterClient.callAsCurrentUser.mockResolvedValue(getMockPrivileges()); - readPrivilegesRoute(server.router, false); + mockSecurity = securityMock.createSetup(); + mockSecurity.authc.isAuthenticated.mockReturnValue(false); + clients.clusterClient.callAsCurrentUser.mockResolvedValue(getMockPrivilegesResult()); + readPrivilegesRoute(server.router, mockSecurity, false); }); describe('normal status codes', () => { @@ -26,10 +30,28 @@ describe('read_privileges', () => { expect(response.status).toEqual(200); }); - test.skip('returns the payload when doing a normal request', async () => { + test('returns the payload when doing a normal request', async () => { const response = await server.inject(getPrivilegeRequest(), context); + const expectedBody = { + ...getMockPrivilegesResult(), + is_authenticated: false, + has_encryption_key: true, + }; expect(response.status).toEqual(200); - expect(response.body).toEqual(getMockPrivileges()); + expect(response.body).toEqual(expectedBody); + }); + + test('is authenticated when security says so', async () => { + mockSecurity.authc.isAuthenticated.mockReturnValue(true); + const expectedBody = { + ...getMockPrivilegesResult(), + is_authenticated: true, + has_encryption_key: true, + }; + + const response = await server.inject(getPrivilegeRequest(), context); + expect(response.status).toEqual(200); + expect(response.body).toEqual(expectedBody); }); test('returns 500 when bad response from cluster', async () => { @@ -41,4 +63,26 @@ describe('read_privileges', () => { expect(response.body).toEqual({ message: 'Test error', status_code: 500 }); }); }); + + describe('when security plugin is disabled', () => { + beforeEach(() => { + server = serverMock.create(); + ({ clients, context } = requestContextMock.createTools()); + + clients.clusterClient.callAsCurrentUser.mockResolvedValue(getMockPrivilegesResult()); + readPrivilegesRoute(server.router, undefined, false); + }); + + it('returns unauthenticated', async () => { + const expectedBody = { + ...getMockPrivilegesResult(), + is_authenticated: false, + has_encryption_key: true, + }; + + const response = await server.inject(getPrivilegeRequest(), context); + expect(response.status).toEqual(200); + expect(response.body).toEqual(expectedBody); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.ts index 81ce4a9c3f2fc..2f5ea4d1ec767 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.ts @@ -8,10 +8,15 @@ import { merge } from 'lodash/fp'; import { IRouter } from '../../../../../../../../../src/core/server'; import { DETECTION_ENGINE_PRIVILEGES_URL } from '../../../../../common/constants'; +import { SetupPlugins } from '../../../../plugin'; import { buildSiemResponse, transformError } from '../utils'; import { readPrivileges } from '../../privileges/read_privileges'; -export const readPrivilegesRoute = (router: IRouter, usingEphemeralEncryptionKey: boolean) => { +export const readPrivilegesRoute = ( + router: IRouter, + security: SetupPlugins['security'], + usingEphemeralEncryptionKey: boolean +) => { router.get( { path: DETECTION_ENGINE_PRIVILEGES_URL, @@ -29,7 +34,7 @@ export const readPrivilegesRoute = (router: IRouter, usingEphemeralEncryptionKey const index = siemClient.signalsIndex; const clusterPrivileges = await readPrivileges(clusterClient.callAsCurrentUser, index); const privileges = merge(clusterPrivileges, { - is_authenticated: true, // until we support optional auth: https://github.com/elastic/kibana/pull/55327#issuecomment-577159911 + is_authenticated: security?.authc.isAuthenticated(request) ?? false, has_encryption_key: !usingEphemeralEncryptionKey, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index e2af678c828e6..32b8eca298229 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -13,6 +13,7 @@ import { getFindResultWithSingleHit, getEmptyFindResult, getResult, + createBulkMlRuleRequest, } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { createRulesBulkRoute } from './create_rules_bulk_route'; @@ -56,6 +57,22 @@ describe('create_rules_bulk', () => { }); describe('unhappy paths', () => { + it('returns an error object if creating an ML rule with an insufficient license', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + + const response = await server.inject(createBulkMlRuleRequest(), context); + expect(response.status).toEqual(200); + expect(response.body).toEqual([ + { + error: { + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }, + rule_id: 'rule-1', + }, + ]); + }); + it('returns an error object if the index does not exist', async () => { clients.clusterClient.callAsCurrentUser.mockResolvedValue(getEmptyIndex()); const response = await server.inject(getReadBulkRequest(), context); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts index 4ffa29c385f28..1ca9f7ef9075e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts @@ -19,6 +19,7 @@ import { createBulkErrorObject, buildRouteValidation, buildSiemResponse, + validateLicenseForRuleType, } from '../utils'; import { createRulesBulkSchema } from '../schemas/create_rules_bulk_schema'; import { rulesBulkSchema } from '../schemas/response/rules_bulk_schema'; @@ -90,6 +91,8 @@ export const createRulesBulkRoute = (router: IRouter) => { } = payloadRule; const ruleIdOrUuid = ruleId ?? uuid.v4(); try { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); + const finalIndex = outputIndex ?? siemClient.signalsIndex; const indexExists = await getIndexExists(clusterClient.callAsCurrentUser, finalIndex); if (!indexExists) { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index 14592dd499d43..4da879d12f809 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -59,6 +59,13 @@ describe('create_rules', () => { expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); }); + + it('returns 200 if license is not platinum', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + + const response = await server.inject(getCreateRequest(), context); + expect(response.status).toEqual(200); + }); }); describe('creating an ML Rule', () => { @@ -66,6 +73,17 @@ describe('create_rules', () => { const response = await server.inject(createMlRuleRequest(), context); expect(response.status).toEqual(200); }); + + it('rejects the request if licensing is not platinum', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + + const response = await server.inject(createMlRuleRequest(), context); + expect(response.status).toEqual(400); + expect(response.body).toEqual({ + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }); + }); }); describe('creating a Notification if throttle and actions were provided ', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts index 1fbbb5274d738..edf37bcb8dbe7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.ts @@ -16,7 +16,12 @@ import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; import { transformValidate } from './validate'; import { getIndexExists } from '../../index/get_index_exists'; import { createRulesSchema } from '../schemas/create_rules_schema'; -import { buildRouteValidation, transformError, buildSiemResponse } from '../utils'; +import { + buildRouteValidation, + transformError, + buildSiemResponse, + validateLicenseForRuleType, +} from '../utils'; import { createNotifications } from '../../notifications/create_notifications'; export const createRulesRoute = (router: IRouter): void => { @@ -66,6 +71,7 @@ export const createRulesRoute = (router: IRouter): void => { const siemResponse = buildSiemResponse(response); try { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); if (!context.alerting || !context.actions) { return siemResponse.error({ statusCode: 404 }); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index f6e1cf6e2420c..aacf83b9ec58a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -9,6 +9,8 @@ import { ruleIdsToNdJsonString, rulesToNdJsonString, getSimpleRuleWithId, + getSimpleRule, + getSimpleMlRule, } from '../__mocks__/utils'; import { getImportRulesRequest, @@ -102,6 +104,30 @@ describe('import_rules_route', () => { }); describe('unhappy paths', () => { + it('returns an error object if creating an ML rule with an insufficient license', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + const rules = [getSimpleRule(), getSimpleMlRule('rule-2')]; + const hapiStreamWithMlRule = buildHapiStream(rulesToNdJsonString(rules)); + request = getImportRulesRequest(hapiStreamWithMlRule); + + const response = await server.inject(request, context); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + errors: [ + { + error: { + message: + 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }, + rule_id: 'rule-2', + }, + ], + success: false, + success_count: 1, + }); + }); + test('returns error if createPromiseFromStreams throws error', async () => { jest .spyOn(createRulesStreamFromNdJson, 'createRulesStreamFromNdJson') diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts index 4a5ea33025d49..2e6c72a87ec7f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts @@ -24,6 +24,7 @@ import { isImportRegular, transformError, buildSiemResponse, + validateLicenseForRuleType, } from '../utils'; import { createRulesStreamFromNdJson } from '../../rules/create_rules_stream_from_ndjson'; import { ImportRuleAlertRest } from '../../types'; @@ -146,6 +147,11 @@ export const importRulesRoute = (router: IRouter, config: LegacyServices['config } = parsedRule; try { + validateLicenseForRuleType({ + license: context.licensing.license, + ruleType: type, + }); + const signalsIndex = siemClient.signalsIndex; const indexExists = await getIndexExists( clusterClient.callAsCurrentUser, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 4c00cfa51c8ee..a1f39936dd674 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -11,6 +11,7 @@ import { getFindResultWithSingleHit, getPatchBulkRequest, getResult, + typicalMlRulePayload, } from '../__mocks__/request_responses'; import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { patchRulesBulkRoute } from './patch_rules_bulk_route'; @@ -88,6 +89,27 @@ describe('patch_rules_bulk', () => { expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); }); + + it('rejects patching of an ML rule with an insufficient license', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + const request = requestMock.create({ + method: 'patch', + path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + body: [typicalMlRulePayload()], + }); + + const response = await server.inject(request, context); + expect(response.status).toEqual(200); + expect(response.body).toEqual([ + { + error: { + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }, + rule_id: 'rule-1', + }, + ]); + }); }); describe('request validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts index a80f3fee6b433..645dbdadf8cab 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts @@ -10,7 +10,12 @@ import { IRuleSavedAttributesSavedObjectAttributes, PatchRuleAlertParamsRest, } from '../../rules/types'; -import { transformBulkError, buildRouteValidation, buildSiemResponse } from '../utils'; +import { + transformBulkError, + buildRouteValidation, + buildSiemResponse, + validateLicenseForRuleType, +} from '../utils'; import { getIdBulkError } from './utils'; import { transformValidateBulkError, validate } from './validate'; import { patchRulesBulkSchema } from '../schemas/patch_rules_bulk_schema'; @@ -80,6 +85,10 @@ export const patchRulesBulkRoute = (router: IRouter) => { } = payloadRule; const idOrRuleIdOrUnknown = id ?? ruleId ?? '(unknown id)'; try { + if (type) { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); + } + const rule = await patchRules({ alertsClient, actionsClient, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index 07519733db291..1e344d8ea7e31 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -13,6 +13,7 @@ import { typicalPayload, getFindResultWithSingleHit, nonRuleFindResult, + typicalMlRulePayload, } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { patchRulesRoute } from './patch_rules_route'; @@ -109,6 +110,22 @@ describe('patch_rules', () => { }) ); }); + + it('rejects patching a rule to ML if licensing is not platinum', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + const request = requestMock.create({ + method: 'patch', + path: DETECTION_ENGINE_RULES_URL, + body: typicalMlRulePayload(), + }); + const response = await server.inject(request, context); + + expect(response.status).toEqual(400); + expect(response.body).toEqual({ + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }); + }); }); describe('request validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.ts index c5ecb109f4595..620bcd8fc17b0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.ts @@ -12,7 +12,12 @@ import { IRuleSavedAttributesSavedObjectAttributes, } from '../../rules/types'; import { patchRulesSchema } from '../schemas/patch_rules_schema'; -import { buildRouteValidation, transformError, buildSiemResponse } from '../utils'; +import { + buildRouteValidation, + transformError, + buildSiemResponse, + validateLicenseForRuleType, +} from '../utils'; import { getIdError } from './utils'; import { transformValidate } from './validate'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; @@ -65,6 +70,10 @@ export const patchRulesRoute = (router: IRouter) => { const siemResponse = buildSiemResponse(response); try { + if (type) { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); + } + if (!context.alerting || !context.actions) { return siemResponse.error({ statusCode: 404 }); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index d530866edaf0d..611b38ccbae8b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -11,6 +11,7 @@ import { getFindResultWithSingleHit, getUpdateBulkRequest, getFindResultStatus, + typicalMlRulePayload, } from '../__mocks__/request_responses'; import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { updateRulesBulkRoute } from './update_rules_bulk_route'; @@ -83,6 +84,27 @@ describe('update_rules_bulk', () => { expect(response.status).toEqual(200); expect(response.body).toEqual(expected); }); + + it('returns an error object if creating an ML rule with an insufficient license', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + const request = requestMock.create({ + method: 'put', + path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, + body: [typicalMlRulePayload()], + }); + + const response = await server.inject(request, context); + expect(response.status).toEqual(200); + expect(response.body).toEqual([ + { + error: { + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }, + rule_id: 'rule-1', + }, + ]); + }); }); describe('request validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts index 6c3c8dffa3dfa..4abeb840c8c0a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts @@ -12,7 +12,12 @@ import { } from '../../rules/types'; import { getIdBulkError } from './utils'; import { transformValidateBulkError, validate } from './validate'; -import { buildRouteValidation, transformBulkError, buildSiemResponse } from '../utils'; +import { + buildRouteValidation, + transformBulkError, + buildSiemResponse, + validateLicenseForRuleType, +} from '../utils'; import { updateRulesBulkSchema } from '../schemas/update_rules_bulk_schema'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; import { updateRules } from '../../rules/update_rules'; @@ -83,6 +88,8 @@ export const updateRulesBulkRoute = (router: IRouter) => { const finalIndex = outputIndex ?? siemClient.signalsIndex; const idOrRuleIdOrUnknown = id ?? ruleId ?? '(unknown id)'; try { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); + const rule = await updateRules({ alertsClient, actionsClient, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index a15f1ca9b044e..717f2cc4a52fe 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -13,6 +13,7 @@ import { getFindResultWithSingleHit, getFindResultStatusEmpty, nonRuleFindResult, + typicalMlRulePayload, } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; @@ -88,6 +89,22 @@ describe('update_rules', () => { status_code: 500, }); }); + + it('rejects the request if licensing is not adequate', async () => { + (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); + const request = requestMock.create({ + method: 'put', + path: DETECTION_ENGINE_RULES_URL, + body: typicalMlRulePayload(), + }); + + const response = await server.inject(request, context); + expect(response.status).toEqual(400); + expect(response.body).toEqual({ + message: 'Your license does not support machine learning. Please upgrade your license.', + status_code: 400, + }); + }); }); describe('request validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts index f8cca6494e000..f0d5f08c5f636 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.ts @@ -11,7 +11,12 @@ import { IRuleSavedAttributesSavedObjectAttributes, } from '../../rules/types'; import { updateRulesSchema } from '../schemas/update_rules_schema'; -import { buildRouteValidation, transformError, buildSiemResponse } from '../utils'; +import { + buildRouteValidation, + transformError, + buildSiemResponse, + validateLicenseForRuleType, +} from '../utils'; import { getIdError } from './utils'; import { transformValidate } from './validate'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; @@ -67,6 +72,8 @@ export const updateRulesRoute = (router: IRouter) => { const siemResponse = buildSiemResponse(response); try { + validateLicenseForRuleType({ license: context.licensing.license, ruleType: type }); + if (!context.alerting || !context.actions) { return siemResponse.error({ statusCode: 404 }); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts index a0458dc3a133d..ca0d133627210 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts @@ -19,7 +19,12 @@ import { isRuleStatusFindTypes, isRuleStatusSavedObjectType, } from '../../rules/types'; -import { OutputRuleAlertRest, ImportRuleAlertRest, RuleAlertParamsRest } from '../../types'; +import { + OutputRuleAlertRest, + ImportRuleAlertRest, + RuleAlertParamsRest, + RuleType, +} from '../../types'; import { createBulkErrorObject, BulkError, @@ -295,3 +300,5 @@ export const getTupleDuplicateErrorsAndUniqueRules = ( return [Array.from(errors.values()), Array.from(rulesAcc.values())]; }; + +export const isMlRule = (ruleType: RuleType) => ruleType === 'machine_learning'; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts index fdb1cd148c7fa..9efe4e491968b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts @@ -19,9 +19,11 @@ import { transformImportError, convertToSnakeCase, SiemResponseFactory, + validateLicenseForRuleType, } from './utils'; import { responseMock } from './__mocks__'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../feature_flags'; +import { licensingMock } from '../../../../../../../plugins/licensing/server/mocks'; describe('utils', () => { beforeAll(() => { @@ -359,4 +361,36 @@ describe('utils', () => { ); }); }); + + describe('validateLicenseForRuleType', () => { + let licenseMock: ReturnType; + + beforeEach(() => { + licenseMock = licensingMock.createLicenseMock(); + }); + + it('throws a BadRequestError if operating on an ML Rule with an insufficient license', () => { + licenseMock.hasAtLeast.mockReturnValue(false); + + expect(() => + validateLicenseForRuleType({ license: licenseMock, ruleType: 'machine_learning' }) + ).toThrowError(BadRequestError); + }); + + it('does not throw if operating on an ML Rule with a sufficient license', () => { + licenseMock.hasAtLeast.mockReturnValue(true); + + expect(() => + validateLicenseForRuleType({ license: licenseMock, ruleType: 'machine_learning' }) + ).not.toThrowError(BadRequestError); + }); + + it('does not throw if operating on a query rule', () => { + licenseMock.hasAtLeast.mockReturnValue(false); + + expect(() => + validateLicenseForRuleType({ license: licenseMock, ruleType: 'query' }) + ).not.toThrowError(BadRequestError); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts index 79c2f47658f7e..90c7d4a07ddf8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts @@ -7,13 +7,18 @@ import Boom from 'boom'; import Joi from 'joi'; import { has, snakeCase } from 'lodash/fp'; +import { i18n } from '@kbn/i18n'; import { RouteValidationFunction, KibanaResponseFactory, CustomHttpResponseOptions, } from '../../../../../../../../src/core/server'; +import { ILicense } from '../../../../../../../plugins/licensing/server'; +import { MINIMUM_ML_LICENSE } from '../../../../common/constants'; import { BadRequestError } from '../errors/bad_request_error'; +import { RuleType } from '../types'; +import { isMlRule } from './rules/utils'; export interface OutputError { message: string; @@ -289,3 +294,28 @@ export const convertToSnakeCase = >( return { ...acc, [newKey]: obj[item] }; }, {}); }; + +/** + * Checks the current Kibana License against the rule under operation. + * + * @param license ILicense representing the user license + * @param ruleType the type of the current rule + * + * @throws BadRequestError if rule and license are incompatible + */ +export const validateLicenseForRuleType = ({ + license, + ruleType, +}: { + license: ILicense; + ruleType: RuleType; +}) => { + if (isMlRule(ruleType) && !license.hasAtLeast(MINIMUM_ML_LICENSE)) { + const message = i18n.translate('xpack.siem.licensing.unsupportedMachineLearningMessage', { + defaultMessage: + 'Your license does not support machine learning. Please upgrade your license.', + }); + + throw new BadRequestError(message); + } +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/saved_object_mappings.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/saved_object_mappings.ts index fd3d35e9f6785..1d91def5fa6cc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/saved_object_mappings.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/saved_object_mappings.ts @@ -4,14 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ElasticsearchMappingOf } from '../../../utils/typed_elasticsearch_mappings'; -import { IRuleStatusAttributes } from './types'; - export const ruleStatusSavedObjectType = 'siem-detection-engine-rule-status'; -export const ruleStatusSavedObjectMappings: { - [ruleStatusSavedObjectType]: ElasticsearchMappingOf; -} = { +export const ruleStatusSavedObjectMappings = { [ruleStatusSavedObjectType]: { properties: { alertId: { @@ -35,6 +30,18 @@ export const ruleStatusSavedObjectMappings: { lastSuccessMessage: { type: 'text', }, + lastLookBackDate: { + type: 'date', + }, + gap: { + type: 'text', + }, + bulkCreateTimeDurations: { + type: 'float', + }, + searchAfterTimeDurations: { + type: 'float', + }, }, }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts index 1efa46c6b8b57..ada11174c5340 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts @@ -60,6 +60,10 @@ export interface IRuleStatusAttributes extends Record { lastSuccessAt: string | null | undefined; lastSuccessMessage: string | null | undefined; status: RuleStatusString | null | undefined; + lastLookBackDate: string | null | undefined; + gap: string | null | undefined; + bulkCreateTimeDurations: string[] | null | undefined; + searchAfterTimeDurations: string[] | null | undefined; } export interface RuleStatusResponse { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/bulk_create_ml_signals.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/bulk_create_ml_signals.ts index 66e9f42061658..c1b61ef24462d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/bulk_create_ml_signals.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/bulk_create_ml_signals.ts @@ -11,7 +11,7 @@ import { Logger } from '../../../../../../../../src/core/server'; import { AlertServices } from '../../../../../../../plugins/alerting/server'; import { RuleAlertAction } from '../../../../common/detection_engine/types'; import { RuleTypeParams } from '../types'; -import { singleBulkCreate } from './single_bulk_create'; +import { singleBulkCreate, SingleBulkCreateResponse } from './single_bulk_create'; import { AnomalyResults, Anomaly } from '../../machine_learning'; interface BulkCreateMlSignalsParams { @@ -75,7 +75,9 @@ const transformAnomalyResultsToEcs = (results: AnomalyResults): SearchResponse { +export const bulkCreateMlSignals = async ( + params: BulkCreateMlSignalsParams +): Promise => { const anomalyResults = params.someResult; const ecsResults = transformAnomalyResultsToEcs(anomalyResults); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_current_status_saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_current_status_saved_object.ts index e5057b6b68997..1fee8bcd6c2f0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_current_status_saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/get_current_status_saved_object.ts @@ -36,6 +36,10 @@ export const getCurrentStatusSavedObject = async ({ lastSuccessAt: null, lastFailureMessage: null, lastSuccessMessage: null, + gap: null, + bulkCreateTimeDurations: [], + searchAfterTimeDurations: [], + lastLookBackDate: null, }); return currentStatusSavedObject; } else { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts index 315a5dd88d94e..b12c21b7a5b56 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.test.ts @@ -34,7 +34,7 @@ describe('searchAfterAndBulkCreate', () => { test('if successful with empty search results', async () => { const sampleParams = sampleRuleAlertParams(); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: sampleEmptyDocSearchResults(), ruleParams: sampleParams, services: mockService, @@ -56,7 +56,7 @@ describe('searchAfterAndBulkCreate', () => { throttle: null, }); expect(mockService.callCluster).toHaveBeenCalledTimes(0); - expect(result).toEqual(true); + expect(success).toEqual(true); }); test('if successful iteration of while loop with maxDocs', async () => { @@ -92,7 +92,7 @@ describe('searchAfterAndBulkCreate', () => { }, ], }); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(3, 1, someGuids.slice(6, 9)), ruleParams: sampleParams, services: mockService, @@ -114,14 +114,14 @@ describe('searchAfterAndBulkCreate', () => { throttle: null, }); expect(mockService.callCluster).toHaveBeenCalledTimes(5); - expect(result).toEqual(true); + expect(success).toEqual(true); }); test('if unsuccessful first bulk create', async () => { const someGuids = Array.from({ length: 4 }).map(x => uuid.v4()); const sampleParams = sampleRuleAlertParams(10); mockService.callCluster.mockReturnValue(sampleBulkCreateDuplicateResult); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(4, 1, someGuids), ruleParams: sampleParams, services: mockService, @@ -143,7 +143,7 @@ describe('searchAfterAndBulkCreate', () => { throttle: null, }); expect(mockLogger.error).toHaveBeenCalled(); - expect(result).toEqual(false); + expect(success).toEqual(false); }); test('if unsuccessful iteration of searchAfterAndBulkCreate due to empty sort ids', async () => { @@ -157,7 +157,7 @@ describe('searchAfterAndBulkCreate', () => { }, ], }); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: sampleDocSearchResultsNoSortId(), ruleParams: sampleParams, services: mockService, @@ -179,7 +179,7 @@ describe('searchAfterAndBulkCreate', () => { throttle: null, }); expect(mockLogger.error).toHaveBeenCalled(); - expect(result).toEqual(false); + expect(success).toEqual(false); }); test('if unsuccessful iteration of searchAfterAndBulkCreate due to empty sort ids and 0 total hits', async () => { @@ -193,7 +193,7 @@ describe('searchAfterAndBulkCreate', () => { }, ], }); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: sampleDocSearchResultsNoSortIdNoHits(), ruleParams: sampleParams, services: mockService, @@ -214,7 +214,7 @@ describe('searchAfterAndBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(result).toEqual(true); + expect(success).toEqual(true); }); test('if successful iteration of while loop with maxDocs and search after returns results with no sort ids', async () => { @@ -231,7 +231,7 @@ describe('searchAfterAndBulkCreate', () => { ], }) .mockReturnValueOnce(sampleDocSearchResultsNoSortId()); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(4, 1, someGuids), ruleParams: sampleParams, services: mockService, @@ -252,7 +252,7 @@ describe('searchAfterAndBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(result).toEqual(true); + expect(success).toEqual(true); }); test('if successful iteration of while loop with maxDocs and search after returns empty results with no sort ids', async () => { @@ -269,7 +269,7 @@ describe('searchAfterAndBulkCreate', () => { ], }) .mockReturnValueOnce(sampleEmptyDocSearchResults()); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(4, 1, someGuids), ruleParams: sampleParams, services: mockService, @@ -290,7 +290,7 @@ describe('searchAfterAndBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(result).toEqual(true); + expect(success).toEqual(true); }); test('if returns false when singleSearchAfter throws an exception', async () => { @@ -309,7 +309,7 @@ describe('searchAfterAndBulkCreate', () => { .mockImplementation(() => { throw Error('Fake Error'); }); - const result = await searchAfterAndBulkCreate({ + const { success } = await searchAfterAndBulkCreate({ someResult: repeatedSearchResultsWithSortId(4, 1, someGuids), ruleParams: sampleParams, services: mockService, @@ -330,6 +330,6 @@ describe('searchAfterAndBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(result).toEqual(false); + expect(success).toEqual(false); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.ts index 4f1a187a82937..ff263333fb798 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/search_after_bulk_create.ts @@ -34,6 +34,13 @@ interface SearchAfterAndBulkCreateParams { throttle: string | null; } +export interface SearchAfterAndBulkCreateReturnType { + success: boolean; + searchAfterTimes: string[]; + bulkCreateTimes: string[]; + lastLookBackDate: Date | null | undefined; +} + // search_after through documents and re-index using bulk endpoint. export const searchAfterAndBulkCreate = async ({ someResult, @@ -55,13 +62,20 @@ export const searchAfterAndBulkCreate = async ({ pageSize, tags, throttle, -}: SearchAfterAndBulkCreateParams): Promise => { +}: SearchAfterAndBulkCreateParams): Promise => { + const toReturn: SearchAfterAndBulkCreateReturnType = { + success: false, + searchAfterTimes: [], + bulkCreateTimes: [], + lastLookBackDate: null, + }; if (someResult.hits.hits.length === 0) { - return true; + toReturn.success = true; + return toReturn; } logger.debug('[+] starting bulk insertion'); - await singleBulkCreate({ + const { bulkCreateDuration } = await singleBulkCreate({ someResult, ruleParams, services, @@ -79,6 +93,13 @@ export const searchAfterAndBulkCreate = async ({ tags, throttle, }); + toReturn.lastLookBackDate = + someResult.hits.hits.length > 0 + ? new Date(someResult.hits.hits[someResult.hits.hits.length - 1]?._source['@timestamp']) + : null; + if (bulkCreateDuration) { + toReturn.bulkCreateTimes.push(bulkCreateDuration); + } const totalHits = typeof someResult.hits.total === 'number' ? someResult.hits.total : someResult.hits.total.value; // maxTotalHitsSize represents the total number of docs to @@ -94,9 +115,11 @@ export const searchAfterAndBulkCreate = async ({ let sortIds = someResult.hits.hits[0].sort; if (sortIds == null && totalHits > 0) { logger.error('sortIds was empty on first search but expected more'); - return false; + toReturn.success = false; + return toReturn; } else if (sortIds == null && totalHits === 0) { - return true; + toReturn.success = true; + return toReturn; } let sortId; if (sortIds != null) { @@ -105,7 +128,10 @@ export const searchAfterAndBulkCreate = async ({ while (hitsSize < maxTotalHitsSize && hitsSize !== 0) { try { logger.debug(`sortIds: ${sortIds}`); - const searchAfterResult: SignalSearchResponse = await singleSearchAfter({ + const { + searchResult, + searchDuration, + }: { searchResult: SignalSearchResponse; searchDuration: string } = await singleSearchAfter({ searchAfterSortId: sortId, index: inputIndexPattern, from: ruleParams.from, @@ -115,20 +141,23 @@ export const searchAfterAndBulkCreate = async ({ filter, pageSize, // maximum number of docs to receive per search result. }); - if (searchAfterResult.hits.hits.length === 0) { - return true; + toReturn.searchAfterTimes.push(searchDuration); + if (searchResult.hits.hits.length === 0) { + toReturn.success = true; + return toReturn; } - hitsSize += searchAfterResult.hits.hits.length; + hitsSize += searchResult.hits.hits.length; logger.debug(`size adjusted: ${hitsSize}`); - sortIds = searchAfterResult.hits.hits[0].sort; + sortIds = searchResult.hits.hits[0].sort; if (sortIds == null) { logger.debug('sortIds was empty on search'); - return true; // no more search results + toReturn.success = true; + return toReturn; // no more search results } sortId = sortIds[0]; logger.debug('next bulk index'); - await singleBulkCreate({ - someResult: searchAfterResult, + const { bulkCreateDuration: bulkDuration } = await singleBulkCreate({ + someResult: searchResult, ruleParams, services, logger, @@ -146,11 +175,16 @@ export const searchAfterAndBulkCreate = async ({ throttle, }); logger.debug('finished next bulk index'); + if (bulkDuration) { + toReturn.bulkCreateTimes.push(bulkDuration); + } } catch (exc) { logger.error(`[-] search_after and bulk threw an error ${exc}`); - return false; + toReturn.success = false; + return toReturn; } } logger.debug(`[+] completed bulk index of ${maxTotalHitsSize}`); - return true; + toReturn.success = true; + return toReturn; }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 03d48a6b27867..ab9def14bef65 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { performance } from 'perf_hooks'; import { Logger } from 'src/core/server'; import { SIGNALS_ID, @@ -13,10 +14,13 @@ import { import { buildEventsSearchQuery } from './build_events_query'; import { getInputIndex } from './get_input_output_index'; -import { searchAfterAndBulkCreate } from './search_after_bulk_create'; +import { + searchAfterAndBulkCreate, + SearchAfterAndBulkCreateReturnType, +} from './search_after_bulk_create'; import { getFilter } from './get_filter'; import { SignalRuleAlertTypeDefinition, RuleAlertAttributes } from './types'; -import { getGapBetweenRuns } from './utils'; +import { getGapBetweenRuns, makeFloatString } from './utils'; import { writeSignalRuleExceptionToSavedObject } from './write_signal_rule_exception_to_saved_object'; import { signalParamsSchema } from './signal_params_schema'; import { siemRuleActionGroups } from './siem_rule_action_groups'; @@ -92,7 +96,6 @@ export const signalRulesAlertType = ({ const updatedAt = savedObject.updated_at ?? ''; const gap = getGapBetweenRuns({ previousStartedAt, interval, from, to }); - await writeGapErrorToSavedObject({ alertId, logger, @@ -105,7 +108,12 @@ export const signalRulesAlertType = ({ }); const searchAfterSize = Math.min(params.maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE); - let creationSucceeded = false; + let creationSucceeded: SearchAfterAndBulkCreateReturnType = { + success: false, + bulkCreateTimes: [], + searchAfterTimes: [], + lastLookBackDate: null, + }; try { if (type === 'machine_learning') { @@ -130,7 +138,7 @@ export const signalRulesAlertType = ({ ); } - creationSucceeded = await bulkCreateMlSignals({ + const { success, bulkCreateDuration } = await bulkCreateMlSignals({ actions, throttle, someResult: anomalyResults, @@ -148,6 +156,10 @@ export const signalRulesAlertType = ({ enabled, tags, }); + creationSucceeded.success = success; + if (bulkCreateDuration) { + creationSucceeded.bulkCreateTimes.push(bulkCreateDuration); + } } else { const inputIndex = await getInputIndex(services, version, index); const esFilter = await getFilter({ @@ -175,7 +187,10 @@ export const signalRulesAlertType = ({ logger.debug( `[+] Initial search call of signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}"` ); + const start = performance.now(); const noReIndexResult = await services.callCluster('search', noReIndex); + const end = performance.now(); + if (noReIndexResult.hits.total.value !== 0) { logger.info( `Found ${ @@ -207,20 +222,22 @@ export const signalRulesAlertType = ({ tags, throttle, }); + creationSucceeded.searchAfterTimes.push(makeFloatString(end - start)); } - if (creationSucceeded) { + if (creationSucceeded.success) { if (meta?.throttle === NOTIFICATION_THROTTLE_RULE && actions.length) { const notificationRuleParams = { ...ruleParams, name, + id: savedObject.id, }; const { signalsCount, resultsLink } = await getSignalsCount({ from: `now-${interval}`, to: 'now', index: ruleParams.outputIndex, ruleId: ruleParams.ruleId!, - kibanaUrl: meta?.kibanaUrl as string, + kibanaSiemAppUrl: meta.kibanaSiemAppUrl as string, ruleAlertId: savedObject.id, callCluster: services.callCluster, }); @@ -241,11 +258,14 @@ export const signalRulesAlertType = ({ } logger.debug( - `Finished signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}", output_index: "${outputIndex}"` + `Finished signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}"` ); await writeCurrentStatusSucceeded({ services, currentStatusSavedObject, + bulkCreateTimes: creationSucceeded.bulkCreateTimes, + searchAfterTimes: creationSucceeded.searchAfterTimes, + lastLookBackDate: creationSucceeded.lastLookBackDate?.toISOString() ?? null, }); } else { await writeSignalRuleExceptionToSavedObject({ @@ -253,22 +273,28 @@ export const signalRulesAlertType = ({ alertId, currentStatusSavedObject, logger, - message: `Bulk Indexing signals failed. Check logs for further details Rule name: "${name}" id: "${alertId}" rule_id: "${ruleId}" output_index: "${outputIndex}"`, + message: `Bulk Indexing signals failed. Check logs for further details \nRule name: "${name}"\nid: "${alertId}"\nrule_id: "${ruleId}"\n`, services, ruleStatusSavedObjects, ruleId: ruleId ?? '(unknown rule id)', + bulkCreateTimes: creationSucceeded.bulkCreateTimes, + searchAfterTimes: creationSucceeded.searchAfterTimes, + lastLookBackDate: creationSucceeded.lastLookBackDate?.toISOString() ?? null, }); } - } catch (error) { + } catch (err) { await writeSignalRuleExceptionToSavedObject({ name, alertId, currentStatusSavedObject, logger, - message: error?.message ?? '(no error message given)', + message: `Bulk Indexing signals failed. Check logs for further details \nRule name: "${name}"\nid: "${alertId}"\nrule_id: "${ruleId}"\n`, services, ruleStatusSavedObjects, ruleId: ruleId ?? '(unknown rule id)', + bulkCreateTimes: creationSucceeded.bulkCreateTimes, + searchAfterTimes: creationSucceeded.searchAfterTimes, + lastLookBackDate: creationSucceeded.lastLookBackDate?.toISOString() ?? null, }); } }, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts index afabd4c44de7d..93f9c24a057f2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.test.ts @@ -144,7 +144,7 @@ describe('singleBulkCreate', () => { }, ], }); - const successfulsingleBulkCreate = await singleBulkCreate({ + const { success } = await singleBulkCreate({ someResult: sampleDocSearchResultsNoSortId(), ruleParams: sampleParams, services: mockService, @@ -162,7 +162,7 @@ describe('singleBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(successfulsingleBulkCreate).toEqual(true); + expect(success).toEqual(true); }); test('create successful bulk create with docs with no versioning', async () => { @@ -176,7 +176,7 @@ describe('singleBulkCreate', () => { }, ], }); - const successfulsingleBulkCreate = await singleBulkCreate({ + const { success } = await singleBulkCreate({ someResult: sampleDocSearchResultsNoSortIdNoVersion(), ruleParams: sampleParams, services: mockService, @@ -194,13 +194,13 @@ describe('singleBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(successfulsingleBulkCreate).toEqual(true); + expect(success).toEqual(true); }); test('create unsuccessful bulk create due to empty search results', async () => { const sampleParams = sampleRuleAlertParams(); mockService.callCluster.mockReturnValue(false); - const successfulsingleBulkCreate = await singleBulkCreate({ + const { success } = await singleBulkCreate({ someResult: sampleEmptyDocSearchResults(), ruleParams: sampleParams, services: mockService, @@ -218,14 +218,14 @@ describe('singleBulkCreate', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: null, }); - expect(successfulsingleBulkCreate).toEqual(true); + expect(success).toEqual(true); }); test('create successful bulk create when bulk create has duplicate errors', async () => { const sampleParams = sampleRuleAlertParams(); const sampleSearchResult = sampleDocSearchResultsNoSortId; mockService.callCluster.mockReturnValue(sampleBulkCreateDuplicateResult); - const successfulsingleBulkCreate = await singleBulkCreate({ + const { success } = await singleBulkCreate({ someResult: sampleSearchResult(), ruleParams: sampleParams, services: mockService, @@ -245,14 +245,14 @@ describe('singleBulkCreate', () => { }); expect(mockLogger.error).not.toHaveBeenCalled(); - expect(successfulsingleBulkCreate).toEqual(true); + expect(success).toEqual(true); }); test('create successful bulk create when bulk create has multiple error statuses', async () => { const sampleParams = sampleRuleAlertParams(); const sampleSearchResult = sampleDocSearchResultsNoSortId; mockService.callCluster.mockReturnValue(sampleBulkCreateErrorResult); - const successfulsingleBulkCreate = await singleBulkCreate({ + const { success } = await singleBulkCreate({ someResult: sampleSearchResult(), ruleParams: sampleParams, services: mockService, @@ -272,7 +272,7 @@ describe('singleBulkCreate', () => { }); expect(mockLogger.error).toHaveBeenCalled(); - expect(successfulsingleBulkCreate).toEqual(true); + expect(success).toEqual(true); }); test('filter duplicate rules will return an empty array given an empty array', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts index e2e4471f609ac..0192ff76efa54 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_bulk_create.ts @@ -10,7 +10,7 @@ import { AlertServices } from '../../../../../../../plugins/alerting/server'; import { SignalSearchResponse, BulkResponse } from './types'; import { RuleAlertAction } from '../../../../common/detection_engine/types'; import { RuleTypeParams } from '../types'; -import { generateId } from './utils'; +import { generateId, makeFloatString } from './utils'; import { buildBulkBody } from './build_bulk_body'; import { Logger } from '../../../../../../../../src/core/server'; @@ -55,6 +55,11 @@ export const filterDuplicateRules = ( }); }; +export interface SingleBulkCreateResponse { + success: boolean; + bulkCreateDuration?: string; +} + // Bulk Index documents. export const singleBulkCreate = async ({ someResult, @@ -73,11 +78,10 @@ export const singleBulkCreate = async ({ enabled, tags, throttle, -}: SingleBulkCreateParams): Promise => { +}: SingleBulkCreateParams): Promise => { someResult.hits.hits = filterDuplicateRules(id, someResult); - if (someResult.hits.hits.length === 0) { - return true; + return { success: true }; } // index documents after creating an ID based on the // source documents' originating index, and the original @@ -123,7 +127,7 @@ export const singleBulkCreate = async ({ body: bulkBody, }); const end = performance.now(); - logger.debug(`individual bulk process time took: ${Number(end - start).toFixed(2)} milliseconds`); + logger.debug(`individual bulk process time took: ${makeFloatString(end - start)} milliseconds`); logger.debug(`took property says bulk took: ${response.took} milliseconds`); if (response.errors) { @@ -141,5 +145,5 @@ export const singleBulkCreate = async ({ ); } } - return true; + return { success: true, bulkCreateDuration: makeFloatString(end - start) }; }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.test.ts index 1685c6518def3..9b726c38d3d96 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.test.ts @@ -42,7 +42,7 @@ describe('singleSearchAfter', () => { test('if singleSearchAfter works with a given sort id', async () => { const searchAfterSortId = '1234567891111'; mockService.callCluster.mockReturnValue(sampleDocSearchResultsWithSortId); - const searchAfterResult = await singleSearchAfter({ + const { searchResult } = await singleSearchAfter({ searchAfterSortId, index: [], from: 'now-360s', @@ -52,7 +52,7 @@ describe('singleSearchAfter', () => { pageSize: 1, filter: undefined, }); - expect(searchAfterResult).toEqual(sampleDocSearchResultsWithSortId); + expect(searchResult).toEqual(sampleDocSearchResultsWithSortId); }); test('if singleSearchAfter throws error', async () => { const searchAfterSortId = '1234567891111'; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.ts index bb12b5a802f8f..6fc8fe4bd24d9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/single_search_after.ts @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { performance } from 'perf_hooks'; import { AlertServices } from '../../../../../../../plugins/alerting/server'; import { Logger } from '../../../../../../../../src/core/server'; import { SignalSearchResponse } from './types'; import { buildEventsSearchQuery } from './build_events_query'; +import { makeFloatString } from './utils'; interface SingleSearchAfterParams { searchAfterSortId: string | undefined; @@ -30,7 +32,10 @@ export const singleSearchAfter = async ({ filter, logger, pageSize, -}: SingleSearchAfterParams): Promise => { +}: SingleSearchAfterParams): Promise<{ + searchResult: SignalSearchResponse; + searchDuration: string; +}> => { if (searchAfterSortId == null) { throw Error('Attempted to search after with empty sort id'); } @@ -43,11 +48,13 @@ export const singleSearchAfter = async ({ size: pageSize, searchAfterSortId, }); + const start = performance.now(); const nextSearchAfterResult: SignalSearchResponse = await services.callCluster( 'search', searchAfterQuery ); - return nextSearchAfterResult; + const end = performance.now(); + return { searchResult: nextSearchAfterResult, searchDuration: makeFloatString(end - start) }; } catch (exc) { logger.error(`[-] nextSearchAfter threw an error ${exc}`); throw exc; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/utils.ts index 8e7fb9c38d658..49af310db559f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/utils.ts @@ -89,3 +89,5 @@ export const getGapBetweenRuns = ({ const drift = diff.subtract(intervalDuration); return drift.subtract(driftTolerance); }; + +export const makeFloatString = (num: number): string => Number(num).toFixed(2); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_current_status_succeeded.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_current_status_succeeded.ts index 6b06235b29063..50136790c3479 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_current_status_succeeded.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_current_status_succeeded.ts @@ -13,17 +13,32 @@ import { IRuleSavedAttributesSavedObjectAttributes } from '../rules/types'; interface GetRuleStatusSavedObject { services: AlertServices; currentStatusSavedObject: SavedObject; + lastLookBackDate: string | null | undefined; + bulkCreateTimes: string[] | null | undefined; + searchAfterTimes: string[] | null | undefined; } export const writeCurrentStatusSucceeded = async ({ services, currentStatusSavedObject, + lastLookBackDate, + bulkCreateTimes, + searchAfterTimes, }: GetRuleStatusSavedObject): Promise => { const sDate = new Date().toISOString(); currentStatusSavedObject.attributes.status = 'succeeded'; currentStatusSavedObject.attributes.statusDate = sDate; currentStatusSavedObject.attributes.lastSuccessAt = sDate; currentStatusSavedObject.attributes.lastSuccessMessage = 'succeeded'; + if (lastLookBackDate != null) { + currentStatusSavedObject.attributes.lastLookBackDate = lastLookBackDate; + } + if (bulkCreateTimes != null) { + currentStatusSavedObject.attributes.bulkCreateTimeDurations = bulkCreateTimes; + } + if (searchAfterTimes != null) { + currentStatusSavedObject.attributes.searchAfterTimeDurations = searchAfterTimes; + } await services.savedObjectsClient.update(ruleStatusSavedObjectType, currentStatusSavedObject.id, { ...currentStatusSavedObject.attributes, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_gap_error_to_saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_gap_error_to_saved_object.ts index 3650548c80ad5..e47e5388527da 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_gap_error_to_saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_gap_error_to_saved_object.ts @@ -48,6 +48,7 @@ export const writeGapErrorToSavedObject = async ({ lastSuccessAt: currentStatusSavedObject.attributes.lastSuccessAt, lastFailureMessage: `Signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}" has a time gap of ${gap.humanize()} (${gap.asMilliseconds()}ms), and could be missing signals within that time. Consider increasing your look behind time or adding more Kibana instances.`, lastSuccessMessage: currentStatusSavedObject.attributes.lastSuccessMessage, + gap: gap.humanize(), }); if (ruleStatusSavedObjects.saved_objects.length >= 6) { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_signal_rule_exception_to_saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_signal_rule_exception_to_saved_object.ts index 5ca0808902a52..2a14184859591 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_signal_rule_exception_to_saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/signals/write_signal_rule_exception_to_saved_object.ts @@ -19,6 +19,9 @@ interface SignalRuleExceptionParams { message: string; services: AlertServices; name: string; + lastLookBackDate?: string | null | undefined; + bulkCreateTimes?: string[] | null | undefined; + searchAfterTimes?: string[] | null | undefined; } export const writeSignalRuleExceptionToSavedObject = async ({ @@ -30,6 +33,9 @@ export const writeSignalRuleExceptionToSavedObject = async ({ ruleStatusSavedObjects, ruleId, name, + lastLookBackDate, + bulkCreateTimes, + searchAfterTimes, }: SignalRuleExceptionParams): Promise => { logger.error( `Error from signal rule name: "${name}", id: "${alertId}", rule_id: "${ruleId}" message: ${message}` @@ -39,6 +45,15 @@ export const writeSignalRuleExceptionToSavedObject = async ({ currentStatusSavedObject.attributes.statusDate = sDate; currentStatusSavedObject.attributes.lastFailureAt = sDate; currentStatusSavedObject.attributes.lastFailureMessage = message; + if (lastLookBackDate) { + currentStatusSavedObject.attributes.lastLookBackDate = lastLookBackDate; + } + if (bulkCreateTimes) { + currentStatusSavedObject.attributes.bulkCreateTimeDurations = bulkCreateTimes; + } + if (searchAfterTimes) { + currentStatusSavedObject.attributes.searchAfterTimeDurations = searchAfterTimes; + } // current status is failing await services.savedObjectsClient.update(ruleStatusSavedObjectType, currentStatusSavedObject.id, { ...currentStatusSavedObject.attributes, diff --git a/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts b/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts index eb483de000915..f2662c79d3393 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ecs_fields/index.ts @@ -316,6 +316,7 @@ export const signalFieldsMap: Readonly> = { 'signal.rule.created_by': 'signal.rule.created_by', 'signal.rule.updated_by': 'signal.rule.updated_by', 'signal.rule.version': 'signal.rule.version', + 'signal.rule.note': 'signal.rule.note', }; export const ruleFieldsMap: Readonly> = { diff --git a/x-pack/legacy/plugins/siem/server/lib/framework/kibana_framework_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/framework/kibana_framework_adapter.ts index 004ac36bad5b4..6b41426e047ca 100644 --- a/x-pack/legacy/plugins/siem/server/lib/framework/kibana_framework_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/framework/kibana_framework_adapter.ts @@ -122,7 +122,7 @@ export class KibanaBackendFrameworkAdapter implements FrameworkAdapter { private async getCurrentUserInfo(request: KibanaRequest): Promise { try { - const user = await this.security.authc.getCurrentUser(request); + const user = (await this.security?.authc.getCurrentUser(request)) ?? null; return user; } catch { return null; diff --git a/x-pack/legacy/plugins/siem/server/lib/note/saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/note/saved_object.ts index b6a43fc523adb..23162f38bffba 100644 --- a/x-pack/legacy/plugins/siem/server/lib/note/saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/note/saved_object.ts @@ -141,6 +141,8 @@ export class Note { } // Update new note + + const existingNote = await this.getSavedNote(request, noteId); return { code: 200, message: 'success', @@ -150,7 +152,7 @@ export class Note { noteId, pickSavedNote(noteId, note, request.user), { - version: version || undefined, + version: existingNote.version || undefined, } ) ), diff --git a/x-pack/legacy/plugins/siem/server/lib/pinned_event/saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/pinned_event/saved_object.ts index 9ea950e8a443b..a95c1da197f57 100644 --- a/x-pack/legacy/plugins/siem/server/lib/pinned_event/saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/pinned_event/saved_object.ts @@ -89,7 +89,7 @@ export class PinnedEvent { public async persistPinnedEventOnTimeline( request: FrameworkRequest, - pinnedEventId: string | null, + pinnedEventId: string | null, // pinned event saved object id eventId: string, timelineId: string | null ): Promise { @@ -116,6 +116,7 @@ export class PinnedEvent { const isPinnedAlreadyExisting = allPinnedEventId.filter( pinnedEvent => pinnedEvent.eventId === eventId ); + if (isPinnedAlreadyExisting.length === 0) { const savedPinnedEvent: SavedPinnedEvent = { eventId, @@ -204,7 +205,7 @@ export const convertSavedObjectToSavedPinnedEvent = ( // then this interface does not allow types without index signature // this is limiting us with our type for now so the easy way was to use any -const pickSavedPinnedEvent = ( +export const pickSavedPinnedEvent = ( pinnedEventId: string | null, savedPinnedEvent: SavedPinnedEvent, userInfo: AuthenticatedUser | null diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/create_timelines_stream_from_ndjson.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/create_timelines_stream_from_ndjson.ts new file mode 100644 index 0000000000000..5373570a4f8cc --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/create_timelines_stream_from_ndjson.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Transform } from 'stream'; +import { + createConcatStream, + createSplitStream, + createMapStream, +} from '../../../../../../../src/legacy/utils'; +import { + parseNdjsonStrings, + filterExportedCounts, + createLimitStream, +} from '../detection_engine/rules/create_rules_stream_from_ndjson'; +import { importTimelinesSchema } from './routes/schemas/import_timelines_schema'; +import { BadRequestError } from '../detection_engine/errors/bad_request_error'; +import { ImportTimelineResponse } from './routes/utils/import_timelines'; + +export const validateTimelines = (): Transform => { + return createMapStream((obj: ImportTimelineResponse) => { + if (!(obj instanceof Error)) { + const validated = importTimelinesSchema.validate(obj); + if (validated.error != null) { + return new BadRequestError(validated.error.message); + } else { + return validated.value; + } + } else { + return obj; + } + }); +}; + +export const createTimelinesStreamFromNdJson = (ruleLimit: number) => { + return [ + createSplitStream('\n'), + parseNdjsonStrings(), + filterExportedCounts(), + validateTimelines(), + createLimitStream(ruleLimit), + createConcatStream([]), + ]; +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/import_timelines.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/import_timelines.ts new file mode 100644 index 0000000000000..74d3744e29299 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/import_timelines.ts @@ -0,0 +1,177 @@ +/* + * 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 { omit } from 'lodash/fp'; + +export const mockDuplicateIdErrors = []; + +export const mockParsedObjects = [ + { + savedObjectId: '79deb4c0-6bc1-11ea-a90b-f5341fb7a189', + version: 'WzEyMjUsMV0=', + columns: [], + dataProviders: [], + description: 'description', + eventType: 'all', + filters: [], + kqlMode: 'filter', + kqlQuery: { filterQuery: [Object] }, + title: 'My duplicate timeline', + dateRange: { start: 1584523907294, end: 1584610307294 }, + savedQueryId: null, + sort: { columnId: '@timestamp', sortDirection: 'desc' }, + created: 1584828930463, + createdBy: 'angela', + updated: 1584868346013, + updatedBy: 'angela', + eventNotes: [ + { + noteId: '73ac2370-6bc2-11ea-a90b-f5341fb7a189', + version: 'WzExMjgsMV0=', + eventId: 'ZaAi8nAB5OldxqFfdhke', + note: 'event note2', + timelineId: 'da49a0e0-6bc1-11ea-a90b-f5341fb7a189', + created: 1584829349563, + createdBy: 'angela', + updated: 1584829349563, + updatedBy: 'angela', + }, + { + noteId: 'f7b71620-6bc2-11ea-a0b6-33c7b2a78885', + version: 'WzExMzUsMV0=', + eventId: 'ZaAi8nAB5OldxqFfdhke', + note: 'event note2', + timelineId: 'da49a0e0-6bc1-11ea-a90b-f5341fb7a189', + created: 1584829571092, + createdBy: 'angela', + updated: 1584829571092, + updatedBy: 'angela', + }, + ], + globalNotes: [ + { + noteId: 'd2649d40-6bc5-11ea-86f0-5db0048c6086', + version: 'WzExNjQsMV0=', + note: 'global', + timelineId: 'd123dfe0-6bc5-11ea-86f0-5db0048c6086', + created: 1584830796969, + createdBy: 'angela', + updated: 1584830796969, + updatedBy: 'angela', + }, + ], + pinnedEventIds: ['k-gi8nABm-sIqJ_scOoS'], + }, +]; + +export const mockUniqueParsedObjects = [ + { + savedObjectId: '79deb4c0-6bc1-11ea-a90b-f5341fb7a189', + version: 'WzEyMjUsMV0=', + columns: [], + dataProviders: [], + description: 'description', + eventType: 'all', + filters: [], + kqlMode: 'filter', + kqlQuery: { filterQuery: [] }, + title: 'My duplicate timeline', + dateRange: { start: 1584523907294, end: 1584610307294 }, + savedQueryId: null, + sort: { columnId: '@timestamp', sortDirection: 'desc' }, + created: 1584828930463, + createdBy: 'angela', + updated: 1584868346013, + updatedBy: 'angela', + eventNotes: [ + { + noteId: '73ac2370-6bc2-11ea-a90b-f5341fb7a189', + version: 'WzExMjgsMV0=', + eventId: 'ZaAi8nAB5OldxqFfdhke', + note: 'event note1', + timelineId: 'da49a0e0-6bc1-11ea-a90b-f5341fb7a189', + created: 1584829349563, + createdBy: 'angela', + updated: 1584829349563, + updatedBy: 'angela', + }, + { + noteId: 'f7b71620-6bc2-11ea-a0b6-33c7b2a78885', + version: 'WzExMzUsMV0=', + eventId: 'ZaAi8nAB5OldxqFfdhke', + note: 'event note2', + timelineId: 'da49a0e0-6bc1-11ea-a90b-f5341fb7a189', + created: 1584829571092, + createdBy: 'angela', + updated: 1584829571092, + updatedBy: 'angela', + }, + ], + globalNotes: [ + { + noteId: 'd2649d40-6bc5-11ea-86f0-5db0048c6086', + version: 'WzExNjQsMV0=', + note: 'global', + timelineId: 'd123dfe0-6bc5-11ea-86f0-5db0048c6086', + created: 1584830796969, + createdBy: 'angela', + updated: 1584830796969, + updatedBy: 'angela', + }, + ], + pinnedEventIds: ['k-gi8nABm-sIqJ_scOoS'], + }, +]; + +export const mockGetTimelineValue = { + savedObjectId: '79deb4c0-6bc1-11ea-a90b-f5341fb7a189', + version: 'WzEyMjUsMV0=', + columns: [], + dataProviders: [], + description: 'description', + eventType: 'all', + filters: [], + kqlMode: 'filter', + kqlQuery: { filterQuery: [] }, + title: 'My duplicate timeline', + dateRange: { start: 1584523907294, end: 1584610307294 }, + savedQueryId: null, + sort: { columnId: '@timestamp', sortDirection: 'desc' }, + created: 1584828930463, + createdBy: 'angela', + updated: 1584868346013, + updatedBy: 'angela', + noteIds: [], + pinnedEventIds: ['k-gi8nABm-sIqJ_scOoS'], +}; + +export const mockParsedTimelineObject = omit( + [ + 'globalNotes', + 'eventNotes', + 'pinnedEventIds', + 'version', + 'savedObjectId', + 'created', + 'createdBy', + 'updated', + 'updatedBy', + ], + mockUniqueParsedObjects[0] +); + +export const mockConfig = { + get: () => { + return 100000000; + }, + has: jest.fn(), +}; + +export const mockGetCurrentUser = { + user: { + username: 'mockUser', + }, +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/request_responses.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/request_responses.ts index eae1ece7e789d..0e73e4bdd6c97 100644 --- a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/request_responses.ts +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/__mocks__/request_responses.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TIMELINE_EXPORT_URL } from '../../../../../common/constants'; +import { TIMELINE_EXPORT_URL, TIMELINE_IMPORT_URL } from '../../../../../common/constants'; import { requestMock } from '../../../detection_engine/routes/__mocks__'; export const getExportTimelinesRequest = () => @@ -16,6 +16,26 @@ export const getExportTimelinesRequest = () => }, }); +export const getImportTimelinesRequest = (filename?: string) => + requestMock.create({ + method: 'post', + path: TIMELINE_IMPORT_URL, + query: { overwrite: false }, + body: { + file: { hapi: { filename: filename ?? 'filename.ndjson' } }, + }, + }); + +export const getImportTimelinesRequestEnableOverwrite = (filename?: string) => + requestMock.create({ + method: 'post', + path: TIMELINE_IMPORT_URL, + query: { overwrite: true }, + body: { + file: { hapi: { filename: filename ?? 'filename.ndjson' } }, + }, + }); + export const mockTimelinesSavedObjects = () => ({ saved_objects: [ { diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/export_timelines_route.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/export_timelines_route.ts index 3ded959aced36..b8e7be13fff34 100644 --- a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/export_timelines_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/export_timelines_route.ts @@ -21,7 +21,7 @@ import { exportTimelinesQuerySchema, } from './schemas/export_timelines_schema'; -import { getExportTimelineByObjectIds } from './utils'; +import { getExportTimelineByObjectIds } from './utils/export_timelines'; export const exportTimelinesRoute = (router: IRouter, config: LegacyServices['config']) => { router.post( diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.test.ts new file mode 100644 index 0000000000000..e89aef4c70ecb --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.test.ts @@ -0,0 +1,341 @@ +/* + * 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 { getImportTimelinesRequest } from './__mocks__/request_responses'; +import { + serverMock, + requestContextMock, + requestMock, +} from '../../detection_engine/routes/__mocks__'; +import { TIMELINE_EXPORT_URL } from '../../../../common/constants'; +import { SecurityPluginSetup } from '../../../../../../../plugins/security/server'; + +import { + mockConfig, + mockUniqueParsedObjects, + mockParsedObjects, + mockDuplicateIdErrors, + mockGetCurrentUser, + mockGetTimelineValue, + mockParsedTimelineObject, +} from './__mocks__/import_timelines'; + +describe('import timelines', () => { + let config: jest.Mock; + let server: ReturnType; + let request: ReturnType; + let securitySetup: SecurityPluginSetup; + let { context } = requestContextMock.createTools(); + let mockGetTimeline: jest.Mock; + let mockPersistTimeline: jest.Mock; + let mockPersistPinnedEventOnTimeline: jest.Mock; + let mockPersistNote: jest.Mock; + const newTimelineSavedObjectId = '79deb4c0-6bc1-11ea-9999-f5341fb7a189'; + const newTimelineVersion = '9999'; + beforeEach(() => { + jest.resetModules(); + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + + server = serverMock.create(); + context = requestContextMock.createTools().context; + config = jest.fn().mockImplementation(() => { + return mockConfig; + }); + + securitySetup = ({ + authc: { + getCurrentUser: jest.fn().mockReturnValue(mockGetCurrentUser), + }, + authz: {}, + } as unknown) as SecurityPluginSetup; + + mockGetTimeline = jest.fn(); + mockPersistTimeline = jest.fn(); + mockPersistPinnedEventOnTimeline = jest.fn(); + mockPersistNote = jest.fn(); + + jest.doMock('../create_timelines_stream_from_ndjson', () => { + return { + createTimelinesStreamFromNdJson: jest.fn().mockReturnValue(mockParsedObjects), + }; + }); + + jest.doMock('../../../../../../../../src/legacy/utils', () => { + return { + createPromiseFromStreams: jest.fn().mockReturnValue(mockParsedObjects), + }; + }); + + jest.doMock('./utils/import_timelines', () => { + const originalModule = jest.requireActual('./utils/import_timelines'); + return { + ...originalModule, + getTupleDuplicateErrorsAndUniqueTimeline: jest + .fn() + .mockReturnValue([mockDuplicateIdErrors, mockUniqueParsedObjects]), + }; + }); + }); + + describe('Import a new timeline', () => { + beforeEach(() => { + jest.doMock('../saved_object', () => { + return { + Timeline: jest.fn().mockImplementation(() => { + return { + getTimeline: mockGetTimeline.mockReturnValue(null), + persistTimeline: mockPersistTimeline.mockReturnValue({ + timeline: { savedObjectId: newTimelineSavedObjectId, version: newTimelineVersion }, + }), + }; + }), + }; + }); + + jest.doMock('../../pinned_event/saved_object', () => { + return { + PinnedEvent: jest.fn().mockImplementation(() => { + return { + persistPinnedEventOnTimeline: mockPersistPinnedEventOnTimeline, + }; + }), + }; + }); + + jest.doMock('../../note/saved_object', () => { + return { + Note: jest.fn().mockImplementation(() => { + return { + persistNote: mockPersistNote, + }; + }), + }; + }); + + const importTimelinesRoute = jest.requireActual('./import_timelines_route') + .importTimelinesRoute; + importTimelinesRoute(server.router, config, securitySetup); + }); + + test('should use given timelineId to check if the timeline savedObject already exist', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockGetTimeline.mock.calls[0][1]).toEqual(mockUniqueParsedObjects[0].savedObjectId); + }); + + test('should Create a new timeline savedObject', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistTimeline).toHaveBeenCalled(); + }); + + test('should Create a new timeline savedObject without timelineId', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistTimeline.mock.calls[0][1]).toBeNull(); + }); + + test('should Create a new timeline savedObject without timeline version', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistTimeline.mock.calls[0][2]).toBeNull(); + }); + + test('should Create a new timeline savedObject witn given timeline', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistTimeline.mock.calls[0][3]).toEqual(mockParsedTimelineObject); + }); + + test('should Create new pinned events', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistPinnedEventOnTimeline).toHaveBeenCalled(); + }); + + test('should Create a new pinned event without pinnedEventSavedObjectId', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistPinnedEventOnTimeline.mock.calls[0][1]).toBeNull(); + }); + + test('should Create a new pinned event with pinnedEventId', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistPinnedEventOnTimeline.mock.calls[0][2]).toEqual( + mockUniqueParsedObjects[0].pinnedEventIds[0] + ); + }); + + test('should Create a new pinned event with new timelineSavedObjectId', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistPinnedEventOnTimeline.mock.calls[0][3]).toEqual(newTimelineSavedObjectId); + }); + + test('should Create notes', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistNote).toHaveBeenCalled(); + }); + + test('should provide no noteSavedObjectId when Creating notes for a timeline', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistNote.mock.calls[0][1]).toBeNull(); + }); + + test('should provide new timeline version when Creating notes for a timeline', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistNote.mock.calls[0][1]).toBeNull(); + }); + + test('should provide note content when Creating notes for a timeline', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistNote.mock.calls[0][2]).toEqual(newTimelineVersion); + }); + + test('should provide new notes when Creating notes for a timeline', async () => { + const mockRequest = getImportTimelinesRequest(); + await server.inject(mockRequest, context); + expect(mockPersistNote.mock.calls[0][3]).toEqual({ + eventId: undefined, + note: mockUniqueParsedObjects[0].globalNotes[0].note, + timelineId: newTimelineSavedObjectId, + }); + expect(mockPersistNote.mock.calls[1][3]).toEqual({ + eventId: mockUniqueParsedObjects[0].eventNotes[0].eventId, + note: mockUniqueParsedObjects[0].eventNotes[0].note, + timelineId: newTimelineSavedObjectId, + }); + expect(mockPersistNote.mock.calls[2][3]).toEqual({ + eventId: mockUniqueParsedObjects[0].eventNotes[1].eventId, + note: mockUniqueParsedObjects[0].eventNotes[1].note, + timelineId: newTimelineSavedObjectId, + }); + }); + + test('returns 200 when import timeline successfully', async () => { + const response = await server.inject(getImportTimelinesRequest(), context); + expect(response.status).toEqual(200); + }); + }); + + describe('Import a timeline already exist but overwrite is not allowed', () => { + beforeEach(() => { + jest.doMock('../saved_object', () => { + return { + Timeline: jest.fn().mockImplementation(() => { + return { + getTimeline: mockGetTimeline.mockReturnValue(mockGetTimelineValue), + persistTimeline: mockPersistTimeline, + }; + }), + }; + }); + + jest.doMock('../../pinned_event/saved_object', () => { + return { + PinnedEvent: jest.fn().mockImplementation(() => { + return { + persistPinnedEventOnTimeline: mockPersistPinnedEventOnTimeline, + }; + }), + }; + }); + + jest.doMock('../../note/saved_object', () => { + return { + Note: jest.fn().mockImplementation(() => { + return { + persistNote: mockPersistNote, + }; + }), + }; + }); + + const importTimelinesRoute = jest.requireActual('./import_timelines_route') + .importTimelinesRoute; + importTimelinesRoute(server.router, config, securitySetup); + }); + + test('returns error message', async () => { + const response = await server.inject(getImportTimelinesRequest(), context); + expect(response.body).toEqual({ + success: false, + success_count: 0, + errors: [ + { + id: '79deb4c0-6bc1-11ea-a90b-f5341fb7a189', + error: { + status_code: 409, + message: `timeline_id: "79deb4c0-6bc1-11ea-a90b-f5341fb7a189" already exists`, + }, + }, + ], + }); + }); + }); + + describe('request validation', () => { + beforeEach(() => { + jest.doMock('../saved_object', () => { + return { + Timeline: jest.fn().mockImplementation(() => { + return { + getTimeline: mockGetTimeline.mockReturnValue(null), + persistTimeline: mockPersistTimeline.mockReturnValue({ + timeline: { savedObjectId: '79deb4c0-6bc1-11ea-9999-f5341fb7a189' }, + }), + }; + }), + }; + }); + + jest.doMock('../../pinned_event/saved_object', () => { + return { + PinnedEvent: jest.fn().mockImplementation(() => { + return { + persistPinnedEventOnTimeline: mockPersistPinnedEventOnTimeline.mockReturnValue( + new Error('Test error') + ), + }; + }), + }; + }); + + jest.doMock('../../note/saved_object', () => { + return { + Note: jest.fn().mockImplementation(() => { + return { + persistNote: mockPersistNote, + }; + }), + }; + }); + }); + test('disallows invalid query', async () => { + request = requestMock.create({ + method: 'post', + path: TIMELINE_EXPORT_URL, + body: { id: 'someId' }, + }); + const importTimelinesRoute = jest.requireActual('./import_timelines_route') + .importTimelinesRoute; + + importTimelinesRoute(server.router, config, securitySetup); + const result = server.validate(request); + + expect(result.badRequest).toHaveBeenCalledWith( + 'child "file" fails because ["file" is required]' + ); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts new file mode 100644 index 0000000000000..2b41b4e7843a7 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts @@ -0,0 +1,226 @@ +/* + * 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 { extname } from 'path'; +import { chunk, omit, set } from 'lodash/fp'; +import { + buildRouteValidation, + buildSiemResponse, + createBulkErrorObject, + BulkError, + transformError, +} from '../../detection_engine/routes/utils'; + +import { createTimelinesStreamFromNdJson } from '../create_timelines_stream_from_ndjson'; +import { createPromiseFromStreams } from '../../../../../../../../src/legacy/utils'; + +import { + createTimelines, + getTupleDuplicateErrorsAndUniqueTimeline, + isBulkError, + isImportRegular, + ImportTimelineResponse, + ImportTimelinesRequestParams, + ImportTimelinesSchema, + PromiseFromStreams, +} from './utils/import_timelines'; + +import { IRouter } from '../../../../../../../../src/core/server'; +import { TIMELINE_IMPORT_URL } from '../../../../common/constants'; +import { SetupPlugins } from '../../../plugin'; +import { importTimelinesPayloadSchema } from './schemas/import_timelines_schema'; +import { importRulesSchema } from '../../detection_engine/routes/schemas/response/import_rules_schema'; +import { LegacyServices } from '../../../types'; + +import { Timeline } from '../saved_object'; +import { validate } from '../../detection_engine/routes/rules/validate'; +import { FrameworkRequest } from '../../framework'; + +const CHUNK_PARSED_OBJECT_SIZE = 10; + +const timelineLib = new Timeline(); + +export const importTimelinesRoute = ( + router: IRouter, + config: LegacyServices['config'], + security: SetupPlugins['security'] +) => { + router.post( + { + path: `${TIMELINE_IMPORT_URL}`, + validate: { + body: buildRouteValidation( + importTimelinesPayloadSchema + ), + }, + options: { + tags: ['access:siem'], + body: { + maxBytes: config().get('savedObjects.maxImportPayloadBytes'), + output: 'stream', + }, + }, + }, + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + const savedObjectsClient = context.core.savedObjects.client; + if (!savedObjectsClient) { + return siemResponse.error({ statusCode: 404 }); + } + const { filename } = request.body.file.hapi; + + const fileExtension = extname(filename).toLowerCase(); + + if (fileExtension !== '.ndjson') { + return siemResponse.error({ + statusCode: 400, + body: `Invalid file extension ${fileExtension}`, + }); + } + + const objectLimit = config().get('savedObjects.maxImportExportSize'); + + try { + const readStream = createTimelinesStreamFromNdJson(objectLimit); + const parsedObjects = await createPromiseFromStreams([ + request.body.file, + ...readStream, + ]); + const [duplicateIdErrors, uniqueParsedObjects] = getTupleDuplicateErrorsAndUniqueTimeline( + parsedObjects, + false + ); + const chunkParseObjects = chunk(CHUNK_PARSED_OBJECT_SIZE, uniqueParsedObjects); + let importTimelineResponse: ImportTimelineResponse[] = []; + + const user = await security?.authc.getCurrentUser(request); + let frameworkRequest = set('context.core.savedObjects.client', savedObjectsClient, request); + frameworkRequest = set('user', user, frameworkRequest); + + while (chunkParseObjects.length) { + const batchParseObjects = chunkParseObjects.shift() ?? []; + const newImportTimelineResponse = await Promise.all( + batchParseObjects.reduce>>( + (accum, parsedTimeline) => { + const importsWorkerPromise = new Promise( + async (resolve, reject) => { + if (parsedTimeline instanceof Error) { + // If the JSON object had a validation or parse error then we return + // early with the error and an (unknown) for the ruleId + resolve( + createBulkErrorObject({ + statusCode: 400, + message: parsedTimeline.message, + }) + ); + + return null; + } + const { + savedObjectId, + pinnedEventIds, + globalNotes, + eventNotes, + } = parsedTimeline; + const parsedTimelineObject = omit( + [ + 'globalNotes', + 'eventNotes', + 'pinnedEventIds', + 'version', + 'savedObjectId', + 'created', + 'createdBy', + 'updated', + 'updatedBy', + ], + parsedTimeline + ); + try { + let timeline = null; + try { + timeline = await timelineLib.getTimeline( + (frameworkRequest as unknown) as FrameworkRequest, + savedObjectId + ); + // eslint-disable-next-line no-empty + } catch (e) {} + + if (timeline == null) { + const newSavedObjectId = await createTimelines( + (frameworkRequest as unknown) as FrameworkRequest, + parsedTimelineObject, + null, // timelineSavedObjectId + null, // timelineVersion + pinnedEventIds, + [...globalNotes, ...eventNotes], + [] // existing note ids + ); + + resolve({ timeline_id: newSavedObjectId, status_code: 200 }); + } else { + resolve( + createBulkErrorObject({ + id: savedObjectId, + statusCode: 409, + message: `timeline_id: "${savedObjectId}" already exists`, + }) + ); + } + } catch (err) { + resolve( + createBulkErrorObject({ + id: savedObjectId, + statusCode: 400, + message: err.message, + }) + ); + } + } + ); + return [...accum, importsWorkerPromise]; + }, + [] + ) + ); + importTimelineResponse = [ + ...duplicateIdErrors, + ...importTimelineResponse, + ...newImportTimelineResponse, + ]; + } + + const errorsResp = importTimelineResponse.filter(resp => isBulkError(resp)) as BulkError[]; + const successes = importTimelineResponse.filter(resp => { + if (isImportRegular(resp)) { + return resp.status_code === 200; + } else { + return false; + } + }); + const importTimelines: ImportTimelinesSchema = { + success: errorsResp.length === 0, + success_count: successes.length, + errors: errorsResp, + }; + const [validated, errors] = validate(importTimelines, importRulesSchema); + + if (errors != null) { + return siemResponse.error({ statusCode: 500, body: errors }); + } else { + return response.ok({ body: validated ?? {} }); + } + } catch (err) { + const error = transformError(err); + + return siemResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/import_timelines_schema.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/import_timelines_schema.ts new file mode 100644 index 0000000000000..61ffa9681c53a --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/import_timelines_schema.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import Joi from 'joi'; +import { + columns, + created, + createdBy, + dataProviders, + dateRange, + description, + eventNotes, + eventType, + favorite, + filters, + globalNotes, + kqlMode, + kqlQuery, + savedObjectId, + savedQueryId, + sort, + title, + updated, + updatedBy, + version, + pinnedEventIds, +} from './schemas'; + +export const importTimelinesPayloadSchema = Joi.object({ + file: Joi.object().required(), +}); + +export const importTimelinesSchema = Joi.object({ + columns, + created, + createdBy, + dataProviders, + dateRange, + description, + eventNotes, + eventType, + filters, + favorite, + globalNotes, + kqlMode, + kqlQuery, + savedObjectId, + savedQueryId, + sort, + title, + updated, + updatedBy, + version, + pinnedEventIds, +}); diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/schemas.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/schemas.ts index 67697c347634e..6552f973a66fa 100644 --- a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/schemas.ts +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/schemas/schemas.ts @@ -5,9 +5,154 @@ */ import Joi from 'joi'; +const allowEmptyString = Joi.string().allow([null, '']); +const columnHeaderType = allowEmptyString; +export const created = Joi.number().allow(null); +export const createdBy = allowEmptyString; + +export const description = allowEmptyString; +export const end = Joi.number(); +export const eventId = allowEmptyString; +export const eventType = allowEmptyString; + +export const filters = Joi.array() + .items( + Joi.object({ + meta: Joi.object({ + alias: allowEmptyString, + controlledBy: allowEmptyString, + disabled: Joi.boolean().allow(null), + field: allowEmptyString, + formattedValue: allowEmptyString, + index: allowEmptyString, + key: allowEmptyString, + negate: Joi.boolean().allow(null), + params: allowEmptyString, + type: allowEmptyString, + value: allowEmptyString, + }), + exists: allowEmptyString, + match_all: allowEmptyString, + missing: allowEmptyString, + query: allowEmptyString, + range: allowEmptyString, + script: allowEmptyString, + }) + ) + .allow(null); + +const name = allowEmptyString; + +export const noteId = allowEmptyString; +export const note = allowEmptyString; + +export const start = Joi.number(); +export const savedQueryId = allowEmptyString; +export const savedObjectId = allowEmptyString; + +export const timelineId = allowEmptyString; +export const title = allowEmptyString; + +export const updated = Joi.number().allow(null); +export const updatedBy = allowEmptyString; +export const version = allowEmptyString; + +export const columns = Joi.array().items( + Joi.object({ + aggregatable: Joi.boolean().allow(null), + category: allowEmptyString, + columnHeaderType, + description, + example: allowEmptyString, + indexes: allowEmptyString, + id: allowEmptyString, + name, + placeholder: allowEmptyString, + searchable: Joi.boolean().allow(null), + type: allowEmptyString, + }).required() +); +export const dataProviders = Joi.array() + .items( + Joi.object({ + id: allowEmptyString, + name: allowEmptyString, + enabled: Joi.boolean().allow(null), + excluded: Joi.boolean().allow(null), + kqlQuery: allowEmptyString, + queryMatch: Joi.object({ + field: allowEmptyString, + displayField: allowEmptyString, + value: allowEmptyString, + displayValue: allowEmptyString, + operator: allowEmptyString, + }), + and: Joi.array() + .items( + Joi.object({ + id: allowEmptyString, + name, + enabled: Joi.boolean().allow(null), + excluded: Joi.boolean().allow(null), + kqlQuery: allowEmptyString, + queryMatch: Joi.object({ + field: allowEmptyString, + displayField: allowEmptyString, + value: allowEmptyString, + displayValue: allowEmptyString, + operator: allowEmptyString, + }).allow(null), + }) + ) + .allow(null), + }) + ) + .allow(null); +export const dateRange = Joi.object({ + start, + end, +}); +export const favorite = Joi.array().items( + Joi.object({ + keySearch: allowEmptyString, + fullName: allowEmptyString, + userName: allowEmptyString, + favoriteDate: Joi.number(), + }).allow(null) +); +const noteItem = Joi.object({ + noteId, + version, + eventId, + note, + timelineId, + created, + createdBy, + updated, + updatedBy, +}); +export const eventNotes = Joi.array().items(noteItem); +export const globalNotes = Joi.array().items(noteItem); +export const kqlMode = allowEmptyString; +export const kqlQuery = Joi.object({ + filterQuery: Joi.object({ + kuery: Joi.object({ + kind: allowEmptyString, + expression: allowEmptyString, + }), + serializedQuery: allowEmptyString, + }), +}); +export const pinnedEventIds = Joi.array() + .items(allowEmptyString) + .allow(null); +export const sort = Joi.object({ + columnId: allowEmptyString, + sortDirection: allowEmptyString, +}); /* eslint-disable @typescript-eslint/camelcase */ -export const ids = Joi.array().items(Joi.string()); +export const ids = Joi.array().items(allowEmptyString); export const exclude_export_details = Joi.boolean(); -export const file_name = Joi.string(); +export const file_name = allowEmptyString; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/export_timelines.ts similarity index 85% rename from x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils.ts rename to x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/export_timelines.ts index 066862e025833..8a28100fbae82 100644 --- a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/export_timelines.ts @@ -3,37 +3,53 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { set as _set } from 'lodash/fp'; import { + noteSavedObjectType, + pinnedEventSavedObjectType, + timelineSavedObjectType, +} from '../../../../saved_objects'; +import { NoteSavedObject } from '../../../note/types'; +import { PinnedEventSavedObject } from '../../../pinned_event/types'; +import { convertSavedObjectToSavedTimeline } from '../../convert_saved_object_to_savedtimeline'; + +import { convertSavedObjectToSavedPinnedEvent } from '../../../pinned_event/saved_object'; +import { convertSavedObjectToSavedNote } from '../../../note/saved_object'; + +import { + SavedObjectsClient, SavedObjectsFindOptions, SavedObjectsFindResponse, -} from '../../../../../../../../src/core/server'; +} from '../../../../../../../../../src/core/server'; import { + ExportedTimelines, ExportTimelineSavedObjectsClient, ExportTimelineRequest, ExportedNotes, TimelineSavedObject, - ExportedTimelines, -} from '../types'; -import { - timelineSavedObjectType, - noteSavedObjectType, - pinnedEventSavedObjectType, -} from '../../../saved_objects'; - -import { convertSavedObjectToSavedNote } from '../../note/saved_object'; -import { convertSavedObjectToSavedPinnedEvent } from '../../pinned_event/saved_object'; -import { convertSavedObjectToSavedTimeline } from '../convert_saved_object_to_savedtimeline'; -import { transformDataToNdjson } from '../../detection_engine/routes/rules/utils'; -import { NoteSavedObject } from '../../note/types'; -import { PinnedEventSavedObject } from '../../pinned_event/types'; +} from '../../types'; + +import { transformDataToNdjson } from '../../../detection_engine/routes/rules/utils'; +export type TimelineSavedObjectsClient = Pick< + SavedObjectsClient, + | 'get' + | 'errors' + | 'create' + | 'bulkCreate' + | 'delete' + | 'find' + | 'bulkGet' + | 'update' + | 'bulkUpdate' +>; const getAllSavedPinnedEvents = ( pinnedEventsSavedObjects: SavedObjectsFindResponse ): PinnedEventSavedObject[] => { return pinnedEventsSavedObjects != null - ? pinnedEventsSavedObjects.saved_objects.map(savedObject => + ? (pinnedEventsSavedObjects?.saved_objects ?? []).map(savedObject => convertSavedObjectToSavedPinnedEvent(savedObject) ) : []; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts new file mode 100644 index 0000000000000..5596d0c70f5ea --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts @@ -0,0 +1,191 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import uuid from 'uuid'; +import { has } from 'lodash/fp'; +import { createBulkErrorObject, BulkError } from '../../../detection_engine/routes/utils'; +import { PinnedEvent } from '../../../pinned_event/saved_object'; +import { Note } from '../../../note/saved_object'; + +import { Timeline } from '../../saved_object'; +import { SavedTimeline } from '../../types'; +import { FrameworkRequest } from '../../../framework'; +import { SavedNote } from '../../../note/types'; +import { NoteResult } from '../../../../graphql/types'; +import { HapiReadableStream } from '../../../detection_engine/rules/types'; + +const pinnedEventLib = new PinnedEvent(); +const timelineLib = new Timeline(); +const noteLib = new Note(); + +export interface ImportTimelinesSchema { + success: boolean; + success_count: number; + errors: BulkError[]; +} + +export type ImportedTimeline = SavedTimeline & { + savedObjectId: string; + pinnedEventIds: string[]; + globalNotes: NoteResult[]; + eventNotes: NoteResult[]; +}; + +interface ImportRegular { + timeline_id: string; + status_code: number; + message?: string; +} + +export type ImportTimelineResponse = ImportRegular | BulkError; +export type PromiseFromStreams = ImportedTimeline; +export interface ImportTimelinesRequestParams { + body: { file: HapiReadableStream }; +} + +export const getTupleDuplicateErrorsAndUniqueTimeline = ( + timelines: PromiseFromStreams[], + isOverwrite: boolean +): [BulkError[], PromiseFromStreams[]] => { + const { errors, timelinesAcc } = timelines.reduce( + (acc, parsedTimeline) => { + if (parsedTimeline instanceof Error) { + acc.timelinesAcc.set(uuid.v4(), parsedTimeline); + } else { + const { savedObjectId } = parsedTimeline; + if (savedObjectId != null) { + if (acc.timelinesAcc.has(savedObjectId) && !isOverwrite) { + acc.errors.set( + uuid.v4(), + createBulkErrorObject({ + id: savedObjectId, + statusCode: 400, + message: `More than one timeline with savedObjectId: "${savedObjectId}" found`, + }) + ); + } + acc.timelinesAcc.set(savedObjectId, parsedTimeline); + } else { + acc.timelinesAcc.set(uuid.v4(), parsedTimeline); + } + } + + return acc; + }, // using map (preserves ordering) + { + errors: new Map(), + timelinesAcc: new Map(), + } + ); + + return [Array.from(errors.values()), Array.from(timelinesAcc.values())]; +}; + +export const saveTimelines = async ( + frameworkRequest: FrameworkRequest, + timeline: SavedTimeline, + timelineSavedObjectId?: string | null, + timelineVersion?: string | null +) => { + const newTimelineRes = await timelineLib.persistTimeline( + frameworkRequest, + timelineSavedObjectId ?? null, + timelineVersion ?? null, + timeline + ); + + return { + newTimelineSavedObjectId: newTimelineRes?.timeline?.savedObjectId ?? null, + newTimelineVersion: newTimelineRes?.timeline?.version ?? null, + }; +}; + +export const savePinnedEvents = ( + frameworkRequest: FrameworkRequest, + timelineSavedObjectId: string, + pinnedEventIds?: string[] | null +) => { + return ( + pinnedEventIds?.map(eventId => { + return pinnedEventLib.persistPinnedEventOnTimeline( + frameworkRequest, + null, // pinnedEventSavedObjectId + eventId, + timelineSavedObjectId + ); + }) ?? [] + ); +}; + +export const saveNotes = ( + frameworkRequest: FrameworkRequest, + timelineSavedObjectId: string, + timelineVersion?: string | null, + existingNoteIds?: string[], + newNotes?: NoteResult[] +) => { + return ( + newNotes?.map(note => { + const newNote: SavedNote = { + eventId: note.eventId, + note: note.note, + timelineId: timelineSavedObjectId, + }; + + return noteLib.persistNote( + frameworkRequest, + existingNoteIds?.find(nId => nId === note.noteId) ?? null, + timelineVersion ?? null, + newNote + ); + }) ?? [] + ); +}; + +export const createTimelines = async ( + frameworkRequest: FrameworkRequest, + timeline: SavedTimeline, + timelineSavedObjectId?: string | null, + timelineVersion?: string | null, + pinnedEventIds?: string[] | null, + notes?: NoteResult[], + existingNoteIds?: string[] +) => { + const { newTimelineSavedObjectId, newTimelineVersion } = await saveTimelines( + frameworkRequest, + timeline, + timelineSavedObjectId, + timelineVersion + ); + await Promise.all([ + savePinnedEvents( + frameworkRequest, + timelineSavedObjectId ?? newTimelineSavedObjectId, + pinnedEventIds + ), + saveNotes( + frameworkRequest, + timelineSavedObjectId ?? newTimelineSavedObjectId, + newTimelineVersion, + existingNoteIds, + notes + ), + ]); + + return newTimelineSavedObjectId; +}; + +export const isImportRegular = ( + importTimelineResponse: ImportTimelineResponse +): importTimelineResponse is ImportRegular => { + return !has('error', importTimelineResponse) && has('status_code', importTimelineResponse); +}; + +export const isBulkError = ( + importRuleResponse: ImportTimelineResponse +): importRuleResponse is BulkError => { + return has('error', importRuleResponse); +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/timeline/saved_object.ts b/x-pack/legacy/plugins/siem/server/lib/timeline/saved_object.ts index 88d7fcdb68164..bc6975331ad9b 100644 --- a/x-pack/legacy/plugins/siem/server/lib/timeline/saved_object.ts +++ b/x-pack/legacy/plugins/siem/server/lib/timeline/saved_object.ts @@ -138,19 +138,19 @@ export class Timeline { timeline: SavedTimeline ): Promise { const savedObjectsClient = request.context.core.savedObjects.client; - try { if (timelineId == null) { // Create new timeline + const newTimeline = convertSavedObjectToSavedTimeline( + await savedObjectsClient.create( + timelineSavedObjectType, + pickSavedTimeline(timelineId, timeline, request.user) + ) + ); return { code: 200, message: 'success', - timeline: convertSavedObjectToSavedTimeline( - await savedObjectsClient.create( - timelineSavedObjectType, - pickSavedTimeline(timelineId, timeline, request.user) - ) - ), + timeline: newTimeline, }; } // Update Timeline @@ -162,6 +162,7 @@ export class Timeline { version: version || undefined, } ); + return { code: 200, message: 'success', diff --git a/x-pack/legacy/plugins/siem/server/plugin.ts b/x-pack/legacy/plugins/siem/server/plugin.ts index d785de32eab7e..98631ea220a54 100644 --- a/x-pack/legacy/plugins/siem/server/plugin.ts +++ b/x-pack/legacy/plugins/siem/server/plugin.ts @@ -21,6 +21,7 @@ import { PluginSetupContract as FeaturesSetup } from '../../../../plugins/featur import { EncryptedSavedObjectsPluginSetup as EncryptedSavedObjectsSetup } from '../../../../plugins/encrypted_saved_objects/server'; import { SpacesPluginSetup as SpacesSetup } from '../../../../plugins/spaces/server'; import { PluginStartContract as ActionsStart } from '../../../../plugins/actions/server'; +import { LicensingPluginSetup } from '../../../../plugins/licensing/server'; import { LegacyServices } from './types'; import { initServer } from './init_server'; import { compose } from './lib/compose/kibana'; @@ -41,11 +42,12 @@ import { hasListsFeature, listsEnvFeatureFlagName } from './lib/detection_engine export { CoreSetup, CoreStart }; export interface SetupPlugins { + alerting: AlertingSetup; encryptedSavedObjects: EncryptedSavedObjectsSetup; features: FeaturesSetup; - security: SecuritySetup; + licensing: LicensingPluginSetup; + security?: SecuritySetup; spaces?: SpacesSetup; - alerting: AlertingSetup; } export interface StartPlugins { @@ -89,7 +91,8 @@ export class Plugin { initRoutes( router, __legacy.config, - plugins.encryptedSavedObjects?.usingEphemeralEncryptionKey ?? false + plugins.encryptedSavedObjects?.usingEphemeralEncryptionKey ?? false, + plugins.security ); plugins.features.registerFeature({ diff --git a/x-pack/legacy/plugins/siem/server/routes/index.ts b/x-pack/legacy/plugins/siem/server/routes/index.ts index 08ff9208ce20b..8c9f92890c26a 100644 --- a/x-pack/legacy/plugins/siem/server/routes/index.ts +++ b/x-pack/legacy/plugins/siem/server/routes/index.ts @@ -29,12 +29,15 @@ import { importRulesRoute } from '../lib/detection_engine/routes/rules/import_ru import { exportRulesRoute } from '../lib/detection_engine/routes/rules/export_rules_route'; import { findRulesStatusesRoute } from '../lib/detection_engine/routes/rules/find_rules_status_route'; import { getPrepackagedRulesStatusRoute } from '../lib/detection_engine/routes/rules/get_prepackaged_rules_status_route'; +import { importTimelinesRoute } from '../lib/timeline/routes/import_timelines_route'; import { exportTimelinesRoute } from '../lib/timeline/routes/export_timelines_route'; +import { SetupPlugins } from '../plugin'; export const initRoutes = ( router: IRouter, config: LegacyServices['config'], - usingEphemeralEncryptionKey: boolean + usingEphemeralEncryptionKey: boolean, + security: SetupPlugins['security'] ) => { // Detection Engine Rule routes that have the REST endpoints of /api/detection_engine/rules // All REST rule creation, deletion, updating, etc...... @@ -55,6 +58,7 @@ export const initRoutes = ( importRulesRoute(router, config); exportRulesRoute(router, config); + importTimelinesRoute(router, config, security); exportTimelinesRoute(router, config); findRulesStatusesRoute(router); @@ -75,5 +79,5 @@ export const initRoutes = ( readTagsRoute(router); // Privileges API to get the generic user privileges - readPrivilegesRoute(router, usingEphemeralEncryptionKey); + readPrivilegesRoute(router, security, usingEphemeralEncryptionKey); }; diff --git a/x-pack/legacy/plugins/spaces/public/legacy.ts b/x-pack/legacy/plugins/spaces/public/legacy.ts index c6740dae81717..277d6a10547b2 100644 --- a/x-pack/legacy/plugins/spaces/public/legacy.ts +++ b/x-pack/legacy/plugins/spaces/public/legacy.ts @@ -4,22 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObjectsManagementAction } from 'src/legacy/core_plugins/management/public'; import { npSetup } from 'ui/new_platform'; import routes from 'ui/routes'; import { SpacesPluginSetup } from '../../../../plugins/spaces/public'; -import { setup as managementSetup } from '../../../../../src/legacy/core_plugins/management/public/legacy'; - -const legacyAPI = { - registerSavedObjectsManagementAction: (action: SavedObjectsManagementAction) => { - managementSetup.savedObjects.registry.register(action); - }, -}; const spaces = (npSetup.plugins as any).spaces as SpacesPluginSetup; if (spaces) { - spaces.registerLegacyAPI(legacyAPI); - routes.when('/management/spaces/list', { redirectTo: '/management/kibana/spaces' }); routes.when('/management/spaces/create', { redirectTo: '/management/kibana/spaces/create' }); routes.when('/management/spaces/edit/:spaceId', { diff --git a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts index a1a3e86e6a97e..7fafe6584d831 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/rest_api.ts @@ -16,6 +16,7 @@ export enum API_URLS { PING_HISTOGRAM = `/api/uptime/ping/histogram`, SNAPSHOT_COUNT = `/api/uptime/snapshot/count`, FILTERS = `/api/uptime/filters`, + logPageView = `/api/uptime/logPageView`, ML_MODULE_JOBS = `/api/ml/modules/jobs_exist/`, ML_SETUP_MODULE = '/api/ml/modules/setup/', diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index bd017e6cfaf4c..c8beb91d807d5 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -8,7 +8,6 @@ // Scalars // ==================================================== - export type UnsignedInteger = any; // ==================================================== @@ -367,7 +366,6 @@ export interface DocCount { count: UnsignedInteger; } - export interface Snapshot { counts: SnapshotCount; } @@ -380,7 +378,6 @@ export interface SnapshotCount { total: number; } - /** The primary object returned for monitor states. */ export interface MonitorSummaryResult { /** Used to go to the next page of results */ @@ -524,7 +521,6 @@ export interface SummaryHistogramPoint { down: number; } - export interface AllPingsQueryArgs { /** Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'. */ sort?: string | null; @@ -540,6 +536,7 @@ export interface AllPingsQueryArgs { dateRangeEnd: string; /** Optional: agent location to filter by. */ location?: string | null; + page?: number; } export interface GetMonitorStatesQueryArgs { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx index 99853a9f775ec..8093dd30604e4 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx @@ -48,7 +48,7 @@ export const ToggleAlertFlyoutButtonComponent = ({ setAlertFlyoutVisible }: Prop })} data-test-subj="xpack.uptime.toggleAlertFlyout" key="create-alert" - icon="alert" + icon="bell" onClick={() => setAlertFlyoutVisible(true)} > { notifications, triggers_actions_ui: { actionTypeRegistry, alertTypeRegistry }, uiSettings, + docLinks, }, } = useKibana(); @@ -26,6 +27,7 @@ export const UptimeAlertsContextProvider: React.FC = ({ children }) => { actionTypeRegistry, alertTypeRegistry, charts, + docLinks, dataFieldsFormats: fieldFormats, http, toastNotifications: notifications?.toasts, diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx index 11f6565734782..cfed52f4e5d27 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx @@ -8,13 +8,13 @@ import React, { useEffect, useState, useContext, useRef } from 'react'; import uuid from 'uuid'; import styled from 'styled-components'; +import { ViewMode } from '../../../../../../../../../src/plugins/embeddable/public'; import { start } from '../../../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; import * as i18n from './translations'; -// @ts-ignore -import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../maps/common/constants'; +import { MapEmbeddable, MapEmbeddableInput } from '../../../../../../maps/public'; +import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../../../plugins/maps/public'; import { Location } from '../../../../../common/runtime_types'; -import { MapEmbeddable } from './types'; import { getLayerList } from './map_config'; import { UptimeThemeContext } from '../../../../contexts'; @@ -49,7 +49,7 @@ export const EmbeddedMap = React.memo(({ upPoints, downPoints }: EmbeddedMapProp const embeddableRoot: React.RefObject = useRef(null); const factory = start.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE); - const input = { + const input: MapEmbeddableInput = { id: uuid.v4(), filters: [], hidePanelTitles: true, @@ -57,7 +57,7 @@ export const EmbeddedMap = React.memo(({ upPoints, downPoints }: EmbeddedMapProp value: 0, pause: false, }, - viewMode: 'view', + viewMode: ViewMode.VIEW, isLayerTOCOpen: false, hideFilterActions: true, // Zoom Lat/Lon values are set to make sure map is in center in the panel diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts b/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts deleted file mode 100644 index 03cb33c3459d2..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Query } from 'src/plugins/data/common'; -import { TimeRange } from 'src/plugins/data/public'; -import { - EmbeddableInput, - EmbeddableOutput, - IEmbeddable, -} from '../../../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; - -import { Filter } from '../../../../../../../../../src/plugins/data/public'; - -export interface MapEmbeddableInput extends EmbeddableInput { - filters: Filter[]; - query: Query; - refreshConfig: { - isPaused: boolean; - interval: number; - }; - timeRange?: TimeRange; -} - -export interface CustomProps { - setLayerList: Function; -} - -export type MapEmbeddable = IEmbeddable & CustomProps; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap index d19de73c16c5f..2e59ec5e57337 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap @@ -364,17 +364,16 @@ exports[`PingList component renders sorted list without errors 1`] = ` onChange={[Function]} pagination={ Object { - "initialPageSize": 20, + "initialPageSize": 25, "pageIndex": 0, - "pageSize": 30, + "pageSize": 10, "pageSizeOptions": Array [ - 5, 10, - 20, + 25, 50, 100, ], - "totalItemCount": 30, + "totalItemCount": 9231, } } responsive={true} diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx index 36586b182de43..68d285bd0baf1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx @@ -204,9 +204,11 @@ describe('PingList component', () => { loading={false} data={{ allPings }} onPageCountChange={jest.fn()} + onPageIndexChange={jest.fn()} onSelectedLocationChange={(_loc: any[]) => {}} onSelectedStatusChange={jest.fn()} - pageSize={30} + pageIndex={0} + pageSize={10} selectedOption="down" selectedLocation={AllLocationOption.value} /> diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx index d245bc1456e6a..19768c7104e91 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx @@ -41,7 +41,9 @@ interface PingListProps { onSelectedStatusChange: (status: string | undefined) => void; onSelectedLocationChange: (location: any) => void; onPageCountChange: (itemCount: number) => void; + onPageIndexChange: (index: number) => void; pageSize: number; + pageIndex: number; selectedOption: string; selectedLocation: string | undefined; } @@ -78,8 +80,10 @@ export const PingListComponent = ({ data, loading, onPageCountChange, + onPageIndexChange, onSelectedLocationChange, onSelectedStatusChange, + pageIndex, pageSize, selectedOption, selectedLocation, @@ -232,15 +236,11 @@ export const PingListComponent = ({ ]; const pagination: Pagination = { - initialPageSize: 20, - pageIndex: 0, + initialPageSize: 25, + pageIndex, pageSize, - pageSizeOptions: [5, 10, 20, 50, 100], - /** - * we're not currently supporting pagination in this component - * so the first page is the only page - */ - totalItemCount: pageSize, + pageSizeOptions: [10, 25, 50, 100], + totalItemCount: data?.allPings?.total ?? pageSize, }; return ( @@ -323,9 +323,10 @@ export const PingListComponent = ({ itemId="id" itemIdToExpandedRowMap={itemIdToExpandedRowMap} pagination={pagination} - onChange={(criteria: CriteriaWithPagination) => - onPageCountChange(criteria.page!.size) - } + onChange={(criteria: CriteriaWithPagination) => { + onPageCountChange(criteria.page!.size); + onPageIndexChange(criteria.page!.index); + }} /> diff --git a/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts b/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts index 7eb18404decfd..fc0e0ce1c3e88 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts +++ b/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts @@ -5,33 +5,31 @@ */ import { useEffect } from 'react'; -import { HttpHandler } from 'kibana/public'; -import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { useUrlParams } from './use_url_params'; +import { apiService } from '../state/api/utils'; +import { API_URLS } from '../../common/constants'; export enum UptimePage { - Overview = '/api/uptime/logOverview', - Monitor = '/api/uptime/logMonitor', + Overview = 'Overview', + Monitor = 'Monitor', + Settings = 'Settings', NotFound = '__not-found__', } -const getApiPath = (page?: UptimePage) => { - if (!page) throw new Error('Telemetry logging for this page not yet implemented'); - if (page === '__not-found__') - throw new Error('Telemetry logging for 404 page not yet implemented'); - return page.valueOf(); -}; - -const logPageLoad = async (fetch: HttpHandler, page?: UptimePage) => { - await fetch(getApiPath(page), { - method: 'POST', - }); -}; - export const useUptimeTelemetry = (page?: UptimePage) => { - const kibana = useKibana(); - const fetch = kibana.services.http?.fetch; + const [getUrlParams] = useUrlParams(); + const { dateRangeStart, dateRangeEnd, autorefreshInterval, autorefreshIsPaused } = getUrlParams(); + useEffect(() => { - if (!fetch) throw new Error('Core http services are not defined'); - logPageLoad(fetch, page); - }, [fetch, page]); + if (!apiService.http) throw new Error('Core http services are not defined'); + + const params = { + page, + autorefreshInterval: autorefreshInterval / 1000, // divide by 1000 to keep it in secs + dateStart: dateRangeStart, + dateEnd: dateRangeEnd, + autoRefreshEnabled: !autorefreshIsPaused, + }; + apiService.post(API_URLS.logPageView, params); + }, [autorefreshInterval, autorefreshIsPaused, dateRangeEnd, dateRangeStart, page]); }; diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 5871783dffdeb..3de636cac6ecd 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -51,6 +51,7 @@ export const MonitorPageComponent: React.FC = ({ const { dateRangeStart, dateRangeEnd, selectedPingStatus } = params; const [selectedLocation, setSelectedLocation] = useState(undefined); + const [pingListIndex, setPingListIndex] = useState(0); const sharedVariables = { dateRangeStart, @@ -81,11 +82,14 @@ export const MonitorPageComponent: React.FC = ({ updateUrlParams({ selectedPingStatus: selectedStatus || '' }); refreshApp(); }} + onPageIndexChange={(index: number) => setPingListIndex(index)} + pageIndex={pingListIndex} pageSize={pingListPageCount} selectedOption={selectedPingStatus} selectedLocation={selectedLocation} variables={{ ...sharedVariables, + page: pingListIndex, size: pingListPageCount, status: selectedPingStatus, }} diff --git a/x-pack/legacy/plugins/uptime/public/pages/settings.tsx b/x-pack/legacy/plugins/uptime/public/pages/settings.tsx index 679a61686e435..d3e17a15ee0e0 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/settings.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/settings.tsx @@ -6,19 +6,19 @@ import React, { useEffect, useState } from 'react'; import { - EuiForm, - EuiTitle, - EuiSpacer, + EuiButton, + EuiButtonEmpty, + EuiCallOut, + EuiCode, EuiDescribedFormGroup, EuiFieldText, - EuiFormRow, - EuiCode, - EuiPanel, EuiFlexGroup, EuiFlexItem, - EuiButton, - EuiButtonEmpty, - EuiCallOut, + EuiForm, + EuiFormRow, + EuiPanel, + EuiSpacer, + EuiTitle, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { connect } from 'react-redux'; @@ -29,10 +29,11 @@ import { AppState } from '../state'; import { selectDynamicSettings } from '../state/selectors'; import { DynamicSettingsState } from '../state/reducers/dynamic_settings'; import { getDynamicSettings, setDynamicSettings } from '../state/actions/dynamic_settings'; -import { DynamicSettings, defaultDynamicSettings } from '../../common/runtime_types'; +import { defaultDynamicSettings, DynamicSettings } from '../../common/runtime_types'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; import { OVERVIEW_ROUTE } from '../../common/constants'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { UptimePage, useUptimeTelemetry } from '../hooks'; interface Props { dynamicSettingsState: DynamicSettingsState; @@ -53,6 +54,8 @@ export const SettingsPageComponent = ({ }); useBreadcrumbs([{ text: settingsBreadcrumbText }]); + useUptimeTelemetry(UptimePage.Settings); + useEffect(() => { dispatchGetDynamicSettings({}); }, [dispatchGetDynamicSettings]); @@ -75,7 +78,8 @@ export const SettingsPageComponent = ({ } }; - const onApply = () => { + const onApply = (event: React.FormEvent) => { + event.preventDefault(); if (formFields) { dispatchSetDynamicSettings(formFields); } @@ -173,7 +177,9 @@ export const SettingsPageComponent = ({ } > { ...config, index: 'testing-123', refresh: false, + executionTimeField: null, }); config.executionTimeField = 'field-123'; @@ -62,6 +63,14 @@ describe('config validation', () => { executionTimeField: 'field-123', }); + config.executionTimeField = null; + expect(validateConfig(actionType, config)).toEqual({ + ...config, + index: 'testing-123', + refresh: false, + executionTimeField: null, + }); + delete config.index; expect(() => { @@ -73,9 +82,11 @@ describe('config validation', () => { expect(() => { validateConfig(actionType, { index: 'testing-123', executionTimeField: true }); - }).toThrowErrorMatchingInlineSnapshot( - `"error validating action type config: [executionTimeField]: expected value of type [string] but got [boolean]"` - ); + }).toThrowErrorMatchingInlineSnapshot(` +"error validating action type config: [executionTimeField]: types that failed validation: +- [executionTimeField.0]: expected value of type [string] but got [boolean] +- [executionTimeField.1]: expected value to equal [null]" +`); delete config.refresh; expect(() => { @@ -138,12 +149,12 @@ describe('params validation', () => { describe('execute()', () => { test('ensure parameters are as expected', async () => { const secrets = {}; - let config: ActionTypeConfigType; + let config: Partial; let params: ActionParamsType; let executorOptions: ActionTypeExecutorOptions; // minimal params - config = { index: 'index-value', refresh: false, executionTimeField: undefined }; + config = { index: 'index-value', refresh: false }; params = { documents: [{ jim: 'bob' }], }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/es_index.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts index b86f0029b5383..ff7b27b3f51fc 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/es_index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts @@ -18,7 +18,7 @@ export type ActionTypeConfigType = TypeOf; const ConfigSchema = schema.object({ index: schema.string(), refresh: schema.boolean({ defaultValue: false }), - executionTimeField: schema.maybe(schema.string()), + executionTimeField: schema.nullable(schema.string()), }); // params definition @@ -63,8 +63,9 @@ async function executor( const bulkBody = []; for (const document of params.documents) { - if (config.executionTimeField != null) { - document[config.executionTimeField] = new Date(); + const timeField = config.executionTimeField == null ? '' : config.executionTimeField.trim(); + if (timeField !== '') { + document[timeField] = new Date(); } bulkBody.push({ index: {} }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/action_handlers.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/action_handlers.test.ts index 2712b8f6ea9b5..aa9b1dcfcf239 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/action_handlers.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/action_handlers.test.ts @@ -226,15 +226,19 @@ describe('handleUpdateIncident', () => { const res = await handleUpdateIncident({ incidentId: '123', serviceNow, - params, + params: { + ...params, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, + }, comments: [], mapping: finalMapping, }); expect(serviceNow.updateIncident).toHaveBeenCalled(); expect(serviceNow.updateIncident).toHaveBeenCalledWith('123', { - short_description: 'a title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - description: 'a description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by Another User)', + description: 'a description (updated at 2020-03-15T08:34:53.450Z by Another User)', }); expect(serviceNow.updateIncident).toHaveReturned(); expect(serviceNow.batchCreateComments).not.toHaveBeenCalled(); @@ -256,7 +260,11 @@ describe('handleUpdateIncident', () => { const res = await handleUpdateIncident({ incidentId: '123', serviceNow, - params, + params: { + ...params, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, + }, comments: [ { comment: 'first comment', @@ -278,10 +286,10 @@ describe('handleUpdateIncident', () => { fullName: 'Elastic User', username: 'elastic', }, - updatedAt: '2020-03-13T08:34:53.450Z', + updatedAt: '2020-03-16T08:34:53.450Z', updatedBy: { - fullName: 'Elastic User', - username: 'elastic', + fullName: 'Another User', + username: 'anotherUser', }, version: 'WzU3LDFd', }, @@ -291,8 +299,8 @@ describe('handleUpdateIncident', () => { expect(serviceNow.updateIncident).toHaveBeenCalled(); expect(serviceNow.updateIncident).toHaveBeenCalledWith('123', { - description: 'a description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', - short_description: 'a title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + description: 'a description (updated at 2020-03-15T08:34:53.450Z by Another User)', + short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by Another User)', }); expect(serviceNow.updateIncident).toHaveReturned(); expect(serviceNow.batchCreateComments).toHaveBeenCalled(); @@ -312,17 +320,17 @@ describe('handleUpdateIncident', () => { version: 'WzU3LDFd', }, { - comment: 'second comment (added at 2020-03-13T08:34:53.450Z by Elastic User)', + comment: 'second comment (added at 2020-03-16T08:34:53.450Z by Another User)', commentId: '789', createdAt: '2020-03-13T08:34:53.450Z', createdBy: { fullName: 'Elastic User', username: 'elastic', }, - updatedAt: '2020-03-13T08:34:53.450Z', + updatedAt: '2020-03-16T08:34:53.450Z', updatedBy: { - fullName: 'Elastic User', - username: 'elastic', + fullName: 'Another User', + username: 'anotherUser', }, version: 'WzU3LDFd', }, diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.test.ts index ce8c3542ab69f..cbcefe6364e8f 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.test.ts @@ -191,13 +191,21 @@ describe('transformFields', () => { test('transform fields for update correctly', () => { const fields = prepareFieldsForTransformation({ - params: fullParams, + params: { + ...fullParams, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { username: 'anotherUser', fullName: 'Another User' }, + }, mapping: finalMapping, defaultPipes: ['informationUpdated'], }); const res = transformFields({ - params: fullParams, + params: { + ...fullParams, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { username: 'anotherUser', fullName: 'Another User' }, + }, fields, currentIncident: { short_description: 'first title (created at 2020-03-13T08:34:53.450Z by Elastic User)', @@ -205,9 +213,9 @@ describe('transformFields', () => { }, }); expect(res).toEqual({ - short_description: 'a title (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by Another User)', description: - 'first description (created at 2020-03-13T08:34:53.450Z by Elastic User) \r\na description (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + 'first description (created at 2020-03-13T08:34:53.450Z by Elastic User) \r\na description (updated at 2020-03-15T08:34:53.450Z by Another User)', }); }); @@ -229,7 +237,7 @@ describe('transformFields', () => { expect(res.description?.includes('\r\n')).toBe(true); }); - test('append username if fullname is undefined', () => { + test('append username if fullname is undefined when create', () => { const fields = prepareFieldsForTransformation({ params: fullParams, mapping: finalMapping, @@ -245,6 +253,32 @@ describe('transformFields', () => { description: 'a description (created at 2020-03-13T08:34:53.450Z by elastic)', }); }); + + test('append username if fullname is undefined when update', () => { + const fields = prepareFieldsForTransformation({ + params: { + ...fullParams, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { username: 'anotherUser', fullName: 'Another User' }, + }, + mapping: finalMapping, + defaultPipes: ['informationUpdated'], + }); + + const res = transformFields({ + params: { + ...fullParams, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { username: 'anotherUser', fullName: null }, + }, + fields, + }); + + expect(res).toEqual({ + short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by anotherUser)', + description: 'a description (updated at 2020-03-15T08:34:53.450Z by anotherUser)', + }); + }); }); describe('appendField', () => { @@ -330,8 +364,8 @@ describe('transformComments', () => { comment: 'first comment', createdAt: '2020-03-13T08:34:53.450Z', createdBy: { fullName: 'Elastic User', username: 'elastic' }, - updatedAt: null, - updatedBy: null, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, }, ]; const res = transformComments(comments, fullParams, ['informationUpdated']); @@ -339,11 +373,11 @@ describe('transformComments', () => { { commentId: 'b5b4c4d0-574e-11ea-9e2e-21b90f8a9631', version: 'WzU3LDFd', - comment: 'first comment (updated at 2020-03-13T08:34:53.450Z by Elastic User)', + comment: 'first comment (updated at 2020-03-15T08:34:53.450Z by Another User)', createdAt: '2020-03-13T08:34:53.450Z', createdBy: { fullName: 'Elastic User', username: 'elastic' }, - updatedAt: null, - updatedBy: null, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, }, ]); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.ts index 46d4789e0bd53..750fda93b60d6 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/helpers.ts @@ -83,8 +83,11 @@ export const transformFields = ({ const transform = flow(...cur.pipes.map(p => t[p])); prev[cur.key] = transform({ value: cur.value, - date: params.createdAt, - user: params.createdBy.fullName ?? params.createdBy.username, + date: params.updatedAt ?? params.createdAt, + user: + params.updatedBy != null + ? params.updatedBy.fullName ?? params.updatedBy.username + : params.createdBy.fullName ?? params.createdBy.username, previousValue: currentIncident ? currentIncident[cur.key] : '', }).value; return prev; @@ -112,8 +115,11 @@ export const transformComments = ( ...c, comment: flow(...pipes.map(p => t[p]))({ value: c.comment, - date: params.createdAt, - user: params.createdBy.fullName ?? '', + date: c.updatedAt ?? c.createdAt, + user: + c.updatedBy != null + ? c.updatedBy.fullName ?? c.updatedBy.username + : c.createdBy.fullName ?? c.createdBy.username, }).value, })); }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.test.ts index 7eda7060df846..1a23354e6490d 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/index.test.ts @@ -226,7 +226,11 @@ describe('execute()', () => { const executorOptions: ActionTypeExecutorOptions = { actionId, config: mockOptions.config, - params: { ...mockOptions.params, executorAction: 'updateIncident' }, + params: { + ...mockOptions.params, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, + }, secrets: mockOptions.secrets, services, }; @@ -244,7 +248,11 @@ describe('execute()', () => { const executorOptions: ActionTypeExecutorOptions = { actionId, config: mockOptions.config, - params: { ...mockOptions.params, executorAction: 'updateIncident' }, + params: { + ...mockOptions.params, + updatedAt: '2020-03-15T08:34:53.450Z', + updatedBy: { fullName: 'Another User', username: 'anotherUser' }, + }, secrets: mockOptions.secrets, services, }; diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index c6c4f377ab618..ce31e62bc9b8e 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -175,7 +175,7 @@ export class ActionsPlugin implements Plugin, Plugi const usageCollection = plugins.usageCollection; if (usageCollection) { - core.getStartServices().then(async ([coreStart, startPlugins]: [CoreStart, any]) => { + core.getStartServices().then(async ([, startPlugins]: [CoreStart, any, any]) => { registerActionsUsageCollector(usageCollection, startPlugins.taskManager); initializeActionsTelemetry( diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts new file mode 100644 index 0000000000000..1b0fe03633531 --- /dev/null +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getTotalCount } from './actions_telemetry'; + +describe('actions telemetry', () => { + test('getTotalCount should replace action types names with . to __', async () => { + const mockEsClient = jest.fn(); + mockEsClient.mockReturnValue({ + aggregations: { + byActionTypeId: { + value: { + types: { '.index': 1, '.server-log': 1 }, + }, + }, + }, + hits: { + hits: [ + { + _id: 'action:541efb3d-f82a-4d2c-a5c3-636d1ce49b53', + _index: '.kibana_1', + _score: 0, + _source: { + action: { + actionTypeId: '.index', + config: { + index: 'kibana_sample_data_ecommerce', + refresh: true, + executionTimeField: null, + }, + name: 'test', + secrets: + 'UPyn6cit6zBTPMmldfKh/8S2JWypwaLhhEQWBXp+OyTc6TtLHOnW92wehCqTq1FhIY3vA8hwVsggj+tbIoCcfPArpzP5SO7hh8vd6pY13x5TkiM083UgjjaAxbPvKQ==', + }, + references: [], + type: 'action', + updated_at: '2020-03-26T18:46:44.449Z', + }, + }, + { + _id: 'action:00000000-f82a-4d2c-a5c3-636d1ce49b53', + _index: '.kibana_1', + _score: 0, + _source: { + action: { + actionTypeId: '.server-log', + config: {}, + name: 'test server log', + secrets: '', + }, + references: [], + type: 'action', + updated_at: '2020-03-26T18:46:44.449Z', + }, + }, + ], + }, + }); + + const telemetry = await getTotalCount(mockEsClient, 'test'); + + expect(mockEsClient).toHaveBeenCalledTimes(1); + + expect(telemetry).toMatchInlineSnapshot(` +Object { + "countByType": Object { + "__index": 1, + "__server-log": 1, + }, + "countTotal": 2, +} +`); + }); +}); diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index ccdb4ecec2012..eabb38e61d17d 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -54,7 +54,13 @@ export async function getTotalCount(callCluster: APICaller, kibanaIndex: string) parseInt(searchResult.aggregations.byActionTypeId.value.types[key], 0) + total, 0 ), - countByType: searchResult.aggregations.byActionTypeId.value.types, + countByType: Object.keys(searchResult.aggregations.byActionTypeId.value.types).reduce( + (obj: any, key: string) => ({ + ...obj, + [key.replace('.', '__')]: searchResult.aggregations.byActionTypeId.value.types[key], + }), + {} + ), }; } diff --git a/x-pack/plugins/advanced_ui_actions/kibana.json b/x-pack/plugins/advanced_ui_actions/kibana.json index 515c4749de212..45907e2d8b602 100644 --- a/x-pack/plugins/advanced_ui_actions/kibana.json +++ b/x-pack/plugins/advanced_ui_actions/kibana.json @@ -1,6 +1,7 @@ { "id": "advancedUiActions", "version": "kibana", + "configPath": ["xpack", "advanced_ui_actions"], "requiredPlugins": [ "embeddable", "uiActions" diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.scss b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.scss index 87ec3f8fc7ec1..2ba6f9baca90d 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.scss +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.scss @@ -1,3 +1,8 @@ +.auaActionWizard__selectedActionFactoryContainer { + background-color: $euiColorLightestShade; + padding: $euiSize; +} + .auaActionWizard__actionFactoryItem { .euiKeyPadMenuItem__label { height: #{$euiSizeXL}; diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.story.tsx b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.story.tsx index 9c73f07289dc9..62f16890cade2 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.story.tsx +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.story.tsx @@ -6,26 +6,28 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -import { Demo, dashboardFactory, urlFactory } from './test_data'; +import { dashboardDrilldownActionFactory, Demo, urlDrilldownActionFactory } from './test_data'; storiesOf('components/ActionWizard', module) - .add('default', () => ) + .add('default', () => ( + + )) .add('Only one factory is available', () => ( // to make sure layout doesn't break - + )) .add('Long list of action factories', () => ( // to make sure layout doesn't break )); diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.test.tsx b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.test.tsx index cc56714fcb2f8..aea47be693b8f 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.test.tsx +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.test.tsx @@ -8,14 +8,21 @@ import React from 'react'; import { cleanup, fireEvent, render } from '@testing-library/react/pure'; import '@testing-library/jest-dom/extend-expect'; // TODO: this should be global import { TEST_SUBJ_ACTION_FACTORY_ITEM, TEST_SUBJ_SELECTED_ACTION_FACTORY } from './action_wizard'; -import { dashboardFactory, dashboards, Demo, urlFactory } from './test_data'; +import { + dashboardDrilldownActionFactory, + dashboards, + Demo, + urlDrilldownActionFactory, +} from './test_data'; // TODO: afterEach is not available for it globally during setup // https://github.com/elastic/kibana/issues/59469 afterEach(cleanup); test('Pick and configure action', () => { - const screen = render(); + const screen = render( + + ); // check that all factories are displayed to pick expect(screen.getAllByTestId(TEST_SUBJ_ACTION_FACTORY_ITEM)).toHaveLength(2); @@ -40,7 +47,7 @@ test('Pick and configure action', () => { }); test('If only one actions factory is available then actionFactory selection is emitted without user input', () => { - const screen = render(); + const screen = render(); // check that no factories are displayed to pick from expect(screen.queryByTestId(TEST_SUBJ_ACTION_FACTORY_ITEM)).not.toBeInTheDocument(); diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.tsx b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.tsx index 846f6d41eb30d..41ef863c00e44 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.tsx +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/action_wizard.tsx @@ -16,23 +16,40 @@ import { } from '@elastic/eui'; import { txtChangeButton } from './i18n'; import './action_wizard.scss'; -import { ActionFactory } from '../../services'; -type ActionBaseConfig = object; -type ActionFactoryBaseContext = object; +// TODO: this interface is temporary for just moving forward with the component +// and it will be imported from the ../ui_actions when implemented properly +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type ActionBaseConfig = {}; +export interface ActionFactory { + type: string; // TODO: type should be tied to Action and ActionByType + displayName: string; + iconType?: string; + wizard: React.FC>; + createConfig: () => Config; + isValid: (config: Config) => boolean; +} + +export interface ActionFactoryWizardProps { + config?: Config; + + /** + * Callback called when user updates the config in UI. + */ + onConfig: (config: Config) => void; +} export interface ActionWizardProps { /** * List of available action factories */ - actionFactories: ActionFactory[]; + actionFactories: Array>; // any here to be able to pass array of ActionFactory with different configs /** * Currently selected action factory * undefined - is allowed and means that non is selected */ currentActionFactory?: ActionFactory; - /** * Action factory selected changed * null - means user click "change" and removed action factory selection @@ -48,11 +65,6 @@ export interface ActionWizardProps { * config changed */ onConfigChange: (config: ActionBaseConfig) => void; - - /** - * Context will be passed into ActionFactory's methods - */ - context: ActionFactoryBaseContext; } export const ActionWizard: React.FC = ({ @@ -61,7 +73,6 @@ export const ActionWizard: React.FC = ({ onActionFactoryChange, onConfigChange, config, - context, }) => { // auto pick action factory if there is only 1 available if (!currentActionFactory && actionFactories.length === 1) { @@ -76,7 +87,6 @@ export const ActionWizard: React.FC = ({ onDeselect={() => { onActionFactoryChange(null); }} - context={context} config={config} onConfigChange={newConfig => { onConfigChange(newConfig); @@ -87,7 +97,6 @@ export const ActionWizard: React.FC = ({ return ( { onActionFactoryChange(actionFactory); @@ -96,11 +105,10 @@ export const ActionWizard: React.FC = ({ ); }; -interface SelectedActionFactoryProps { - actionFactory: ActionFactory; - config: ActionBaseConfig; - context: ActionFactoryBaseContext; - onConfigChange: (config: ActionBaseConfig) => void; +interface SelectedActionFactoryProps { + actionFactory: ActionFactory; + config: Config; + onConfigChange: (config: Config) => void; showDeselect: boolean; onDeselect: () => void; } @@ -113,28 +121,28 @@ const SelectedActionFactory: React.FC = ({ showDeselect, onConfigChange, config, - context, }) => { return (
- {actionFactory.getIconType(context) && ( + {actionFactory.iconType && ( - + )} -

{actionFactory.getDisplayName(context)}

+

{actionFactory.displayName}

{showDeselect && ( - onDeselect()}> + onDeselect()}> {txtChangeButton} @@ -143,11 +151,10 @@ const SelectedActionFactory: React.FC = ({
- + {actionFactory.wizard({ + config, + onConfig: onConfigChange, + })}
); @@ -155,7 +162,6 @@ const SelectedActionFactory: React.FC = ({ interface ActionFactorySelectorProps { actionFactories: ActionFactory[]; - context: ActionFactoryBaseContext; onActionFactorySelected: (actionFactory: ActionFactory) => void; } @@ -164,7 +170,6 @@ export const TEST_SUBJ_ACTION_FACTORY_ITEM = 'action-factory-item'; const ActionFactorySelector: React.FC = ({ actionFactories, onActionFactorySelected, - context, }) => { if (actionFactories.length === 0) { // this is not user facing, as it would be impossible to get into this state @@ -173,23 +178,19 @@ const ActionFactorySelector: React.FC = ({ } return ( - - {[...actionFactories] - .sort((f1, f2) => f1.order - f2.order) - .map(actionFactory => ( - - onActionFactorySelected(actionFactory)} - > - {actionFactory.getIconType(context) && ( - - )} - - - ))} + + {actionFactories.map(actionFactory => ( + onActionFactorySelected(actionFactory)} + > + {actionFactory.iconType && } + + ))} ); }; diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/i18n.ts b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/i18n.ts index a315184bf68ef..641f25176264a 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/i18n.ts +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/i18n.ts @@ -9,6 +9,6 @@ import { i18n } from '@kbn/i18n'; export const txtChangeButton = i18n.translate( 'xpack.advancedUiActions.components.actionWizard.changeButton', { - defaultMessage: 'Change', + defaultMessage: 'change', } ); diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/index.ts b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/index.ts index a189afbf956ee..ed224248ec4cd 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/index.ts +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ActionWizard } from './action_wizard'; +export { ActionFactory, ActionWizard } from './action_wizard'; diff --git a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/test_data.tsx b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/test_data.tsx index 167cb130fdb4a..8ecdde681069e 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/test_data.tsx +++ b/x-pack/plugins/advanced_ui_actions/public/components/action_wizard/test_data.tsx @@ -6,161 +6,124 @@ import React, { useState } from 'react'; import { EuiFieldText, EuiFormRow, EuiSelect, EuiSwitch } from '@elastic/eui'; -import { reactToUiComponent } from '../../../../../../src/plugins/kibana_react/public'; -import { ActionWizard } from './action_wizard'; -import { ActionFactoryDefinition, ActionFactory } from '../../services'; -import { CollectConfigProps } from '../../util'; - -type ActionBaseConfig = object; +import { ActionFactory, ActionBaseConfig, ActionWizard } from './action_wizard'; export const dashboards = [ { id: 'dashboard1', title: 'Dashboard 1' }, { id: 'dashboard2', title: 'Dashboard 2' }, ]; -interface DashboardDrilldownConfig { +export const dashboardDrilldownActionFactory: ActionFactory<{ dashboardId?: string; - useCurrentFilters: boolean; - useCurrentDateRange: boolean; -} - -function DashboardDrilldownCollectConfig(props: CollectConfigProps) { - const config = props.config ?? { - dashboardId: undefined, - useCurrentFilters: true, - useCurrentDateRange: true, - }; - return ( - <> - - ({ value: id, text: title }))} - value={config.dashboardId} - onChange={e => { - props.onConfig({ ...config, dashboardId: e.target.value }); - }} - /> - - - - props.onConfig({ - ...config, - useCurrentFilters: !config.useCurrentFilters, - }) - } - /> - - - - props.onConfig({ - ...config, - useCurrentDateRange: !config.useCurrentDateRange, - }) - } - /> - - - ); -} - -export const dashboardDrilldownActionFactory: ActionFactoryDefinition< - DashboardDrilldownConfig, - any, - any -> = { - id: 'Dashboard', - getDisplayName: () => 'Go to Dashboard', - getIconType: () => 'dashboardApp', + useCurrentDashboardFilters: boolean; + useCurrentDashboardDataRange: boolean; +}> = { + type: 'Dashboard', + displayName: 'Go to Dashboard', + iconType: 'dashboardApp', createConfig: () => { return { dashboardId: undefined, - useCurrentFilters: true, - useCurrentDateRange: true, + useCurrentDashboardDataRange: true, + useCurrentDashboardFilters: true, }; }, - isConfigValid: (config: DashboardDrilldownConfig): config is DashboardDrilldownConfig => { + isValid: config => { if (!config.dashboardId) return false; return true; }, - CollectConfig: reactToUiComponent(DashboardDrilldownCollectConfig), - - isCompatible(context?: object): Promise { - return Promise.resolve(true); + wizard: props => { + const config = props.config ?? { + dashboardId: undefined, + useCurrentDashboardDataRange: true, + useCurrentDashboardFilters: true, + }; + return ( + <> + + ({ value: id, text: title }))} + value={config.dashboardId} + onChange={e => { + props.onConfig({ ...config, dashboardId: e.target.value }); + }} + /> + + + + props.onConfig({ + ...config, + useCurrentDashboardFilters: !config.useCurrentDashboardFilters, + }) + } + /> + + + + props.onConfig({ + ...config, + useCurrentDashboardDataRange: !config.useCurrentDashboardDataRange, + }) + } + /> + + + ); }, - order: 0, - create: () => ({ - id: 'test', - execute: async () => alert('Navigate to dashboard!'), - }), }; -export const dashboardFactory = new ActionFactory(dashboardDrilldownActionFactory); - -interface UrlDrilldownConfig { - url: string; - openInNewTab: boolean; -} -function UrlDrilldownCollectConfig(props: CollectConfigProps) { - const config = props.config ?? { - url: '', - openInNewTab: false, - }; - return ( - <> - - props.onConfig({ ...config, url: event.target.value })} - /> - - - props.onConfig({ ...config, openInNewTab: !config.openInNewTab })} - /> - - - ); -} -export const urlDrilldownActionFactory: ActionFactoryDefinition = { - id: 'Url', - getDisplayName: () => 'Go to URL', - getIconType: () => 'link', +export const urlDrilldownActionFactory: ActionFactory<{ url: string; openInNewTab: boolean }> = { + type: 'Url', + displayName: 'Go to URL', + iconType: 'link', createConfig: () => { return { url: '', openInNewTab: false, }; }, - isConfigValid: (config: UrlDrilldownConfig): config is UrlDrilldownConfig => { + isValid: config => { if (!config.url) return false; return true; }, - CollectConfig: reactToUiComponent(UrlDrilldownCollectConfig), - - order: 10, - isCompatible(context?: object): Promise { - return Promise.resolve(true); + wizard: props => { + const config = props.config ?? { + url: '', + openInNewTab: false, + }; + return ( + <> + + props.onConfig({ ...config, url: event.target.value })} + /> + + + props.onConfig({ ...config, openInNewTab: !config.openInNewTab })} + /> + + + ); }, - create: () => null as any, }; -export const urlFactory = new ActionFactory(urlDrilldownActionFactory); - export function Demo({ actionFactories }: { actionFactories: Array> }) { const [state, setState] = useState<{ currentActionFactory?: ActionFactory; @@ -194,15 +157,14 @@ export function Demo({ actionFactories }: { actionFactories: Array

-
Action Factory Id: {state.currentActionFactory?.id}
+
Action Factory Type: {state.currentActionFactory?.type}
Action Factory Config: {JSON.stringify(state.config)}
Is config valid:{' '} - {JSON.stringify(state.currentActionFactory?.isConfigValid(state.config!) ?? false)} + {JSON.stringify(state.currentActionFactory?.isValid(state.config!) ?? false)}
); diff --git a/x-pack/plugins/advanced_ui_actions/public/custom_time_range_action.tsx b/x-pack/plugins/advanced_ui_actions/public/custom_time_range_action.tsx index c0cd8d5540db2..325a5ddc10179 100644 --- a/x-pack/plugins/advanced_ui_actions/public/custom_time_range_action.tsx +++ b/x-pack/plugins/advanced_ui_actions/public/custom_time_range_action.tsx @@ -44,7 +44,7 @@ export class CustomTimeRangeAction implements ActionByType { + implements Plugin { constructor(initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup, { uiActions }: SetupDependencies): SetupContract { - return { - ...uiActions, - }; - } + public setup(core: CoreSetup, { uiActions }: SetupDependencies): Setup {} - public start(core: CoreStart, { uiActions }: StartDependencies): StartContract { + public start(core: CoreStart, { uiActions }: StartDependencies): Start { const dateFormat = core.uiSettings.get('dateFormat') as string; const commonlyUsedRanges = core.uiSettings.get('timepicker:quickRanges') as CommonlyUsedRange[]; const { openModal } = createReactOverlays(core); @@ -72,18 +66,16 @@ export class AdvancedUiActionsPublicPlugin dateFormat, commonlyUsedRanges, }); - uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, timeRangeAction); + uiActions.registerAction(timeRangeAction); + uiActions.attachAction(CONTEXT_MENU_TRIGGER, timeRangeAction); const timeRangeBadge = new CustomTimeRangeBadge({ openModal, dateFormat, commonlyUsedRanges, }); - uiActions.addTriggerAction(PANEL_BADGE_TRIGGER, timeRangeBadge); - - return { - ...uiActions, - }; + uiActions.registerAction(timeRangeBadge); + uiActions.attachAction(PANEL_BADGE_TRIGGER, timeRangeBadge); } public stop() {} diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index b705a334bc2b5..9d4ea69a63609 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -10,4 +10,13 @@ export * from './alert_instance'; export * from './alert_task_instance'; export * from './alert_navigation'; +export interface ActionGroup { + id: string; + name: string; +} + +export interface AlertingFrameworkHealth { + isSufficientlySecure: boolean; +} + export const BASE_ALERT_API_PATH = '/api/alert'; diff --git a/x-pack/plugins/alerting/server/alerts_client.ts b/x-pack/plugins/alerting/server/alerts_client.ts index 49c80af0072c9..5538b44b69fcb 100644 --- a/x-pack/plugins/alerting/server/alerts_client.ts +++ b/x-pack/plugins/alerting/server/alerts_client.ts @@ -27,7 +27,7 @@ import { import { validateAlertTypeParams } from './lib'; import { InvalidateAPIKeyParams, - CreateAPIKeyResult as SecurityPluginCreateAPIKeyResult, + GrantAPIKeyResult as SecurityPluginGrantAPIKeyResult, InvalidateAPIKeyResult as SecurityPluginInvalidateAPIKeyResult, } from '../../../plugins/security/server'; import { EncryptedSavedObjectsPluginStart } from '../../../plugins/encrypted_saved_objects/server'; @@ -37,7 +37,7 @@ import { taskInstanceToAlertTaskInstance } from './task_runner/alert_task_instan type NormalizedAlertAction = Omit; export type CreateAPIKeyResult = | { apiKeysEnabled: false } - | { apiKeysEnabled: true; result: SecurityPluginCreateAPIKeyResult }; + | { apiKeysEnabled: true; result: SecurityPluginGrantAPIKeyResult }; export type InvalidateAPIKeyResult = | { apiKeysEnabled: false } | { apiKeysEnabled: true; result: SecurityPluginInvalidateAPIKeyResult }; diff --git a/x-pack/plugins/alerting/server/alerts_client_factory.test.ts b/x-pack/plugins/alerting/server/alerts_client_factory.test.ts index b0558ef1ea98c..4c74ca54a0d2f 100644 --- a/x-pack/plugins/alerting/server/alerts_client_factory.test.ts +++ b/x-pack/plugins/alerting/server/alerts_client_factory.test.ts @@ -17,7 +17,7 @@ jest.mock('./alerts_client'); const savedObjectsClient = savedObjectsClientMock.create(); const securityPluginSetup = { authc: { - createAPIKey: jest.fn(), + grantAPIKeyAsInternalUser: jest.fn(), getCurrentUser: jest.fn(), }, }; @@ -110,7 +110,7 @@ test('createAPIKey() returns { apiKeysEnabled: false } when security is enabled factory.create(KibanaRequest.from(fakeRequest), savedObjectsClient); const constructorCall = jest.requireMock('./alerts_client').AlertsClient.mock.calls[0][0]; - securityPluginSetup.authc.createAPIKey.mockResolvedValueOnce(null); + securityPluginSetup.authc.grantAPIKeyAsInternalUser.mockResolvedValueOnce(null); const createAPIKeyResult = await constructorCall.createAPIKey(); expect(createAPIKeyResult).toEqual({ apiKeysEnabled: false }); }); @@ -124,7 +124,10 @@ test('createAPIKey() returns an API key when security is enabled', async () => { factory.create(KibanaRequest.from(fakeRequest), savedObjectsClient); const constructorCall = jest.requireMock('./alerts_client').AlertsClient.mock.calls[0][0]; - securityPluginSetup.authc.createAPIKey.mockResolvedValueOnce({ api_key: '123', id: 'abc' }); + securityPluginSetup.authc.grantAPIKeyAsInternalUser.mockResolvedValueOnce({ + api_key: '123', + id: 'abc', + }); const createAPIKeyResult = await constructorCall.createAPIKey(); expect(createAPIKeyResult).toEqual({ apiKeysEnabled: true, @@ -141,7 +144,9 @@ test('createAPIKey() throws when security plugin createAPIKey throws an error', factory.create(KibanaRequest.from(fakeRequest), savedObjectsClient); const constructorCall = jest.requireMock('./alerts_client').AlertsClient.mock.calls[0][0]; - securityPluginSetup.authc.createAPIKey.mockRejectedValueOnce(new Error('TLS disabled')); + securityPluginSetup.authc.grantAPIKeyAsInternalUser.mockRejectedValueOnce( + new Error('TLS disabled') + ); await expect(constructorCall.createAPIKey()).rejects.toThrowErrorMatchingInlineSnapshot( `"TLS disabled"` ); diff --git a/x-pack/plugins/alerting/server/alerts_client_factory.ts b/x-pack/plugins/alerting/server/alerts_client_factory.ts index c502c0e5bf1cf..fd480658e236a 100644 --- a/x-pack/plugins/alerting/server/alerts_client_factory.ts +++ b/x-pack/plugins/alerting/server/alerts_client_factory.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import uuid from 'uuid'; import { AlertsClient } from './alerts_client'; import { AlertTypeRegistry, SpaceIdToNamespaceFunction } from './types'; import { KibanaRequest, Logger, SavedObjectsClientContract } from '../../../../src/core/server'; @@ -71,10 +70,12 @@ export class AlertsClientFactory { if (!securityPluginSetup) { return { apiKeysEnabled: false }; } - const createAPIKeyResult = await securityPluginSetup.authc.createAPIKey(request, { - name: `source: alerting, generated uuid: "${uuid.v4()}"`, - role_descriptors: {}, - }); + // Create an API key using the new grant API - in this case the Kibana system user is creating the + // API key for the user, instead of having the user create it themselves, which requires api_key + // privileges + const createAPIKeyResult = await securityPluginSetup.authc.grantAPIKeyAsInternalUser( + request + ); if (!createAPIKeyResult) { return { apiKeysEnabled: false }; } @@ -87,8 +88,7 @@ export class AlertsClientFactory { if (!securityPluginSetup) { return { apiKeysEnabled: false }; } - const invalidateAPIKeyResult = await securityPluginSetup.authc.invalidateAPIKey( - request, + const invalidateAPIKeyResult = await securityPluginSetup.authc.invalidateAPIKeyAsInternalUser( params ); // Null when Elasticsearch security is disabled diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 58807b42dc278..b0d06d4aeeb74 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -46,6 +46,7 @@ import { unmuteAllAlertRoute, muteAlertInstanceRoute, unmuteAlertInstanceRoute, + healthRoute, } from './routes'; import { LicensingPluginSetup } from '../../licensing/server'; import { @@ -142,7 +143,7 @@ export class AlertingPlugin { const usageCollection = plugins.usageCollection; if (usageCollection) { - core.getStartServices().then(async ([coreStart, startPlugins]: [CoreStart, any]) => { + core.getStartServices().then(async ([, startPlugins]: [CoreStart, any, any]) => { registerAlertsUsageCollector(usageCollection, startPlugins.taskManager); initializeAlertingTelemetry( @@ -173,6 +174,7 @@ export class AlertingPlugin { unmuteAllAlertRoute(router, this.licenseState); muteAlertInstanceRoute(router, this.licenseState); unmuteAlertInstanceRoute(router, this.licenseState); + healthRoute(router, this.licenseState); return { registerType: alertTypeRegistry.register.bind(alertTypeRegistry), diff --git a/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts index 9815ad5194af7..5a1d680eb06f3 100644 --- a/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/alerting/server/routes/_mock_handler_arguments.ts @@ -10,13 +10,14 @@ import { httpServerMock } from '../../../../../src/core/server/mocks'; import { alertsClientMock } from '../alerts_client.mock'; export function mockHandlerArguments( - { alertsClient, listTypes: listTypesRes = [] }: any, + { alertsClient, listTypes: listTypesRes = [], elasticsearch }: any, req: any, res?: Array> ): [RequestHandlerContext, KibanaRequest, KibanaResponseFactory] { const listTypes = jest.fn(() => listTypesRes); return [ ({ + core: { elasticsearch }, alerting: { listTypes, getAlertsClient() { diff --git a/x-pack/plugins/alerting/server/routes/create.ts b/x-pack/plugins/alerting/server/routes/create.ts index 7e17a66e84547..f08460ffcb453 100644 --- a/x-pack/plugins/alerting/server/routes/create.ts +++ b/x-pack/plugins/alerting/server/routes/create.ts @@ -15,6 +15,7 @@ import { import { LicenseState } from '../lib/license_state'; import { verifyApiAccess } from '../lib/license_api_access'; import { validateDurationSchema } from '../lib'; +import { handleDisabledApiKeysError } from './lib/error_handler'; import { Alert, BASE_ALERT_API_PATH } from '../types'; export const bodySchema = schema.object({ @@ -50,22 +51,24 @@ export const createAlertRoute = (router: IRouter, licenseState: LicenseState) => tags: ['access:alerting-all'], }, }, - router.handleLegacyErrors(async function( - context: RequestHandlerContext, - req: KibanaRequest, any>, - res: KibanaResponseFactory - ): Promise> { - verifyApiAccess(licenseState); + handleDisabledApiKeysError( + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - const alertsClient = context.alerting.getAlertsClient(); - const alert = req.body; - const alertRes: Alert = await alertsClient.create({ data: alert }); - return res.ok({ - body: alertRes, - }); - }) + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const alert = req.body; + const alertRes: Alert = await alertsClient.create({ data: alert }); + return res.ok({ + body: alertRes, + }); + }) + ) ); }; diff --git a/x-pack/plugins/alerting/server/routes/enable.ts b/x-pack/plugins/alerting/server/routes/enable.ts index 9fb837e5074e8..2283ae4a4c765 100644 --- a/x-pack/plugins/alerting/server/routes/enable.ts +++ b/x-pack/plugins/alerting/server/routes/enable.ts @@ -15,6 +15,7 @@ import { import { LicenseState } from '../lib/license_state'; import { verifyApiAccess } from '../lib/license_api_access'; import { BASE_ALERT_API_PATH } from '../../common'; +import { handleDisabledApiKeysError } from './lib/error_handler'; const paramSchema = schema.object({ id: schema.string(), @@ -31,19 +32,21 @@ export const enableAlertRoute = (router: IRouter, licenseState: LicenseState) => tags: ['access:alerting-all'], }, }, - router.handleLegacyErrors(async function( - context: RequestHandlerContext, - req: KibanaRequest, any, any, any>, - res: KibanaResponseFactory - ): Promise> { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - const alertsClient = context.alerting.getAlertsClient(); - const { id } = req.params; - await alertsClient.enable({ id }); - return res.noContent(); - }) + handleDisabledApiKeysError( + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, any, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + await alertsClient.enable({ id }); + return res.noContent(); + }) + ) ); }; diff --git a/x-pack/plugins/alerting/server/routes/health.test.ts b/x-pack/plugins/alerting/server/routes/health.test.ts new file mode 100644 index 0000000000000..9efe020bc10c4 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/health.test.ts @@ -0,0 +1,171 @@ +/* + * 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 { healthRoute } from './health'; +import { mockRouter, RouterMock } from '../../../../../src/core/server/http/router/router.mock'; +import { mockHandlerArguments } from './_mock_handler_arguments'; +import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { mockLicenseState } from '../lib/license_state.mock'; + +jest.mock('../lib/license_api_access.ts', () => ({ + verifyApiAccess: jest.fn(), +})); + +beforeEach(() => { + jest.resetAllMocks(); +}); + +describe('healthRoute', () => { + it('registers the route', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + + const [config] = router.get.mock.calls[0]; + + expect(config.path).toMatchInlineSnapshot(`"/api/alert/_health"`); + }); + + it('queries the usage api', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue(Promise.resolve({})); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + await handler(context, req, res); + + expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); + + expect(elasticsearch.adminClient.callAsInternalUser.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "transport.request", + Object { + "method": "GET", + "path": "/_xpack/usage", + }, + ] + `); + }); + + it('evaluates missing security info from the usage api to mean that the security plugin is disbled', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue(Promise.resolve({})); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "isSufficientlySecure": true, + }, + } + `); + }); + + it('evaluates missing security http info from the usage api to mean that the security plugin is disbled', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue(Promise.resolve({ security: {} })); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "isSufficientlySecure": true, + }, + } + `); + }); + + it('evaluates security enabled, and missing ssl info from the usage api to mean that the user cannot generate keys', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue( + Promise.resolve({ security: { enabled: true } }) + ); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "isSufficientlySecure": false, + }, + } + `); + }); + + it('evaluates security enabled, SSL info present but missing http info from the usage api to mean that the user cannot generate keys', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue( + Promise.resolve({ security: { enabled: true, ssl: {} } }) + ); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "isSufficientlySecure": false, + }, + } + `); + }); + + it('evaluates security and tls enabled to mean that the user can generate keys', async () => { + const router: RouterMock = mockRouter.create(); + + const licenseState = mockLicenseState(); + healthRoute(router, licenseState); + const [, handler] = router.get.mock.calls[0]; + + const elasticsearch = elasticsearchServiceMock.createSetup(); + elasticsearch.adminClient.callAsInternalUser.mockReturnValue( + Promise.resolve({ security: { enabled: true, ssl: { http: { enabled: true } } } }) + ); + + const [context, req, res] = mockHandlerArguments({ elasticsearch }, {}, ['ok']); + + expect(await handler(context, req, res)).toMatchInlineSnapshot(` + Object { + "body": Object { + "isSufficientlySecure": true, + }, + } + `); + }); +}); diff --git a/x-pack/plugins/alerting/server/routes/health.ts b/x-pack/plugins/alerting/server/routes/health.ts new file mode 100644 index 0000000000000..29c2f3c5730f4 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/health.ts @@ -0,0 +1,67 @@ +/* + * 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 { + IRouter, + RequestHandlerContext, + KibanaRequest, + IKibanaResponse, + KibanaResponseFactory, +} from 'kibana/server'; +import { LicenseState } from '../lib/license_state'; +import { verifyApiAccess } from '../lib/license_api_access'; +import { AlertingFrameworkHealth } from '../types'; + +interface XPackUsageSecurity { + security?: { + enabled?: boolean; + ssl?: { + http?: { + enabled?: boolean; + }; + }; + }; +} + +export function healthRoute(router: IRouter, licenseState: LicenseState) { + router.get( + { + path: '/api/alert/_health', + validate: false, + }, + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + try { + const { + security: { + enabled: isSecurityEnabled = false, + ssl: { http: { enabled: isTLSEnabled = false } = {} } = {}, + } = {}, + }: XPackUsageSecurity = await context.core.elasticsearch.adminClient + // `transport.request` is potentially unsafe when combined with untrusted user input. + // Do not augment with such input. + .callAsInternalUser('transport.request', { + method: 'GET', + path: '/_xpack/usage', + }); + + const frameworkHealth: AlertingFrameworkHealth = { + isSufficientlySecure: !isSecurityEnabled || (isSecurityEnabled && isTLSEnabled), + }; + + return res.ok({ + body: frameworkHealth, + }); + } catch (error) { + return res.badRequest({ body: error }); + } + }) + ); +} diff --git a/x-pack/plugins/alerting/server/routes/index.ts b/x-pack/plugins/alerting/server/routes/index.ts index 7ec901ae685c4..f833a29c67bb9 100644 --- a/x-pack/plugins/alerting/server/routes/index.ts +++ b/x-pack/plugins/alerting/server/routes/index.ts @@ -18,3 +18,4 @@ export { muteAlertInstanceRoute } from './mute_instance'; export { unmuteAlertInstanceRoute } from './unmute_instance'; export { muteAllAlertRoute } from './mute_all'; export { unmuteAllAlertRoute } from './unmute_all'; +export { healthRoute } from './health'; diff --git a/x-pack/plugins/alerting/server/routes/lib/error_handler.ts b/x-pack/plugins/alerting/server/routes/lib/error_handler.ts new file mode 100644 index 0000000000000..b3cf48c52fe17 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/lib/error_handler.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { + RequestHandler, + KibanaRequest, + KibanaResponseFactory, + RequestHandlerContext, + RouteMethod, +} from 'kibana/server'; + +export function handleDisabledApiKeysError( + handler: RequestHandler +): RequestHandler { + return async ( + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) => { + try { + return await handler(context, request, response); + } catch (e) { + if (isApiKeyDisabledError(e)) { + return response.badRequest({ + body: new Error( + i18n.translate('xpack.alerting.api.error.disabledApiKeys', { + defaultMessage: 'Alerting relies upon API keys which appear to be disabled', + }) + ), + }); + } + throw e; + } + }; +} + +export function isApiKeyDisabledError(e: Error) { + return e?.message?.includes('api keys are not enabled') ?? false; +} + +export function isSecurityPluginDisabledError(e: Error) { + return e?.message?.includes('no handler found') ?? false; +} diff --git a/x-pack/plugins/alerting/server/routes/update.ts b/x-pack/plugins/alerting/server/routes/update.ts index 26a8320fffebb..45f7b26b521d4 100644 --- a/x-pack/plugins/alerting/server/routes/update.ts +++ b/x-pack/plugins/alerting/server/routes/update.ts @@ -15,6 +15,7 @@ import { import { LicenseState } from '../lib/license_state'; import { verifyApiAccess } from '../lib/license_api_access'; import { validateDurationSchema } from '../lib'; +import { handleDisabledApiKeysError } from './lib/error_handler'; import { BASE_ALERT_API_PATH } from '../../common'; const paramSchema = schema.object({ @@ -52,24 +53,26 @@ export const updateAlertRoute = (router: IRouter, licenseState: LicenseState) => tags: ['access:alerting-all'], }, }, - router.handleLegacyErrors(async function( - context: RequestHandlerContext, - req: KibanaRequest, any, TypeOf, any>, - res: KibanaResponseFactory - ): Promise> { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - const alertsClient = context.alerting.getAlertsClient(); - const { id } = req.params; - const { name, actions, params, schedule, tags, throttle } = req.body; - return res.ok({ - body: await alertsClient.update({ - id, - data: { name, actions, params, schedule, tags, throttle }, - }), - }); - }) + handleDisabledApiKeysError( + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, TypeOf, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + const { name, actions, params, schedule, tags, throttle } = req.body; + return res.ok({ + body: await alertsClient.update({ + id, + data: { name, actions, params, schedule, tags, throttle }, + }), + }); + }) + ) ); }; diff --git a/x-pack/plugins/alerting/server/routes/update_api_key.ts b/x-pack/plugins/alerting/server/routes/update_api_key.ts index 62c1b1510ddac..f70d30f0bb5da 100644 --- a/x-pack/plugins/alerting/server/routes/update_api_key.ts +++ b/x-pack/plugins/alerting/server/routes/update_api_key.ts @@ -15,6 +15,7 @@ import { import { LicenseState } from '../lib/license_state'; import { verifyApiAccess } from '../lib/license_api_access'; import { BASE_ALERT_API_PATH } from '../../common'; +import { handleDisabledApiKeysError } from './lib/error_handler'; const paramSchema = schema.object({ id: schema.string(), @@ -31,19 +32,21 @@ export const updateApiKeyRoute = (router: IRouter, licenseState: LicenseState) = tags: ['access:alerting-all'], }, }, - router.handleLegacyErrors(async function( - context: RequestHandlerContext, - req: KibanaRequest, any, any, any>, - res: KibanaResponseFactory - ): Promise> { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - const alertsClient = context.alerting.getAlertsClient(); - const { id } = req.params; - await alertsClient.updateApiKey({ id }); - return res.noContent(); - }) + handleDisabledApiKeysError( + router.handleLegacyErrors(async function( + context: RequestHandlerContext, + req: KibanaRequest, any, any, any>, + res: KibanaResponseFactory + ): Promise> { + verifyApiAccess(licenseState); + if (!context.alerting) { + return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); + } + const alertsClient = context.alerting.getAlertsClient(); + const { id } = req.params; + await alertsClient.updateApiKey({ id }); + return res.noContent(); + }) + ) ); }; diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts new file mode 100644 index 0000000000000..171f80cf11cb8 --- /dev/null +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getTotalCountInUse } from './alerts_telemetry'; + +describe('alerts telemetry', () => { + test('getTotalCountInUse should replace action types names with . to __', async () => { + const mockEsClient = jest.fn(); + mockEsClient.mockReturnValue({ + aggregations: { + byAlertTypeId: { + value: { + types: { '.index-threshold': 2 }, + }, + }, + }, + hits: { + hits: [], + }, + }); + + const telemetry = await getTotalCountInUse(mockEsClient, 'test'); + + expect(mockEsClient).toHaveBeenCalledTimes(1); + + expect(telemetry).toMatchInlineSnapshot(` +Object { + "countByType": Object { + "__index-threshold": 2, + }, + "countTotal": 2, +} +`); + }); +}); diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts index 9ab63b7755500..9c710fa3b3b8e 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts @@ -245,7 +245,13 @@ export async function getTotalCountAggregations(callCluster: APICaller, kibanaIn return { count_total: totalAlertsCount, - count_by_type: results.aggregations.byAlertTypeId.value.types, + count_by_type: Object.keys(results.aggregations.byAlertTypeId.value.types).reduce( + (obj: any, key: string) => ({ + ...obj, + [key.replace('.', '__')]: results.aggregations.byAlertTypeId.value.types[key], + }), + {} + ), throttle_time: { min: `${results.aggregations.throttleTime.value.min}s`, avg: `${ @@ -298,7 +304,13 @@ export async function getTotalCountInUse(callCluster: APICaller, kibanaInex: str parseInt(searchResult.aggregations.byAlertTypeId.value.types[key], 0) + total, 0 ), - countByType: searchResult.aggregations.byAlertTypeId.value.types, + countByType: Object.keys(searchResult.aggregations.byAlertTypeId.value.types).reduce( + (obj: any, key: string) => ({ + ...obj, + [key.replace('.', '__')]: searchResult.aggregations.byAlertTypeId.value.types[key], + }), + {} + ), }; } diff --git a/x-pack/plugins/alerting_builtins/kibana.json b/x-pack/plugins/alerting_builtins/kibana.json index cd6bb7519c093..78de9a1ae0165 100644 --- a/x-pack/plugins/alerting_builtins/kibana.json +++ b/x-pack/plugins/alerting_builtins/kibana.json @@ -4,5 +4,6 @@ "version": "8.0.0", "kibanaVersion": "kibana", "requiredPlugins": ["alerting"], + "configPath": ["xpack", "alerting_builtins"], "ui": false } diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index 365d8838a24a6..0c585bec22f6c 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -2,11 +2,6 @@ exports[`settingDefinitions should have correct default values 1`] = ` Array [ - Object { - "key": "active", - "type": "boolean", - "validationName": "(\\"true\\" | \\"false\\")", - }, Object { "key": "api_request_size", "type": "bytes", @@ -105,6 +100,11 @@ Array [ "validationError": "Please specify an integer and a unit", "validationName": "durationRt", }, + Object { + "key": "recording", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, Object { "key": "server_timeout", "type": "duration", diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index b6eb40305dae7..6a0e2d65d1949 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -13,21 +13,6 @@ import { RawSettingDefinition } from './types'; * Settings added here will show up in the UI and will be validated on the client and server */ export const generalSettings: RawSettingDefinition[] = [ - // Active - { - key: 'active', - type: 'boolean', - defaultValue: 'true', - label: i18n.translate('xpack.apm.agentConfig.active.label', { - defaultMessage: 'Active' - }), - description: i18n.translate('xpack.apm.agentConfig.active.description', { - defaultMessage: - 'A boolean specifying if the agent should be active or not.\nWhen active, the agent instruments incoming HTTP requests, tracks errors and collects and sends metrics.\nWhen inactive, the agent works as a noop, not collecting data and not communicating with the APM Server.\nAs this is a reversible switch, agent threads are not being killed when inactivated, but they will be \nmostly idle in this state, so the overhead should be negligible.\n\nYou can use this setting to dynamically disable Elastic APM at runtime.' - }), - excludeAgents: ['js-base', 'rum-js', 'python', 'dotnet'] - }, - // API Request Size { key: 'api_request_size', @@ -40,7 +25,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'xpack.apm.agentConfig.apiRequestSize.description', { defaultMessage: - 'The maximum total compressed size of the request body which is sent to the APM server intake api via a chunked encoding (HTTP streaming).\nNote that a small overshoot is possible.\n\nAllowed byte units are `b`, `kb` and `mb`. `1kb` is equal to `1024b`.' + 'The maximum total compressed size of the request body which is sent to the APM Server intake api via a chunked encoding (HTTP streaming).\nNote that a small overshoot is possible.\n\nAllowed byte units are `b`, `kb` and `mb`. `1kb` is equal to `1024b`.' } ), excludeAgents: ['js-base', 'rum-js', 'dotnet'] @@ -64,24 +49,6 @@ export const generalSettings: RawSettingDefinition[] = [ excludeAgents: ['js-base', 'rum-js', 'dotnet'] }, - // Capture headers - { - key: 'capture_headers', - type: 'boolean', - defaultValue: 'true', - label: i18n.translate('xpack.apm.agentConfig.captureHeaders.label', { - defaultMessage: 'Capture Headers' - }), - description: i18n.translate( - 'xpack.apm.agentConfig.captureHeaders.description', - { - defaultMessage: - 'If set to `true`, the agent will capture request and response headers, including cookies.\n\nNOTE: Setting this to `false` reduces network bandwidth, disk space and object allocations.' - } - ), - excludeAgents: ['js-base', 'rum-js'] - }, - // Capture body { key: 'capture_body', @@ -104,7 +71,25 @@ export const generalSettings: RawSettingDefinition[] = [ { text: 'transactions' }, { text: 'all' } ], - excludeAgents: ['js-base', 'rum-js', 'dotnet'] + excludeAgents: ['js-base', 'rum-js'] + }, + + // Capture headers + { + key: 'capture_headers', + type: 'boolean', + defaultValue: 'true', + label: i18n.translate('xpack.apm.agentConfig.captureHeaders.label', { + defaultMessage: 'Capture Headers' + }), + description: i18n.translate( + 'xpack.apm.agentConfig.captureHeaders.description', + { + defaultMessage: + 'If set to `true`, the agent will capture request and response headers, including cookies.\n\nNOTE: Setting this to `false` reduces network bandwidth, disk space and object allocations.' + } + ), + excludeAgents: ['js-base', 'rum-js'] }, // LOG_LEVEL @@ -121,6 +106,20 @@ export const generalSettings: RawSettingDefinition[] = [ excludeAgents: ['js-base', 'rum-js', 'python'] }, + // Recording + { + key: 'recording', + type: 'boolean', + defaultValue: 'true', + label: i18n.translate('xpack.apm.agentConfig.recording.label', { + defaultMessage: 'Recording' + }), + description: i18n.translate('xpack.apm.agentConfig.recording.description', { + defaultMessage: + 'When recording, the agent instruments incoming HTTP requests, tracks errors, and collects and sends metrics. When inactive, the agent works as a noop, not collecting data and not communicating with the APM Server except for polling for updated configuration. As this is a reversible switch, agent threads are not being killed when inactivated, but they will be mostly idle in this state, so the overhead should be negligible. You can use this setting to dynamically control whether Elastic APM is enabled or disabled.' + }) + }, + // SERVER_TIMEOUT { key: 'server_timeout', @@ -133,7 +132,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'xpack.apm.agentConfig.serverTimeout.description', { defaultMessage: - 'If a request to the APM server takes longer than the configured timeout,\nthe request is cancelled and the event (exception or transaction) is discarded.\nSet to 0 to disable timeouts.\n\nWARNING: If timeouts are disabled or set to a high value, your app could experience memory issues if the APM server times out.' + 'If a request to the APM Server takes longer than the configured timeout,\nthe request is cancelled and the event (exception or transaction) is discarded.\nSet to 0 to disable timeouts.\n\nWARNING: If timeouts are disabled or set to a high value, your app could experience memory issues if the APM Server times out.' } ), includeAgents: ['nodejs', 'java', 'go'] @@ -175,23 +174,6 @@ export const generalSettings: RawSettingDefinition[] = [ includeAgents: ['nodejs', 'java', 'dotnet', 'go'] }, - // Transaction sample rate - { - key: 'transaction_sample_rate', - type: 'float', - defaultValue: '1.0', - label: i18n.translate('xpack.apm.agentConfig.transactionSampleRate.label', { - defaultMessage: 'Transaction sample rate' - }), - description: i18n.translate( - 'xpack.apm.agentConfig.transactionSampleRate.description', - { - defaultMessage: - 'By default, the agent will sample every transaction (e.g. request to your service). To reduce overhead and storage requirements, you can set the sample rate to a value between 0.0 and 1.0. We still record overall time and the result for unsampled transactions, but no context information, labels, or spans.' - } - ) - }, - // Transaction max spans { key: 'transaction_max_spans', @@ -215,5 +197,22 @@ export const generalSettings: RawSettingDefinition[] = [ min: 0, max: 32000, excludeAgents: ['js-base', 'rum-js'] + }, + + // Transaction sample rate + { + key: 'transaction_sample_rate', + type: 'float', + defaultValue: '1.0', + label: i18n.translate('xpack.apm.agentConfig.transactionSampleRate.label', { + defaultMessage: 'Transaction sample rate' + }), + description: i18n.translate( + 'xpack.apm.agentConfig.transactionSampleRate.description', + { + defaultMessage: + 'By default, the agent will sample every transaction (e.g. request to your service). To reduce overhead and storage requirements, you can set the sample rate to a value between 0.0 and 1.0. We still record overall time and the result for unsampled transactions, but no context information, labels, or spans.' + } + ) } ]; diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts index 0d1113d74c98b..b0255d2d828bb 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts @@ -43,12 +43,12 @@ describe('filterByAgent', () => { describe('options per agent', () => { it('go', () => { expect(getSettingKeysForAgent('go')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'server_timeout', 'span_frames_min_duration', 'stack_trace_limit', @@ -59,7 +59,6 @@ describe('filterByAgent', () => { it('java', () => { expect(getSettingKeysForAgent('java')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', @@ -72,6 +71,7 @@ describe('filterByAgent', () => { 'profiling_inferred_spans_included_classes', 'profiling_inferred_spans_min_duration', 'profiling_inferred_spans_sampling_interval', + 'recording', 'server_timeout', 'span_frames_min_duration', 'stack_trace_limit', @@ -88,24 +88,26 @@ describe('filterByAgent', () => { it('js-base', () => { expect(getSettingKeysForAgent('js-base')).toEqual([ + 'recording', 'transaction_sample_rate' ]); }); it('rum-js', () => { expect(getSettingKeysForAgent('rum-js')).toEqual([ + 'recording', 'transaction_sample_rate' ]); }); it('nodejs', () => { expect(getSettingKeysForAgent('nodejs')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'server_timeout', 'stack_trace_limit', 'transaction_max_spans', @@ -119,6 +121,7 @@ describe('filterByAgent', () => { 'api_request_time', 'capture_body', 'capture_headers', + 'recording', 'span_frames_min_duration', 'transaction_max_spans', 'transaction_sample_rate' @@ -127,8 +130,10 @@ describe('filterByAgent', () => { it('dotnet', () => { expect(getSettingKeysForAgent('dotnet')).toEqual([ + 'capture_body', 'capture_headers', 'log_level', + 'recording', 'span_frames_min_duration', 'stack_trace_limit', 'transaction_max_spans', @@ -138,12 +143,12 @@ describe('filterByAgent', () => { it('ruby', () => { expect(getSettingKeysForAgent('ruby')).toEqual([ - 'active', 'api_request_size', 'api_request_time', 'capture_body', 'capture_headers', 'log_level', + 'recording', 'span_frames_min_duration', 'transaction_max_spans', 'transaction_sample_rate' @@ -152,7 +157,9 @@ describe('filterByAgent', () => { it('"All" services (no agent name)', () => { expect(getSettingKeysForAgent(undefined)).toEqual([ + 'capture_body', 'capture_headers', + 'recording', 'transaction_max_spans', 'transaction_sample_rate' ]); diff --git a/x-pack/plugins/apm/common/custom_link/custom_link_filter_options.ts b/x-pack/plugins/apm/common/custom_link/custom_link_filter_options.ts new file mode 100644 index 0000000000000..65d2877dabe9a --- /dev/null +++ b/x-pack/plugins/apm/common/custom_link/custom_link_filter_options.ts @@ -0,0 +1,18 @@ +/* + * 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 { + SERVICE_NAME, + SERVICE_ENVIRONMENT, + TRANSACTION_NAME, + TRANSACTION_TYPE +} from '../elasticsearch_fieldnames'; + +export const FILTER_OPTIONS = [ + SERVICE_NAME, + SERVICE_ENVIRONMENT, + TRANSACTION_TYPE, + TRANSACTION_NAME +] as const; diff --git a/x-pack/plugins/apm/common/custom_link/custom_link_types.d.ts b/x-pack/plugins/apm/common/custom_link/custom_link_types.d.ts new file mode 100644 index 0000000000000..ca5e475554951 --- /dev/null +++ b/x-pack/plugins/apm/common/custom_link/custom_link_types.d.ts @@ -0,0 +1,39 @@ +/* + * 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 { + SERVICE_NAME, + SERVICE_ENVIRONMENT, + TRANSACTION_NAME, + TRANSACTION_TYPE +} from '../elasticsearch_fieldnames'; +import { FILTER_OPTIONS } from './custom_link_filter_options'; + +export interface CustomLinkES { + id?: string; + '@timestamp'?: number; + label: string; + url: string; + [SERVICE_NAME]?: string[]; + [SERVICE_ENVIRONMENT]?: string[]; + [TRANSACTION_NAME]?: string[]; + [TRANSACTION_TYPE]?: string[]; +} + +export type FilterKey = typeof FILTER_OPTIONS[number]; + +export interface Filter { + key: FilterKey | ''; + value: string; +} + +export interface CustomLink { + id?: string; + '@timestamp'?: number; + label: string; + url: string; + filters?: Filter[]; +} diff --git a/x-pack/plugins/apm/common/custom_link_filter_options.ts b/x-pack/plugins/apm/common/custom_link_filter_options.ts deleted file mode 100644 index 32b19ad60a646..0000000000000 --- a/x-pack/plugins/apm/common/custom_link_filter_options.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import * as t from 'io-ts'; -import { - SERVICE_NAME, - SERVICE_ENVIRONMENT, - TRANSACTION_TYPE, - TRANSACTION_NAME -} from './elasticsearch_fieldnames'; - -export const FilterOptionsRt = t.partial({ - [SERVICE_NAME]: t.union([t.string, t.array(t.string)]), - [SERVICE_ENVIRONMENT]: t.union([t.string, t.array(t.string)]), - [TRANSACTION_NAME]: t.union([t.string, t.array(t.string)]), - [TRANSACTION_TYPE]: t.union([t.string, t.array(t.string)]) -}); - -export type FilterOptions = t.TypeOf; - -export const FILTER_OPTIONS: ReadonlyArray = [ - SERVICE_NAME, - SERVICE_ENVIRONMENT, - TRANSACTION_TYPE, - TRANSACTION_NAME -] as const; diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index c80057a2894dc..a78b2b93a250d 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -96,14 +96,22 @@ export async function createApmTelemetry({ const collector = usageCollector.makeUsageCollector({ type: 'apm', fetch: async () => { - const data = ( - await savedObjectsClient.get( - APM_TELEMETRY_SAVED_OBJECT_TYPE, - APM_TELEMETRY_SAVED_OBJECT_ID - ) - ).attributes; + try { + const data = ( + await savedObjectsClient.get( + APM_TELEMETRY_SAVED_OBJECT_TYPE, + APM_TELEMETRY_SAVED_OBJECT_ID + ) + ).attributes; - return data; + return data; + } catch (err) { + if (err.output?.statusCode === 404) { + // task has not run yet, so no saved object to return + return {}; + } + throw err; + } }, isReady: () => true }); diff --git a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts index 01d6a2e2e81bc..572d73e368c7a 100644 --- a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts @@ -140,4 +140,21 @@ describe('dedupeConnections', () => { // @ts-ignore expect(nodejsNode?.data[SPAN_SUBTYPE]).toBe('aa'); }); + + it('processes connections without a matching "service" aggregation', () => { + const response: ServiceMapResponse = { + services: [javaService], + discoveredServices: [], + connections: [ + { + source: javaService, + destination: nodejsService + } + ] + }; + + const { elements } = dedupeConnections(response); + + expect(elements.length).toBe(3); + }); }); diff --git a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.ts b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.ts index d256f657bb778..e5d7c0b2de10c 100644 --- a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.ts +++ b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { isEqual, sortBy } from 'lodash'; +import { sortBy, pick, identity } from 'lodash'; import { ValuesType } from 'utility-types'; import { SERVICE_NAME, @@ -72,24 +72,35 @@ export function dedupeConnections(response: ServiceMapResponse) { return map; } - const service = - discoveredServices.find(({ from }) => { - if ('span.destination.service.resource' in node) { - return ( - node[SPAN_DESTINATION_SERVICE_RESOURCE] === - from[SPAN_DESTINATION_SERVICE_RESOURCE] - ); - } - return false; - })?.to ?? serviceNodes.find(serviceNode => serviceNode.id === node.id); - - if (service) { + const matchedService = discoveredServices.find(({ from }) => { + if ('span.destination.service.resource' in node) { + return ( + node[SPAN_DESTINATION_SERVICE_RESOURCE] === + from[SPAN_DESTINATION_SERVICE_RESOURCE] + ); + } + return false; + })?.to; + + let serviceName: string | undefined = matchedService?.[SERVICE_NAME]; + + if (!serviceName && 'service.name' in node) { + serviceName = node[SERVICE_NAME]; + } + + const matchedServiceNodes = serviceNodes.filter( + serviceNode => serviceNode[SERVICE_NAME] === serviceName + ); + + if (matchedServiceNodes.length) { return { ...map, - [node.id]: { - id: service[SERVICE_NAME], - ...service - } + [node.id]: Object.assign( + { + id: matchedServiceNodes[0][SERVICE_NAME] + }, + ...matchedServiceNodes.map(serviceNode => pick(serviceNode, identity)) + ) }; } @@ -138,7 +149,7 @@ export function dedupeConnections(response: ServiceMapResponse) { const dedupedNodes: typeof nodes = []; nodes.forEach(node => { - if (!dedupedNodes.find(dedupedNode => isEqual(node, dedupedNode))) { + if (!dedupedNodes.find(dedupedNode => node.id === dedupedNode.id)) { dedupedNodes.push(node); } }); diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index 1414f743e8a03..17b595385a84e 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -13,17 +13,13 @@ import { import { getServicesProjection } from '../../../common/projections/services'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; import { PromiseReturnType } from '../../../typings/common'; -import { - Setup, - SetupTimeRange, - SetupUIFilters -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { dedupeConnections } from './dedupe_connections'; import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; export interface IEnvOptions { - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; serviceName?: string; environment?: string; } @@ -77,7 +73,9 @@ async function getConnectionData({ async function getServicesData(options: IEnvOptions) { const { setup } = options; - const projection = getServicesProjection({ setup }); + const projection = getServicesProjection({ + setup: { ...setup, uiFiltersES: [] } + }); const { filter } = projection.body.query.bool; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts b/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts index 9cb1a61e1d76f..5e2ab82239d9f 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { uniq, take, sortBy } from 'lodash'; -import { - Setup, - SetupUIFilters, - SetupTimeRange -} from '../helpers/setup_request'; +import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { rangeFilter } from '../helpers/range_filter'; import { ESFilter } from '../../../typings/elasticsearch'; import { @@ -28,7 +24,7 @@ export async function getTraceSampleIds({ }: { serviceName?: string; environment?: string; - setup: Setup & SetupTimeRange & SetupUIFilters; + setup: Setup & SetupTimeRange; }) { const { start, end, client, indices, config } = setup; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/__snapshots__/get_transaction.test.ts.snap b/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap similarity index 59% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__test__/__snapshots__/get_transaction.test.ts.snap rename to x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap index 16a270fd6d25b..a91641b592526 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/__snapshots__/get_transaction.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap @@ -8,22 +8,35 @@ Object { "filter": Array [ Object { "term": Object { - "service.name": "foo", + "processor.event": "transaction", }, }, Object { - "term": Object { - "service.environment": "bar", + "terms": Object { + "service.name": Array [ + "foo", + ], }, }, Object { - "term": Object { - "transaction.type": "qux", + "terms": Object { + "service.environment": Array [ + "bar", + ], }, }, Object { - "term": Object { - "transaction.name": "baz", + "terms": Object { + "transaction.name": Array [ + "baz", + ], + }, + }, + Object { + "terms": Object { + "transaction.type": Array [ + "qux", + ], }, }, ], @@ -37,21 +50,6 @@ Object { `; exports[`custom link get transaction fetches without filter 1`] = ` -Object { - "body": Object { - "query": Object { - "bool": Object { - "filter": Array [], - }, - }, - }, - "index": "myIndex", - "size": 1, - "terminateAfter": 1, -} -`; - -exports[`custom link get transaction removes not listed filters from query 1`] = ` Object { "body": Object { "query": Object { @@ -59,7 +57,7 @@ Object { "filter": Array [ Object { "term": Object { - "service.name": "foo", + "processor.event": "transaction", }, }, ], diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/__snapshots__/list_custom_links.test.ts.snap b/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__test__/__snapshots__/list_custom_links.test.ts.snap rename to x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/create_or_update_custom_link.test.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts similarity index 72% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__test__/create_or_update_custom_link.test.ts rename to x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts index 624f01c649322..9bd6c78797605 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/create_or_update_custom_link.test.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createOrUpdateCustomLink } from '../create_or_update_custom_link'; -import { CustomLink } from '../custom_link_types'; -import { Setup } from '../../../helpers/setup_request'; -import { mockNow } from '../../../../../../../legacy/plugins/apm/public/utils/testHelpers'; +import { Setup } from '../../helpers/setup_request'; +import { mockNow } from '../../../../../../legacy/plugins/apm/public/utils/testHelpers'; +import { CustomLink } from '../../../../common/custom_link/custom_link_types'; +import { createOrUpdateCustomLink } from './create_or_update_custom_link'; describe('Create or Update Custom link', () => { const internalClientIndexMock = jest.fn(); @@ -23,8 +23,10 @@ describe('Create or Update Custom link', () => { const customLink = ({ label: 'foo', url: 'http://elastic.com/{{trace.id}}', - 'service.name': 'opbeans-java', - 'transaction.type': 'Request' + filters: [ + { key: 'service.name', value: 'opbeans-java' }, + { key: 'transaction.type', value: 'Request' } + ] } as unknown) as CustomLink; afterEach(() => { internalClientIndexMock.mockClear(); @@ -43,8 +45,8 @@ describe('Create or Update Custom link', () => { '@timestamp': 1570737000000, label: 'foo', url: 'http://elastic.com/{{trace.id}}', - 'service.name': 'opbeans-java', - 'transaction.type': 'Request' + 'service.name': ['opbeans-java'], + 'transaction.type': ['Request'] } }); }); @@ -62,8 +64,8 @@ describe('Create or Update Custom link', () => { '@timestamp': 1570737000000, label: 'foo', url: 'http://elastic.com/{{trace.id}}', - 'service.name': 'opbeans-java', - 'transaction.type': 'Request' + 'service.name': ['opbeans-java'], + 'transaction.type': ['Request'] } }); }); diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts index 5dce371e4f307..d24fd9988997a 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts @@ -4,11 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { pick } from 'lodash'; -import { FILTER_OPTIONS } from '../../../../common/custom_link_filter_options'; +import { + CustomLink, + CustomLinkES +} from '../../../../common/custom_link/custom_link_types'; import { APMIndexDocumentParams } from '../../helpers/es_client'; import { Setup } from '../../helpers/setup_request'; -import { CustomLink } from './custom_link_types'; +import { toESFormat } from './helper'; export async function createOrUpdateCustomLink({ customLinkId, @@ -21,14 +23,12 @@ export async function createOrUpdateCustomLink({ }) { const { internalClient, indices } = setup; - const params: APMIndexDocumentParams = { + const params: APMIndexDocumentParams = { refresh: true, index: indices.apmCustomLinkIndex, body: { '@timestamp': Date.now(), - label: customLink.label, - url: customLink.url, - ...pick(customLink, FILTER_OPTIONS) + ...toESFormat(customLink) } }; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.d.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.d.ts deleted file mode 100644 index edb9eb35b9029..0000000000000 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import * as t from 'io-ts'; -import { FilterOptions } from '../../../../common/custom_link_filter_options'; - -export type CustomLink = { - id?: string; - '@timestamp': number; - label: string; - url: string; -} & FilterOptions; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.ts new file mode 100644 index 0000000000000..f35a72ff840f9 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import * as t from 'io-ts'; +import { + SERVICE_NAME, + SERVICE_ENVIRONMENT, + TRANSACTION_NAME, + TRANSACTION_TYPE +} from '../../../../common/elasticsearch_fieldnames'; + +export interface CustomLinkES { + id?: string; + '@timestamp'?: number; + label: string; + url: string; + [SERVICE_NAME]?: string[]; + [SERVICE_ENVIRONMENT]?: string[]; + [TRANSACTION_NAME]?: string[]; + [TRANSACTION_TYPE]?: string[]; +} + +export const filterOptionsRt = t.partial({ + [SERVICE_NAME]: t.string, + [SERVICE_ENVIRONMENT]: t.string, + [TRANSACTION_NAME]: t.string, + [TRANSACTION_TYPE]: t.string +}); + +export const payloadRt = t.intersection([ + t.type({ + label: t.string, + url: t.string + }), + t.partial({ + id: t.string, + filters: t.array( + t.type({ + key: t.string, + value: t.string + }) + ) + }) +]); diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/get_transaction.test.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts similarity index 64% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__test__/get_transaction.test.ts rename to x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts index 4fc22298a476c..514e473b8e78c 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/get_transaction.test.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts @@ -6,29 +6,18 @@ import { inspectSearchParams, SearchParamsMock -} from '../../../../../../../legacy/plugins/apm/public/utils/testHelpers'; -import { getTransaction } from '../get_transaction'; -import { Setup } from '../../../helpers/setup_request'; +} from '../../../../../../legacy/plugins/apm/public/utils/testHelpers'; +import { getTransaction } from './get_transaction'; +import { Setup } from '../../helpers/setup_request'; import { SERVICE_NAME, TRANSACTION_TYPE, SERVICE_ENVIRONMENT, TRANSACTION_NAME -} from '../../../../../common/elasticsearch_fieldnames'; +} from '../../../../common/elasticsearch_fieldnames'; describe('custom link get transaction', () => { let mock: SearchParamsMock; - it('removes not listed filters from query', async () => { - mock = await inspectSearchParams(setup => - getTransaction({ - setup: (setup as unknown) as Setup, - // @ts-ignore ignoring the _debug is not part of filter options - filters: { _debug: true, [SERVICE_NAME]: 'foo' } - }) - ); - - expect(mock.params).toMatchSnapshot(); - }); it('fetches without filter', async () => { mock = await inspectSearchParams(setup => getTransaction({ diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts index 396a7cb29f014..4310349318783 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts @@ -3,35 +3,47 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { pick } from 'lodash'; -import { - FilterOptions, - FILTER_OPTIONS -} from '../../../../common/custom_link_filter_options'; +import * as t from 'io-ts'; +import { PROCESSOR_EVENT } from '../../../../common/elasticsearch_fieldnames'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { Setup } from '../../helpers/setup_request'; +import { ProcessorEvent } from '../../../../common/processor_event'; +import { filterOptionsRt } from './custom_link_types'; +import { splitFilterValueByComma } from './helper'; export async function getTransaction({ setup, filters = {} }: { setup: Setup; - filters?: FilterOptions; + filters?: t.TypeOf; }) { const { client, indices } = setup; - const esFilters = Object.entries(pick(filters, FILTER_OPTIONS)).map( - ([key, value]) => { - return { term: { [key]: value } }; - } - ); + const esFilters = Object.entries(filters) + // loops through the filters splitting the value by comma and removing white spaces + .map(([key, value]) => { + if (value) { + return { terms: { [key]: splitFilterValueByComma(value) } }; + } + }) + // removes filters without value + .filter(value => value); const params = { terminateAfter: 1, index: indices['apm_oss.transactionIndices'], size: 1, - body: { query: { bool: { filter: esFilters } } } + body: { + query: { + bool: { + filter: [ + { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, + ...esFilters + ] + } + } + } }; const resp = await client.search(params); return resp.hits.hits[0]?._source; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/helper.test.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/helper.test.ts new file mode 100644 index 0000000000000..6ebf02fcc72d1 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/helper.test.ts @@ -0,0 +1,137 @@ +/* + * 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 { fromESFormat, splitFilterValueByComma, toESFormat } from './helper'; + +describe('Custom link API helper', () => { + describe('splitFilterValueByComma', () => { + it('returns empty string when any value is provided', () => { + expect(splitFilterValueByComma('')).toEqual([]); + }); + it('removes white spaces', () => { + expect(splitFilterValueByComma('foo, bar, ')).toEqual(['foo', 'bar']); + expect(splitFilterValueByComma('foo , bar , baz, ')).toEqual([ + 'foo', + 'bar', + 'baz' + ]); + }); + it('doesnt slipt when comma is not found', () => { + expect(splitFilterValueByComma('foo bar')).toEqual(['foo bar']); + }); + it('doesnt slipt with dot', () => { + expect(splitFilterValueByComma('foo.bar. baz')).toEqual(['foo.bar. baz']); + }); + }); + + describe('fromESFormat', () => { + it('converts without filters', () => { + expect( + fromESFormat({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar' + }) + ).toEqual({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar', + filters: [] + }); + }); + it('converts with filters', () => { + expect( + fromESFormat({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar', + 'service.name': ['baz'], + 'transaction.name': ['quz', 'qux', 'quux'] + }) + ).toEqual({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar', + filters: [ + { key: 'service.name', value: 'baz' }, + { key: 'transaction.name', value: 'quz,qux,quux' } + ] + }); + }); + it('returns empty string when any filter value is provided', () => { + expect( + fromESFormat({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar', + 'service.name': [], + 'transaction.name': ['quz', 'qux', 'quux'] + }) + ).toEqual({ + id: '123', + '@timestamp': 455, + label: 'foo', + url: 'bar', + filters: [ + { key: 'service.name', value: '' }, + { key: 'transaction.name', value: 'quz,qux,quux' } + ] + }); + }); + }); + + describe('toESFormat', () => { + it('converts without filters', () => { + expect( + toESFormat({ + label: 'foo', + url: 'bar' + }) + ).toEqual({ + label: 'foo', + url: 'bar' + }); + }); + it('converts with filters', () => { + expect( + toESFormat({ + label: 'foo', + url: 'bar', + filters: [ + { key: 'service.name', value: 'baz' }, + { key: 'transaction.name', value: 'quz,qux,quux' } + ] + }) + ).toEqual({ + label: 'foo', + url: 'bar', + 'service.name': ['baz'], + 'transaction.name': ['quz', 'qux', 'quux'] + }); + }); + it('removes filters without key or value', () => { + expect( + toESFormat({ + label: 'foo', + url: 'bar', + filters: [ + { key: '', value: 'baz' }, + { key: 'service.name', value: '' }, + { key: 'transaction.name', value: 'quz,qux,quux' } + ] + }) + ).toEqual({ + label: 'foo', + url: 'bar', + 'transaction.name': ['quz', 'qux', 'quux'] + }); + }); + }); +}); diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/helper.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/helper.ts new file mode 100644 index 0000000000000..cfdbbdc21b43b --- /dev/null +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/helper.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { isEmpty } from 'lodash'; +import { + CustomLinkES, + CustomLink, + Filter, + FilterKey +} from '../../../../common/custom_link/custom_link_types'; + +export function fromESFormat(customLinkES: CustomLinkES): CustomLink { + const { id, label, url, '@timestamp': timestamp, ...filters } = customLinkES; + return { + id, + '@timestamp': timestamp, + label, + url, + filters: Object.entries(filters).map( + ([key, value]: [string, string[]]) => ({ + key: key as FilterKey, + value: isEmpty(value) ? '' : value.join() + }) + ) + }; +} + +export function toESFormat(customLink: CustomLink): CustomLinkES { + const { label, url, filters = [] } = customLink; + const ESFilters = filters + .filter(({ key, value }) => key && value) + .reduce((acc: Record, { key, value }) => { + acc[key] = splitFilterValueByComma(value); + return acc; + }, {}); + return { label, url, ...ESFilters }; +} + +export function splitFilterValueByComma(filterValue: Filter['value']) { + return filterValue + .split(',') + .map(v => v.trim()) + .filter(v => v); +} diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/list_custom_links.test.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts similarity index 79% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__test__/list_custom_links.test.ts rename to x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts index 5466225dc3211..45610e36786b7 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/__test__/list_custom_links.test.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { listCustomLinks } from '../list_custom_links'; +import { listCustomLinks } from './list_custom_links'; import { inspectSearchParams, SearchParamsMock -} from '../../../../../../../legacy/plugins/apm/public/utils/testHelpers'; -import { Setup } from '../../../helpers/setup_request'; +} from '../../../../../../legacy/plugins/apm/public/utils/testHelpers'; +import { Setup } from '../../helpers/setup_request'; import { SERVICE_NAME, TRANSACTION_NAME -} from '../../../../../common/elasticsearch_fieldnames'; +} from '../../../../common/elasticsearch_fieldnames'; describe('List Custom Links', () => { let mock: SearchParamsMock; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts index 67956ef3a60ce..bae313c8b6eef 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts @@ -3,20 +3,23 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { FilterOptions } from '../../../../common/custom_link_filter_options'; +import * as t from 'io-ts'; +import { + CustomLink, + CustomLinkES +} from '../../../../common/custom_link/custom_link_types'; import { Setup } from '../../helpers/setup_request'; -import { CustomLink } from './custom_link_types'; +import { fromESFormat } from './helper'; +import { filterOptionsRt } from './custom_link_types'; export async function listCustomLinks({ setup, filters = {} }: { setup: Setup; - filters?: FilterOptions; -}) { + filters?: t.TypeOf; +}): Promise { const { internalClient, indices } = setup; - const esFilters = Object.entries(filters).map(([key, value]) => { return { bool: { @@ -47,9 +50,12 @@ export async function listCustomLinks({ ] } }; - const resp = await internalClient.search(params); - return resp.hits.hits.map(item => ({ - id: item._id, - ...item._source - })); + const resp = await internalClient.search(params); + const customLinks = resp.hits.hits.map(item => + fromESFormat({ + id: item._id, + ...item._source + }) + ); + return customLinks; } diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index a61a61e3ccaac..6838717cbc6da 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -14,7 +14,7 @@ import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceMap } from '../lib/service_map/get_service_map'; import { getServiceMapServiceNodeInfo } from '../lib/service_map/get_service_map_service_node_info'; import { createRoute } from './create_route'; -import { rangeRt, uiFiltersRt } from './default_api_types'; +import { rangeRt } from './default_api_types'; export const serviceMapRoute = createRoute(() => ({ path: '/api/apm/service-map', @@ -24,7 +24,6 @@ export const serviceMapRoute = createRoute(() => ({ environment: t.string, serviceName: t.string }), - uiFiltersRt, rangeRt ]) }, diff --git a/x-pack/plugins/apm/server/routes/settings/custom_link.ts b/x-pack/plugins/apm/server/routes/settings/custom_link.ts index e11c1df9d4b16..428b96ad3982d 100644 --- a/x-pack/plugins/apm/server/routes/settings/custom_link.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link.ts @@ -4,51 +4,52 @@ * you may not use this file except in compliance with the Elastic License. */ import * as t from 'io-ts'; -import { FilterOptionsRt } from '../../../common/custom_link_filter_options'; -import { createRoute } from '../create_route'; +import { pick } from 'lodash'; +import { FILTER_OPTIONS } from '../../../common/custom_link/custom_link_filter_options'; import { setupRequest } from '../../lib/helpers/setup_request'; import { createOrUpdateCustomLink } from '../../lib/settings/custom_link/create_or_update_custom_link'; +import { + filterOptionsRt, + payloadRt +} from '../../lib/settings/custom_link/custom_link_types'; import { deleteCustomLink } from '../../lib/settings/custom_link/delete_custom_link'; -import { listCustomLinks } from '../../lib/settings/custom_link/list_custom_links'; import { getTransaction } from '../../lib/settings/custom_link/get_transaction'; +import { listCustomLinks } from '../../lib/settings/custom_link/list_custom_links'; +import { createRoute } from '../create_route'; export const customLinkTransactionRoute = createRoute(core => ({ path: '/api/apm/settings/custom_links/transaction', params: { - query: FilterOptionsRt + query: filterOptionsRt }, handler: async ({ context, request }) => { const setup = await setupRequest(context, request); - const { params } = context; - return await getTransaction({ setup, filters: params.query }); + const { query } = context.params; + // picks only the items listed in FILTER_OPTIONS + const filters = pick(query, FILTER_OPTIONS); + return await getTransaction({ setup, filters }); } })); export const listCustomLinksRoute = createRoute(core => ({ path: '/api/apm/settings/custom_links', params: { - query: FilterOptionsRt + query: filterOptionsRt }, handler: async ({ context, request }) => { const setup = await setupRequest(context, request); - const { params } = context; - return await listCustomLinks({ setup, filters: params.query }); + const { query } = context.params; + // picks only the items listed in FILTER_OPTIONS + const filters = pick(query, FILTER_OPTIONS); + return await listCustomLinks({ setup, filters }); } })); -const payload = t.intersection([ - t.type({ - label: t.string, - url: t.string - }), - FilterOptionsRt -]); - export const createCustomLinkRoute = createRoute(() => ({ method: 'POST', path: '/api/apm/settings/custom_links', params: { - body: payload + body: payloadRt }, options: { tags: ['access:apm', 'access:apm_write'] @@ -68,7 +69,7 @@ export const updateCustomLinkRoute = createRoute(() => ({ path: t.type({ id: t.string }), - body: payload + body: payloadRt }, options: { tags: ['access:apm', 'access:apm_write'] diff --git a/x-pack/plugins/apm/server/tutorial/index_pattern.json b/x-pack/plugins/apm/server/tutorial/index_pattern.json index 4052f4050a31b..ede9ba54681c0 100644 --- a/x-pack/plugins/apm/server/tutorial/index_pattern.json +++ b/x-pack/plugins/apm/server/tutorial/index_pattern.json @@ -1,7 +1,7 @@ { "attributes": { "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, diff --git a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts index d076008da9d8e..9695c331e0504 100644 --- a/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts +++ b/x-pack/plugins/apm/server/tutorial/instructions/apm_agent_instructions.ts @@ -437,7 +437,7 @@ export const createJsAgentInstructions = (apmServerUrl = '') => [ title: i18n.translate( 'xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title', { - defaultMessage: 'Enable Real User Monitoring support in APM server' + defaultMessage: 'Enable Real User Monitoring support in APM Server' } ), textPre: i18n.translate( diff --git a/x-pack/plugins/case/common/api/cases/case.ts b/x-pack/plugins/case/common/api/cases/case.ts index ee244dd205113..3c5d3405f395e 100644 --- a/x-pack/plugins/case/common/api/cases/case.ts +++ b/x-pack/plugins/case/common/api/cases/case.ts @@ -54,7 +54,11 @@ export const CaseAttributesRt = rt.intersection([ }), ]); -export const CaseRequestRt = CaseBasicRt; +export const CasePostRequestRt = rt.type({ + description: rt.string, + tags: rt.array(rt.string), + title: rt.string, +}); export const CaseExternalServiceRequestRt = CaseExternalServiceBasicRt; @@ -95,7 +99,7 @@ export const CasesFindResponseRt = rt.intersection([ ]); export const CasePatchRequestRt = rt.intersection([ - rt.partial(CaseRequestRt.props), + rt.partial(CaseBasicRt.props), rt.type({ id: rt.string, version: rt.string }), ]); @@ -157,7 +161,7 @@ export const ServiceConnectorCaseResponseRt = rt.intersection([ ]); export type CaseAttributes = rt.TypeOf; -export type CaseRequest = rt.TypeOf; +export type CasePostRequest = rt.TypeOf; export type CaseResponse = rt.TypeOf; export type CasesResponse = rt.TypeOf; export type CasesFindResponse = rt.TypeOf; diff --git a/x-pack/plugins/case/common/api/runtime_types.ts b/x-pack/plugins/case/common/api/runtime_types.ts index d5b858df38def..4717d7c3c48c4 100644 --- a/x-pack/plugins/case/common/api/runtime_types.ts +++ b/x-pack/plugins/case/common/api/runtime_types.ts @@ -4,22 +4,55 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fold } from 'fp-ts/lib/Either'; +import { either, fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; -import { Errors, Type } from 'io-ts'; +import * as rt from 'io-ts'; import { failure } from 'io-ts/lib/PathReporter'; type ErrorFactory = (message: string) => Error; export const createPlainError = (message: string) => new Error(message); -export const throwErrors = (createError: ErrorFactory) => (errors: Errors) => { +export const throwErrors = (createError: ErrorFactory) => (errors: rt.Errors) => { throw createError(failure(errors).join('\n')); }; export const decodeOrThrow = ( - runtimeType: Type, + runtimeType: rt.Type, createError: ErrorFactory = createPlainError ) => (inputValue: I) => pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity)); + +const getExcessProps = (props: rt.Props, r: Record): string[] => { + const ex: string[] = []; + for (const k of Object.keys(r)) { + if (!props.hasOwnProperty(k)) { + ex.push(k); + } + } + return ex; +}; + +export function excess>(codec: C): C { + const r = new rt.InterfaceType( + codec.name, + codec.is, + (i, c) => + either.chain(rt.UnknownRecord.validate(i, c), (s: Record) => { + const ex = getExcessProps(codec.props, s); + return ex.length > 0 + ? rt.failure( + i, + c, + `Invalid value ${JSON.stringify(i)} supplied to : ${ + codec.name + }, excess properties: ${JSON.stringify(ex)}` + ) + : codec.validate(i, c); + }), + codec.encode, + codec.props + ); + return r as any; +} diff --git a/x-pack/plugins/case/common/api/user.ts b/x-pack/plugins/case/common/api/user.ts index 651cd08f08a02..3adb78ccdac07 100644 --- a/x-pack/plugins/case/common/api/user.ts +++ b/x-pack/plugins/case/common/api/user.ts @@ -7,8 +7,8 @@ import * as rt from 'io-ts'; export const UserRT = rt.type({ - email: rt.union([rt.undefined, rt.string]), - full_name: rt.union([rt.undefined, rt.string]), + email: rt.union([rt.undefined, rt.null, rt.string]), + full_name: rt.union([rt.undefined, rt.null, rt.string]), username: rt.string, }); diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts index 5051f78a47cce..95cd66a9c51a2 100644 --- a/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts +++ b/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts @@ -29,7 +29,7 @@ export const createMockSavedObjectsRepository = ({ if (!result.length) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - return result[0]; + return result; } const result = caseSavedObject.filter(s => s.id === id); if (!result.length) { @@ -100,8 +100,9 @@ export const createMockSavedObjectsRepository = ({ if (attributes.description === 'Throw an error' || attributes.comment === 'Throw an error') { throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing'); } + if (type === CASE_COMMENT_SAVED_OBJECT) { - return { + const newCommentObj = { type, id: 'mock-comment', attributes, @@ -109,6 +110,8 @@ export const createMockSavedObjectsRepository = ({ updated_at: '2019-12-02T22:48:08.327Z', version: 'WzksMV0=', }; + caseCommentSavedObject = [...caseCommentSavedObject, newCommentObj]; + return newCommentObj; } return { type, @@ -124,6 +127,16 @@ export const createMockSavedObjectsRepository = ({ if (!caseCommentSavedObject.find(s => s.id === id)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } + caseCommentSavedObject = [ + ...caseCommentSavedObject, + { + id, + type, + updated_at: '2019-11-22T22:50:55.191Z', + version: 'WzE3LDFd', + attributes, + }, + ]; } else if (type === CASE_SAVED_OBJECT) { if (!caseSavedObject.find(s => s.id === id)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts index 941ac90f2e90e..1dfab165eccd7 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_all_comments.ts @@ -53,7 +53,7 @@ export function initDeleteAllCommentsApi({ caseService, router, userActionServic ), }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts index 8f05fbce391f8..b2022e6dec26d 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.test.ts @@ -21,7 +21,7 @@ describe('DELETE comment', () => { beforeAll(async () => { routeHandler = await createRoute(initDeleteCommentApi, 'delete'); }); - it(`deletes the comment. responds with 200`, async () => { + it(`deletes the comment. responds with 204`, async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/cases/{case_id}/comments/{comment_id}', method: 'delete', @@ -39,7 +39,7 @@ describe('DELETE comment', () => { ); const response = await routeHandler(theContext, request, kibanaResponseFactory); - expect(response.status).toEqual(200); + expect(response.status).toEqual(204); }); it(`returns an error when thrown from deleteComment service`, async () => { const request = httpServerMock.createKibanaRequest({ diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts index 44e57fc809e04..ff0729afed96a 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/delete_comment.ts @@ -64,7 +64,7 @@ export function initDeleteCommentApi({ caseService, router, userActionService }: ], }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.test.ts b/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.test.ts index 4e7e266f326a2..8d9906c2abe7f 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.test.ts @@ -43,7 +43,9 @@ describe('PATCH comment', () => { const response = await routeHandler(theContext, request, kibanaResponseFactory); expect(response.status).toEqual(200); - expect(response.payload.comment).toEqual('Update my comment'); + expect(response.payload.comments[response.payload.comments.length - 1].comment).toEqual( + 'Update my comment' + ); }); it(`Fails with 409 if version does not match`, async () => { diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.ts b/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.ts index c67ad1bdaea71..3b38afc02ed81 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/patch_comment.ts @@ -10,11 +10,11 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { CommentPatchRequestRt, CommentResponseRt, throwErrors } from '../../../../../common/api'; +import { CommentPatchRequestRt, CaseResponseRt, throwErrors } from '../../../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../../saved_object_types'; import { buildCommentUserActionItem } from '../../../../services/user_actions/helpers'; import { RouteDeps } from '../../types'; -import { escapeHatch, wrapError, flattenCommentSavedObject } from '../../utils'; +import { escapeHatch, wrapError, flattenCaseSavedObject } from '../../utils'; export function initPatchCommentApi({ caseService, router, userActionService }: RouteDeps) { router.patch( @@ -30,11 +30,17 @@ export function initPatchCommentApi({ caseService, router, userActionService }: async (context, request, response) => { try { const client = context.core.savedObjects.client; + const caseId = request.params.case_id; const query = pipe( CommentPatchRequestRt.decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); + const myCase = await caseService.getCase({ + client, + caseId, + }); + const myComment = await caseService.getComment({ client, commentId: query.id, @@ -45,10 +51,8 @@ export function initPatchCommentApi({ caseService, router, userActionService }: } const caseRef = myComment.references.find(c => c.type === CASE_SAVED_OBJECT); - if (caseRef == null || (caseRef != null && caseRef.id !== request.params.case_id)) { - throw Boom.notFound( - `This comment ${query.id} does not exist in ${request.params.case_id}).` - ); + if (caseRef == null || (caseRef != null && caseRef.id !== caseId)) { + throw Boom.notFound(`This comment ${query.id} does not exist in ${caseId}).`); } if (query.version !== myComment.version) { @@ -59,40 +63,77 @@ export function initPatchCommentApi({ caseService, router, userActionService }: const { username, full_name, email } = await caseService.getUser({ request, response }); const updatedDate = new Date().toISOString(); - const updatedComment = await caseService.patchComment({ + const [updatedComment, updatedCase] = await Promise.all([ + caseService.patchComment({ + client, + commentId: query.id, + updatedAttributes: { + comment: query.comment, + updated_at: updatedDate, + updated_by: { email, full_name, username }, + }, + version: query.version, + }), + caseService.patchCase({ + client, + caseId, + updatedAttributes: { + updated_at: updatedDate, + updated_by: { username, full_name, email }, + }, + version: myCase.version, + }), + ]); + + const totalCommentsFindByCases = await caseService.getAllCaseComments({ client, - commentId: query.id, - updatedAttributes: { - comment: query.comment, - updated_at: updatedDate, - updated_by: { email, full_name, username }, + caseId, + options: { + fields: [], + page: 1, + perPage: 1, }, - version: query.version, }); - await userActionService.postUserActions({ - client, - actions: [ - buildCommentUserActionItem({ - action: 'update', - actionAt: updatedDate, - actionBy: { username, full_name, email }, - caseId: request.params.case_id, - commentId: updatedComment.id, - fields: ['comment'], - newValue: query.comment, - oldValue: myComment.attributes.comment, - }), - ], - }); + const [comments] = await Promise.all([ + caseService.getAllCaseComments({ + client, + caseId: request.params.case_id, + options: { + fields: [], + page: 1, + perPage: totalCommentsFindByCases.total, + }, + }), + userActionService.postUserActions({ + client, + actions: [ + buildCommentUserActionItem({ + action: 'update', + actionAt: updatedDate, + actionBy: { username, full_name, email }, + caseId: request.params.case_id, + commentId: updatedComment.id, + fields: ['comment'], + newValue: query.comment, + oldValue: myComment.attributes.comment, + }), + ], + }), + ]); return response.ok({ - body: CommentResponseRt.encode( - flattenCommentSavedObject({ - ...updatedComment, - attributes: { ...myComment.attributes, ...updatedComment.attributes }, - references: myComment.references, - }) + body: CaseResponseRt.encode( + flattenCaseSavedObject( + { + ...myCase, + ...updatedCase, + attributes: { ...myCase.attributes, ...updatedCase.attributes }, + version: updatedCase.version ?? myCase.version, + references: myCase.references, + }, + comments.saved_objects + ) ), }); } catch (error) { diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.test.ts b/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.test.ts index e51ec7c894d08..af6f8bf223ee5 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.test.ts @@ -42,7 +42,9 @@ describe('POST comment', () => { const response = await routeHandler(theContext, request, kibanaResponseFactory); expect(response.status).toEqual(200); - expect(response.payload.id).toEqual('mock-comment'); + expect(response.payload.comments[response.payload.comments.length - 1].id).toEqual( + 'mock-comment' + ); }); it(`Returns an error if the case does not exist`, async () => { const request = httpServerMock.createKibanaRequest({ diff --git a/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.ts b/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.ts index 2410505872a3a..70405af26f576 100644 --- a/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.ts +++ b/x-pack/plugins/case/server/routes/api/cases/comments/post_comment.ts @@ -10,15 +10,10 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { CommentRequestRt, CommentResponseRt, throwErrors } from '../../../../../common/api'; +import { CaseResponseRt, CommentRequestRt, excess, throwErrors } from '../../../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../../saved_object_types'; import { buildCommentUserActionItem } from '../../../../services/user_actions/helpers'; -import { - escapeHatch, - transformNewComment, - wrapError, - flattenCommentSavedObject, -} from '../../utils'; +import { escapeHatch, transformNewComment, wrapError, flattenCaseSavedObject } from '../../utils'; import { RouteDeps } from '../../types'; export function initPostCommentApi({ caseService, router, userActionService }: RouteDeps) { @@ -35,54 +30,98 @@ export function initPostCommentApi({ caseService, router, userActionService }: R async (context, request, response) => { try { const client = context.core.savedObjects.client; + const caseId = request.params.case_id; const query = pipe( - CommentRequestRt.decode(request.body), + excess(CommentRequestRt).decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); const myCase = await caseService.getCase({ client, - caseId: request.params.case_id, + caseId, }); const { username, full_name, email } = await caseService.getUser({ request, response }); const createdDate = new Date().toISOString(); - const newComment = await caseService.postNewComment({ - client, - attributes: transformNewComment({ - createdDate, - ...query, - username, - full_name, - email, + const [newComment, updatedCase] = await Promise.all([ + caseService.postNewComment({ + client, + attributes: transformNewComment({ + createdDate, + ...query, + username, + full_name, + email, + }), + references: [ + { + type: CASE_SAVED_OBJECT, + name: `associated-${CASE_SAVED_OBJECT}`, + id: myCase.id, + }, + ], }), - references: [ - { - type: CASE_SAVED_OBJECT, - name: `associated-${CASE_SAVED_OBJECT}`, - id: myCase.id, + caseService.patchCase({ + client, + caseId, + updatedAttributes: { + updated_at: createdDate, + updated_by: { username, full_name, email }, }, - ], - }); + version: myCase.version, + }), + ]); - await userActionService.postUserActions({ + const totalCommentsFindByCases = await caseService.getAllCaseComments({ client, - actions: [ - buildCommentUserActionItem({ - action: 'create', - actionAt: createdDate, - actionBy: { username, full_name, email }, - caseId: myCase.id, - commentId: newComment.id, - fields: ['comment'], - newValue: query.comment, - }), - ], + caseId, + options: { + fields: [], + page: 1, + perPage: 1, + }, }); + const [comments] = await Promise.all([ + caseService.getAllCaseComments({ + client, + caseId, + options: { + fields: [], + page: 1, + perPage: totalCommentsFindByCases.total, + }, + }), + userActionService.postUserActions({ + client, + actions: [ + buildCommentUserActionItem({ + action: 'create', + actionAt: createdDate, + actionBy: { username, full_name, email }, + caseId: myCase.id, + commentId: newComment.id, + fields: ['comment'], + newValue: query.comment, + }), + ], + }), + ]); + return response.ok({ - body: CommentResponseRt.encode(flattenCommentSavedObject(newComment)), + body: CaseResponseRt.encode( + flattenCaseSavedObject( + { + ...myCase, + ...updatedCase, + attributes: { ...myCase.attributes, ...updatedCase.attributes }, + version: updatedCase.version ?? myCase.version, + references: myCase.references, + }, + comments.saved_objects + ) + ), }); } catch (error) { return response.customError(wrapError(error)); diff --git a/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts b/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts index cee705694f21d..c5be6f78a1570 100644 --- a/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/delete_cases.test.ts @@ -22,7 +22,7 @@ describe('DELETE case', () => { beforeAll(async () => { routeHandler = await createRoute(initDeleteCasesApi, 'delete'); }); - it(`deletes the case. responds with 200`, async () => { + it(`deletes the case. responds with 204`, async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/cases', method: 'delete', @@ -39,7 +39,7 @@ describe('DELETE case', () => { ); const response = await routeHandler(theContext, request, kibanaResponseFactory); - expect(response.status).toEqual(200); + expect(response.status).toEqual(204); }); it(`returns an error when thrown from deleteCase service`, async () => { const request = httpServerMock.createKibanaRequest({ diff --git a/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts b/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts index 8b0384c12edce..0214017ae5c29 100644 --- a/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts +++ b/x-pack/plugins/case/server/routes/api/cases/delete_cases.ts @@ -70,7 +70,7 @@ export function initDeleteCasesApi({ caseService, router, userActionService }: R ), }); - return response.ok({ body: 'true' }); + return response.noContent(); } catch (error) { return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/case/server/routes/api/cases/helpers.ts b/x-pack/plugins/case/server/routes/api/cases/helpers.ts index 747b5195da7ec..46c2209d79f7d 100644 --- a/x-pack/plugins/case/server/routes/api/cases/helpers.ts +++ b/x-pack/plugins/case/server/routes/api/cases/helpers.ts @@ -62,11 +62,14 @@ export const getCaseToUpdate = ( Object.entries(queryCase).reduce( (acc, [key, value]) => { const currentValue = get(currentCase, key); - if (isTwoArraysDifference(value, currentValue)) { - return { - ...acc, - [key]: value, - }; + if (Array.isArray(currentValue) && Array.isArray(value)) { + if (isTwoArraysDifference(value, currentValue)) { + return { + ...acc, + [key]: value, + }; + } + return acc; } else if (currentValue != null && value !== currentValue) { return { ...acc, diff --git a/x-pack/plugins/case/server/routes/api/cases/patch_cases.ts b/x-pack/plugins/case/server/routes/api/cases/patch_cases.ts index 3d0b7bc79f88b..c36ea8964dc80 100644 --- a/x-pack/plugins/case/server/routes/api/cases/patch_cases.ts +++ b/x-pack/plugins/case/server/routes/api/cases/patch_cases.ts @@ -11,9 +11,10 @@ import { identity } from 'fp-ts/lib/function'; import { CasesPatchRequestRt, - throwErrors, CasesResponseRt, CasePatchRequest, + excess, + throwErrors, } from '../../../../common/api'; import { escapeHatch, wrapError, flattenCaseSavedObject } from '../utils'; import { RouteDeps } from '../types'; @@ -32,7 +33,7 @@ export function initPatchCasesApi({ caseService, router, userActionService }: Ro try { const client = context.core.savedObjects.client; const query = pipe( - CasesPatchRequestRt.decode(request.body), + excess(CasesPatchRequestRt).decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); const myCases = await caseService.getCases({ @@ -116,6 +117,7 @@ export function initPatchCasesApi({ caseService, router, userActionService }: Ro ...updatedCase, attributes: { ...myCase.attributes, ...updatedCase?.attributes }, references: myCase.references, + version: updatedCase?.version ?? myCase.version, }); }); diff --git a/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts b/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts index 5b716e5a2d490..96ce3c1a7eead 100644 --- a/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts +++ b/x-pack/plugins/case/server/routes/api/cases/post_case.test.ts @@ -27,7 +27,6 @@ describe('POST cases', () => { body: { description: 'This is a brand new case of a bad meanie defacing data', title: 'Super Bad Security Issue', - status: 'open', tags: ['defacement'], }, }); @@ -43,6 +42,28 @@ describe('POST cases', () => { expect(response.payload.id).toEqual('mock-it'); expect(response.payload.created_by.username).toEqual('awesome'); }); + + it(`Error if you passing status for a new case`, async () => { + const request = httpServerMock.createKibanaRequest({ + path: '/api/cases', + method: 'post', + body: { + description: 'This is a brand new case of a bad meanie defacing data', + title: 'Super Bad Security Issue', + status: 'open', + tags: ['defacement'], + }, + }); + + const theContext = createRouteContext( + createMockSavedObjectsRepository({ + caseSavedObject: mockCases, + }) + ); + + const response = await routeHandler(theContext, request, kibanaResponseFactory); + expect(response.status).toEqual(400); + }); it(`Returns an error if postNewCase throws`, async () => { const request = httpServerMock.createKibanaRequest({ path: '/api/cases', @@ -50,7 +71,6 @@ describe('POST cases', () => { body: { description: 'Throw an error', title: 'Super Bad Security Issue', - status: 'open', tags: ['error'], }, }); @@ -74,7 +94,6 @@ describe('POST cases', () => { body: { description: 'This is a brand new case of a bad meanie defacing data', title: 'Super Bad Security Issue', - status: 'open', tags: ['defacement'], }, }); diff --git a/x-pack/plugins/case/server/routes/api/cases/post_case.ts b/x-pack/plugins/case/server/routes/api/cases/post_case.ts index 75be68013bcd4..239b8bfdf9b29 100644 --- a/x-pack/plugins/case/server/routes/api/cases/post_case.ts +++ b/x-pack/plugins/case/server/routes/api/cases/post_case.ts @@ -11,7 +11,7 @@ import { identity } from 'fp-ts/lib/function'; import { flattenCaseSavedObject, transformNewCase, wrapError, escapeHatch } from '../utils'; -import { CaseRequestRt, throwErrors, CaseResponseRt } from '../../../../common/api'; +import { CasePostRequestRt, throwErrors, excess, CaseResponseRt } from '../../../../common/api'; import { buildCaseUserActionItem } from '../../../services/user_actions/helpers'; import { RouteDeps } from '../types'; @@ -27,7 +27,7 @@ export function initPostCaseApi({ caseService, router, userActionService }: Rout try { const client = context.core.savedObjects.client; const query = pipe( - CaseRequestRt.decode(request.body), + excess(CasePostRequestRt).decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); diff --git a/x-pack/plugins/case/server/routes/api/cases/push_case.ts b/x-pack/plugins/case/server/routes/api/cases/push_case.ts index 6ae3df180d9e4..1b24904ce03b7 100644 --- a/x-pack/plugins/case/server/routes/api/cases/push_case.ts +++ b/x-pack/plugins/case/server/routes/api/cases/push_case.ts @@ -15,6 +15,7 @@ import { flattenCaseSavedObject, wrapError, escapeHatch } from '../utils'; import { CaseExternalServiceRequestRt, CaseResponseRt, throwErrors } from '../../../../common/api'; import { buildCaseUserActionItem } from '../../../services/user_actions/helpers'; import { RouteDeps } from '../types'; +import { CASE_COMMENT_SAVED_OBJECT } from '../../../saved_object_types'; export function initPushCaseUserActionApi({ caseConfigureService, @@ -53,6 +54,7 @@ export function initPushCaseUserActionApi({ client, caseId, options: { + filter: `not ${CASE_COMMENT_SAVED_OBJECT}.attributes.pushed_at: *`, fields: [], page: 1, perPage: 1, @@ -70,6 +72,7 @@ export function initPushCaseUserActionApi({ client, caseId, options: { + filter: `not ${CASE_COMMENT_SAVED_OBJECT}.attributes.pushed_at: *`, fields: [], page: 1, perPage: totalCommentsFindByCases.total, @@ -140,7 +143,6 @@ export function initPushCaseUserActionApi({ ], }), ]); - return response.ok({ body: CaseResponseRt.encode( flattenCaseSavedObject( diff --git a/x-pack/plugins/case/server/routes/api/utils.ts b/x-pack/plugins/case/server/routes/api/utils.ts index 9d90eb8ef4a6d..822d6d70c7d61 100644 --- a/x-pack/plugins/case/server/routes/api/utils.ts +++ b/x-pack/plugins/case/server/routes/api/utils.ts @@ -14,7 +14,7 @@ import { } from 'kibana/server'; import { - CaseRequest, + CasePostRequest, CaseResponse, CasesFindResponse, CaseAttributes, @@ -35,17 +35,18 @@ export const transformNewCase = ({ createdDate: string; email?: string; full_name?: string; - newCase: CaseRequest; + newCase: CasePostRequest; username: string; }): CaseAttributes => ({ + ...newCase, closed_at: null, closed_by: null, created_at: createdDate, created_by: { email, full_name, username }, external_service: null, + status: 'open', updated_at: null, updated_by: null, - ...newCase, }); interface NewCommentArgs { diff --git a/x-pack/plugins/case/server/saved_object_types/comments.ts b/x-pack/plugins/case/server/saved_object_types/comments.ts index 8776dd39b11fa..73b1852bafe58 100644 --- a/x-pack/plugins/case/server/saved_object_types/comments.ts +++ b/x-pack/plugins/case/server/saved_object_types/comments.ts @@ -44,6 +44,9 @@ export const caseCommentSavedObjectType: SavedObjectsType = { full_name: { type: 'keyword', }, + email: { + type: 'keyword', + }, }, }, updated_at: { diff --git a/x-pack/plugins/case/server/services/index.ts b/x-pack/plugins/case/server/services/index.ts index 09d726228d309..52f41aae293ab 100644 --- a/x-pack/plugins/case/server/services/index.ts +++ b/x-pack/plugins/case/server/services/index.ts @@ -75,13 +75,13 @@ interface PatchCasesArgs extends ClientArgs { } interface UpdateCommentArgs extends ClientArgs { commentId: string; - updatedAttributes: Partial; + updatedAttributes: Partial; version?: string; } interface PatchComment { commentId: string; - updatedAttributes: Partial; + updatedAttributes: Partial; version?: string; } diff --git a/x-pack/plugins/case/server/services/user_actions/helpers.ts b/x-pack/plugins/case/server/services/user_actions/helpers.ts index 59d193f0f30d5..95d35d5a57a57 100644 --- a/x-pack/plugins/case/server/services/user_actions/helpers.ts +++ b/x-pack/plugins/case/server/services/user_actions/helpers.ts @@ -31,8 +31,8 @@ export const transformNewUserAction = ({ actionField: UserActionField; action: UserAction; actionAt: string; - email?: string; - full_name?: string; + email?: string | null; + full_name?: string | null; newValue?: string | null; oldValue?: string | null; username: string; diff --git a/x-pack/plugins/advanced_ui_actions/public/services/index.ts b/x-pack/plugins/console_extensions/server/lib/spec_definitions/js/index.ts similarity index 85% rename from x-pack/plugins/advanced_ui_actions/public/services/index.ts rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/js/index.ts index 0f8b4c8d8f409..bc9fbec194d0c 100644 --- a/x-pack/plugins/advanced_ui_actions/public/services/index.ts +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/js/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './action_factory_service'; +export { processors } from './ingest'; diff --git a/x-pack/plugins/console_extensions/server/spec/ingest/index.ts b/x-pack/plugins/console_extensions/server/lib/spec_definitions/js/ingest.ts similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/ingest/index.ts rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/js/ingest.ts diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.delete.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.delete.json new file mode 100644 index 0000000000000..a0be8f05e7722 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.delete.json @@ -0,0 +1,11 @@ +{ + "async_search.delete": { + "methods": [ + "DELETE" + ], + "patterns": [ + "_async_search/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/async-search.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.get.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.get.json new file mode 100644 index 0000000000000..09f4520d580e3 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.get.json @@ -0,0 +1,16 @@ +{ + "async_search.get": { + "url_params": { + "wait_for_completion": "", + "keep_alive": "", + "typed_keys": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_async_search/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/async-search.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.submit.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.submit.json new file mode 100644 index 0000000000000..83fb7c0fe75ad --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/async_search.submit.json @@ -0,0 +1,70 @@ +{ + "async_search.submit": { + "url_params": { + "wait_for_completion": "", + "clean_on_completion": "__flag__", + "keep_alive": "", + "batched_reduce_size": "", + "request_cache": "__flag__", + "analyzer": "", + "analyze_wildcard": "__flag__", + "default_operator": [ + "AND", + "OR" + ], + "df": "", + "explain": "__flag__", + "stored_fields": [], + "docvalue_fields": [], + "from": "0", + "ignore_unavailable": "__flag__", + "ignore_throttled": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "lenient": "__flag__", + "preference": "random", + "q": "", + "routing": [], + "search_type": [ + "query_then_fetch", + "dfs_query_then_fetch" + ], + "size": "10", + "sort": [], + "_source": [], + "_source_excludes": [], + "_source_includes": [], + "terminate_after": "", + "stats": [], + "suggest_field": "", + "suggest_mode": [ + "missing", + "popular", + "always" + ], + "suggest_size": "", + "suggest_text": "", + "timeout": "", + "track_scores": "__flag__", + "track_total_hits": "__flag__", + "allow_partial_search_results": "__flag__", + "typed_keys": "__flag__", + "version": "__flag__", + "seq_no_primary_term": "__flag__", + "max_concurrent_shard_requests": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_async_search", + "{indices}/_async_search" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/async-search.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/autoscaling.get_autoscaling_decision.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/autoscaling.get_autoscaling_decision.json new file mode 100644 index 0000000000000..241075f4ca538 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/autoscaling.get_autoscaling_decision.json @@ -0,0 +1,11 @@ +{ + "autoscaling.get_autoscaling_decision": { + "methods": [ + "GET" + ], + "patterns": [ + "_autoscaling/decision" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/autoscaling-get-autoscaling-decision.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json new file mode 100644 index 0000000000000..e2ddaefd87dea --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_data_frame_analytics.json @@ -0,0 +1,42 @@ +{ + "cat.ml_data_frame_analytics": { + "url_params": { + "allow_no_match": "__flag__", + "bytes": [ + "b", + "k", + "kb", + "m", + "mb", + "g", + "gb", + "t", + "tb", + "p", + "pb" + ], + "format": "", + "h": [], + "help": "__flag__", + "s": [], + "time": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/ml/data_frame/analytics", + "_cat/ml/data_frame/analytics/{id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-dfanalytics.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json new file mode 100644 index 0000000000000..04f4e45782e1f --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_datafeeds.json @@ -0,0 +1,29 @@ +{ + "cat.ml_datafeeds": { + "url_params": { + "allow_no_datafeeds": "__flag__", + "format": "", + "h": [], + "help": "__flag__", + "s": [], + "time": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/ml/datafeeds", + "_cat/ml/datafeeds/{datafeed_id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-datafeeds.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_jobs.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_jobs.json new file mode 100644 index 0000000000000..2f7e03e564b5d --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_jobs.json @@ -0,0 +1,42 @@ +{ + "cat.ml_jobs": { + "url_params": { + "allow_no_jobs": "__flag__", + "bytes": [ + "b", + "k", + "kb", + "m", + "mb", + "g", + "gb", + "t", + "tb", + "p", + "pb" + ], + "format": "", + "h": [], + "help": "__flag__", + "s": [], + "time": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/ml/anomaly_detectors", + "_cat/ml/anomaly_detectors/{job_id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/cat-anomaly-detectors.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json new file mode 100644 index 0000000000000..9ff12e8bf6c57 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/cat.ml_trained_models.json @@ -0,0 +1,44 @@ +{ + "cat.ml_trained_models": { + "url_params": { + "allow_no_match": "__flag__", + "from": 0, + "size": 0, + "bytes": [ + "b", + "k", + "kb", + "m", + "mb", + "g", + "gb", + "t", + "tb", + "p", + "pb" + ], + "format": "", + "h": [], + "help": "__flag__", + "s": [], + "time": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/ml/trained_models", + "_cat/ml/trained_models/{model_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-trained-model.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.delete_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.delete_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.delete_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.follow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.follow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.follow_info.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow_info.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.follow_info.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow_info.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.follow_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow_stats.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.follow_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.follow_stats.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.forget_follower.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.forget_follower.json similarity index 53% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.forget_follower.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.forget_follower.json index aa9a42c54dff4..f2aabe9ef4257 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ccr.forget_follower.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.forget_follower.json @@ -6,6 +6,6 @@ "patterns": [ "{indices}/_ccr/forget_follower" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-post-forget-follower.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.get_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.get_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.get_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.pause_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.pause_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.pause_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.pause_follow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.pause_follow.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.pause_follow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.pause_follow.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.put_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.put_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.put_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.resume_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.resume_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.resume_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.resume_follow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.resume_follow.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.resume_follow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.resume_follow.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.stats.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.stats.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ccr.unfollow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.unfollow.json similarity index 52% rename from x-pack/plugins/console_extensions/server/spec/generated/ccr.unfollow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.unfollow.json index 92759d8222c63..37530bf373c42 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ccr.unfollow.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ccr.unfollow.json @@ -6,6 +6,6 @@ "patterns": [ "{indices}/_ccr/unfollow" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-post-unfollow.html" } } diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.delete_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.delete_policy.json new file mode 100644 index 0000000000000..d7615779bc566 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.delete_policy.json @@ -0,0 +1,11 @@ +{ + "enrich.delete_policy": { + "methods": [ + "DELETE" + ], + "patterns": [ + "_enrich/policy/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-enrich-policy-api.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/enrich.execute_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.execute_policy.json similarity index 61% rename from x-pack/plugins/console_extensions/server/spec/generated/enrich.execute_policy.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.execute_policy.json index 542b709c08ec6..a7d6d99753c2e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/enrich.execute_policy.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.execute_policy.json @@ -8,6 +8,7 @@ ], "patterns": [ "_enrich/policy/{name}/_execute" - ] + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/execute-enrich-policy-api.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/enrich.get_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.get_policy.json similarity index 53% rename from x-pack/plugins/console_extensions/server/spec/generated/enrich.get_policy.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.get_policy.json index b59bf72670b6d..9b91d899d099f 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/enrich.get_policy.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.get_policy.json @@ -6,6 +6,7 @@ "patterns": [ "_enrich/policy/{name}", "_enrich/policy" - ] + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-enrich-policy-api.html" } } diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.put_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.put_policy.json new file mode 100644 index 0000000000000..5ff0ab55aef80 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.put_policy.json @@ -0,0 +1,11 @@ +{ + "enrich.put_policy": { + "methods": [ + "PUT" + ], + "patterns": [ + "_enrich/policy/{name}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/put-enrich-policy-api.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.stats.json new file mode 100644 index 0000000000000..6cdd037a21216 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/enrich.stats.json @@ -0,0 +1,11 @@ +{ + "enrich.stats": { + "methods": [ + "GET" + ], + "patterns": [ + "_enrich/_stats" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-stats-api.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/graph.explore.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/graph.explore.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/graph.explore.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/graph.explore.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.delete_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.delete_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.delete_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.delete_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.explain_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.explain_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.explain_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.get_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.get_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.get_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.get_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.get_status.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.get_status.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.get_status.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.get_status.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.move_to_step.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.move_to_step.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.move_to_step.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.move_to_step.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.put_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.put_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.put_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.put_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.remove_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.remove_policy.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.remove_policy.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.remove_policy.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.retry.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.retry.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.retry.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.retry.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.set_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.set_policy.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.set_policy.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.set_policy.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.start.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.start.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.start.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.start.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ilm.stop.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.stop.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ilm.stop.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ilm.stop.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/indices.freeze.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.freeze.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/indices.freeze.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.freeze.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/indices.reload_search_analyzers.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/indices.reload_search_analyzers.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.reload_search_analyzers.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/indices.unfreeze.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.unfreeze.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/indices.unfreeze.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/indices.unfreeze.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.delete.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.delete.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.delete.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.delete.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.get.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.get.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.get_basic_status.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get_basic_status.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.get_basic_status.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get_basic_status.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.get_trial_status.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get_trial_status.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.get_trial_status.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.get_trial_status.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.post.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.post.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.post_start_basic.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post_start_basic.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.post_start_basic.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post_start_basic.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/license.post_start_trial.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post_start_trial.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/license.post_start_trial.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/license.post_start_trial.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/migration.deprecations.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.deprecations.json similarity index 59% rename from x-pack/plugins/console_extensions/server/spec/generated/migration.deprecations.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.deprecations.json index dce5244ea40ac..597791a2439c2 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/migration.deprecations.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.deprecations.json @@ -7,6 +7,6 @@ "_migration/deprecations", "{indices}/_migration/deprecations" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-deprecation.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-deprecation.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/migration.get_assistance.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.get_assistance.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/migration.get_assistance.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.get_assistance.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/migration.upgrade.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.upgrade.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/migration.upgrade.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/migration.upgrade.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.close_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.close_job.json similarity index 70% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.close_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.close_job.json index 310b0d125b1f9..b0f2c6489b30e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.close_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.close_job.json @@ -11,6 +11,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/_close" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-close-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-close-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar_event.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar_event.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar_event.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar_event.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_calendar_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_calendar_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_data_frame_analytics.json similarity index 64% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_data_frame_analytics.json index c3d7048406ef6..2e4593f339212 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_data_frame_analytics.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_data_frame_analytics.json @@ -9,6 +9,6 @@ "patterns": [ "_ml/data_frame/analytics/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/delete-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_datafeed.json similarity index 62% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_datafeed.json index 7c7f3c40f23bb..0836a844eb0f5 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_datafeed.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_datafeed.json @@ -9,6 +9,6 @@ "patterns": [ "_ml/datafeeds/{datafeed_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-datafeed.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-datafeed.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_expired_data.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_expired_data.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_expired_data.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_expired_data.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_filter.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_filter.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_filter.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_filter.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_forecast.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_forecast.json similarity index 72% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_forecast.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_forecast.json index 971a761cc77e9..acaddfba74338 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_forecast.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_forecast.json @@ -11,6 +11,6 @@ "_ml/anomaly_detectors/{job_id}/_forecast", "_ml/anomaly_detectors/{job_id}/_forecast/{forecast_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-forecast.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-forecast.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_job.json similarity index 68% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_job.json index ab518071bf765..aa79a4c195ebe 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_job.json @@ -10,6 +10,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_model_snapshot.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_model_snapshot.json similarity index 60% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_model_snapshot.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_model_snapshot.json index 53d45bf0498ab..af4a7a6d68498 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_model_snapshot.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_model_snapshot.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-snapshot.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-delete-snapshot.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.delete_trained_model.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.delete_trained_model.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.delete_trained_model.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.evaluate_data_frame.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.evaluate_data_frame.json similarity index 54% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.evaluate_data_frame.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.evaluate_data_frame.json index c4523a8b41604..40f913383424d 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.evaluate_data_frame.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.evaluate_data_frame.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/data_frame/_evaluate" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/evaluate-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/evaluate-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.explain_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.explain_data_frame_analytics.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.explain_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.explain_data_frame_analytics.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.find_file_structure.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.find_file_structure.json similarity index 84% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.find_file_structure.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.find_file_structure.json index ec51a62c4f901..6e7163ae2b740 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.find_file_structure.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.find_file_structure.json @@ -27,6 +27,6 @@ "patterns": [ "_ml/find_file_structure" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-find-file-structure.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-find-file-structure.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.flush_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.flush_job.json similarity index 72% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.flush_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.flush_job.json index 2f496003a2834..38f8cd7e9b90b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.flush_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.flush_job.json @@ -13,6 +13,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/_flush" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-flush-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-flush-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.forecast.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.forecast.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.forecast.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.forecast.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_buckets.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_buckets.json similarity index 81% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_buckets.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_buckets.json index 2cbcb9d6155ec..b7c864064496e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_buckets.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_buckets.json @@ -19,6 +19,6 @@ "_ml/anomaly_detectors/{job_id}/results/buckets/{timestamp}", "_ml/anomaly_detectors/{job_id}/results/buckets" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-bucket.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-bucket.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_calendar_events.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_calendar_events.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_calendar_events.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_calendar_events.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_calendars.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_calendars.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_calendars.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_calendars.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_categories.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_categories.json similarity index 73% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_categories.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_categories.json index 357a7b7fb0ccc..64edb196bb366 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_categories.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_categories.json @@ -12,6 +12,6 @@ "_ml/anomaly_detectors/{job_id}/results/categories/{category_id}", "_ml/anomaly_detectors/{job_id}/results/categories/" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-category.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-category.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics.json similarity index 71% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics.json index b3a0c9cf3ef71..ecccec9c7e059 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics.json @@ -12,6 +12,6 @@ "_ml/data_frame/analytics/{id}", "_ml/data_frame/analytics" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/get-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics_stats.json similarity index 71% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics_stats.json index e4b4ee7b1f64e..3ae103f79f798 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_data_frame_analytics_stats.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_data_frame_analytics_stats.json @@ -12,6 +12,6 @@ "_ml/data_frame/analytics/_stats", "_ml/data_frame/analytics/{id}/_stats" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/get-dfanalytics-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-dfanalytics-stats.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeed_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeed_stats.json similarity index 67% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeed_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeed_stats.json index 5c300e444c794..2971b8a7f6c63 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeed_stats.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeed_stats.json @@ -10,6 +10,6 @@ "_ml/datafeeds/{datafeed_id}/_stats", "_ml/datafeeds/_stats" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed-stats.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeeds.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeeds.json similarity index 66% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeeds.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeeds.json index 9979a685426be..deeb81d692739 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_datafeeds.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_datafeeds.json @@ -10,6 +10,6 @@ "_ml/datafeeds/{datafeed_id}", "_ml/datafeeds" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-datafeed.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_filters.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_filters.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_filters.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_filters.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_influencers.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_influencers.json similarity index 77% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_influencers.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_influencers.json index 9471fac64d489..6f6745d3a5472 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_influencers.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_influencers.json @@ -17,6 +17,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/results/influencers" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-influencer.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-influencer.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_job_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_job_stats.json similarity index 68% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_job_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_job_stats.json index b28a2655cbefe..6173b3ebdc6d0 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_job_stats.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_job_stats.json @@ -10,6 +10,6 @@ "_ml/anomaly_detectors/_stats", "_ml/anomaly_detectors/{job_id}/_stats" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job-stats.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_jobs.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_jobs.json similarity index 68% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_jobs.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_jobs.json index 8f7de906578d7..2486684424670 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_jobs.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_jobs.json @@ -10,6 +10,6 @@ "_ml/anomaly_detectors/{job_id}", "_ml/anomaly_detectors" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_model_snapshots.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_model_snapshots.json similarity index 77% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_model_snapshots.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_model_snapshots.json index a3b9702f4e4f0..19a61afc9e0e3 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_model_snapshots.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_model_snapshots.json @@ -16,6 +16,6 @@ "_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}", "_ml/anomaly_detectors/{job_id}/model_snapshots" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-snapshot.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-snapshot.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_overall_buckets.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_overall_buckets.json similarity index 76% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_overall_buckets.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_overall_buckets.json index e89d63ae7f49f..3a88c9d8ab9c9 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_overall_buckets.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_overall_buckets.json @@ -16,6 +16,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/results/overall_buckets" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-overall-buckets.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-overall-buckets.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_records.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_records.json similarity index 77% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_records.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_records.json index fd03c8d34214c..6ad8ecb6f7d6b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_records.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_records.json @@ -17,6 +17,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/results/records" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-record.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-record.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_trained_models.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_trained_models.json similarity index 92% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_trained_models.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_trained_models.json index cdeaca9654b77..76598ee015c6d 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_trained_models.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_trained_models.json @@ -5,7 +5,8 @@ "include_model_definition": "__flag__", "decompress_definition": "__flag__", "from": 0, - "size": 0 + "size": 0, + "tags": [] }, "methods": [ "GET" diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.get_trained_models_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_trained_models_stats.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.get_trained_models_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.get_trained_models_stats.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.info.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.info.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.info.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.info.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.open_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.open_job.json similarity index 56% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.open_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.open_job.json index cd330ec4822c0..969da2253cc89 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.open_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.open_job.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/_open" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-open-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-open-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.post_calendar_events.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.post_calendar_events.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.post_calendar_events.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.post_calendar_events.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.post_data.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.post_data.json similarity index 66% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.post_data.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.post_data.json index cc6f0b658e111..512d258f52780 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.post_data.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.post_data.json @@ -10,6 +10,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/_data" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-post-data.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-post-data.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.preview_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.preview_datafeed.json similarity index 55% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.preview_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.preview_datafeed.json index be3c3d466f37d..6eb537804134b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.preview_datafeed.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.preview_datafeed.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/datafeeds/{datafeed_id}/_preview" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-preview-datafeed.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-preview-datafeed.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_calendar.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_calendar.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_calendar.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_calendar.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_calendar_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_calendar_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_calendar_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_calendar_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_data_frame_analytics.json similarity index 56% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_data_frame_analytics.json index 83ffd0da3dda5..fd00ff3a94ebd 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_data_frame_analytics.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_data_frame_analytics.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/data_frame/analytics/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/put-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/put-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_datafeed.json new file mode 100644 index 0000000000000..302599b1633f4 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_datafeed.json @@ -0,0 +1,23 @@ +{ + "ml.put_datafeed": { + "url_params": { + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "ignore_throttled": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] + }, + "methods": [ + "PUT" + ], + "patterns": [ + "_ml/datafeeds/{datafeed_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-datafeed.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_filter.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_filter.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_filter.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_filter.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_job.json similarity index 55% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_job.json index d8e38a0bd4b9d..7a48994bd1a6c 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_job.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_trained_model.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_trained_model.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.put_trained_model.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.put_trained_model.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.revert_model_snapshot.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.revert_model_snapshot.json similarity index 69% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.revert_model_snapshot.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.revert_model_snapshot.json index 7b6d74d47a711..b0763d8a9b329 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.revert_model_snapshot.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.revert_model_snapshot.json @@ -9,6 +9,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}/_revert" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-revert-snapshot.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-revert-snapshot.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.set_upgrade_mode.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.set_upgrade_mode.json similarity index 64% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.set_upgrade_mode.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.set_upgrade_mode.json index d46e93c6eee46..71a0f0c042813 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.set_upgrade_mode.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.set_upgrade_mode.json @@ -10,6 +10,6 @@ "patterns": [ "_ml/set_upgrade_mode" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-set-upgrade-mode.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-set-upgrade-mode.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.start_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_data_frame_analytics.json similarity index 64% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.start_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_data_frame_analytics.json index 1b5d7c122fc53..0b420733cd9de 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.start_data_frame_analytics.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_data_frame_analytics.json @@ -9,6 +9,6 @@ "patterns": [ "_ml/data_frame/analytics/{id}/_start" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/start-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/start-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.start_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_datafeed.json similarity index 66% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.start_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_datafeed.json index 8171a792d7e33..36f9e5fa93257 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.start_datafeed.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.start_datafeed.json @@ -11,6 +11,6 @@ "patterns": [ "_ml/datafeeds/{datafeed_id}/_start" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-start-datafeed.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-start-datafeed.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.stop_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_data_frame_analytics.json similarity index 70% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.stop_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_data_frame_analytics.json index 05edf9bbef3a2..bda7a7c0d414b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.stop_data_frame_analytics.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_data_frame_analytics.json @@ -11,6 +11,6 @@ "patterns": [ "_ml/data_frame/analytics/{id}/_stop" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/stop-dfanalytics.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/stop-dfanalytics.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.stop_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_datafeed.json similarity index 69% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.stop_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_datafeed.json index b10fed7010a7f..d6769ed58148f 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.stop_datafeed.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.stop_datafeed.json @@ -11,6 +11,6 @@ "patterns": [ "_ml/datafeeds/{datafeed_id}/_stop" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-stop-datafeed.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-stop-datafeed.html" } } diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_datafeed.json new file mode 100644 index 0000000000000..4b31a9595659d --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_datafeed.json @@ -0,0 +1,23 @@ +{ + "ml.update_datafeed": { + "url_params": { + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "ignore_throttled": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] + }, + "methods": [ + "POST" + ], + "patterns": [ + "_ml/datafeeds/{datafeed_id}/_update" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-datafeed.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_filter.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_filter.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.update_filter.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_filter.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_job.json similarity index 56% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.update_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_job.json index 7276183b2e0c9..47ba249374e51 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_job.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_job.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/_update" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-job.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-job.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_model_snapshot.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_model_snapshot.json similarity index 61% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.update_model_snapshot.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_model_snapshot.json index 80e533eb55826..037982e7ebb2e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_model_snapshot.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.update_model_snapshot.json @@ -6,6 +6,6 @@ "patterns": [ "_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}/_update" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-snapshot.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-snapshot.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.upgrade.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.upgrade.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.upgrade.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.upgrade.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.validate.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.validate.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.validate.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.validate.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.validate_detector.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.validate_detector.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ml.validate_detector.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ml.validate_detector.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/monitoring.bulk.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/monitoring.bulk.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/monitoring.bulk.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.delete_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.delete_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.delete_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.delete_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.get_jobs.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_jobs.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.get_jobs.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_jobs.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.get_rollup_caps.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.get_rollup_caps.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_rollup_caps.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.get_rollup_index_caps.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.get_rollup_index_caps.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.get_rollup_index_caps.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.put_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.put_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.put_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.put_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.rollup_search.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.rollup_search.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.rollup_search.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.rollup_search.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.start_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.start_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.start_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.start_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/rollup.stop_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.stop_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/rollup.stop_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/rollup.stop_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.authenticate.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.authenticate.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.authenticate.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.authenticate.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.change_password.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.change_password.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.change_password.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.change_password.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.clear_cached_realms.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.clear_cached_realms.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.clear_cached_realms.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.clear_cached_realms.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.clear_cached_roles.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.clear_cached_roles.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.clear_cached_roles.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.clear_cached_roles.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.create_api_key.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.create_api_key.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.create_api_key.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.create_api_key.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.delete_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_privileges.json similarity index 68% rename from x-pack/plugins/console_extensions/server/spec/generated/security.delete_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_privileges.json index b44798013fe59..a7b56aa904bb2 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/security.delete_privileges.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_privileges.json @@ -13,6 +13,6 @@ "patterns": [ "_security/privilege/{application}/{name}" ], - "documentation": "TODO" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-privilege.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.delete_role.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_role.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.delete_role.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_role.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.delete_role_mapping.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_role_mapping.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.delete_role_mapping.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_role_mapping.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.delete_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.delete_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.delete_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.disable_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.disable_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.disable_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.disable_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.enable_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.enable_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.enable_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.enable_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_api_key.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_api_key.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_api_key.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_api_key.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_builtin_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_builtin_privileges.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_builtin_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_builtin_privileges.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_privileges.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_privileges.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_role.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_role.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_role.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_role.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_role_mapping.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_role_mapping.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_role_mapping.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_role_mapping.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.get_user_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_user_privileges.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.get_user_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.get_user_privileges.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.has_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.has_privileges.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.has_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.has_privileges.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.invalidate_api_key.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.invalidate_api_key.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.invalidate_api_key.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.invalidate_api_key.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.invalidate_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.invalidate_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.invalidate_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.invalidate_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.put_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_privileges.json similarity index 59% rename from x-pack/plugins/console_extensions/server/spec/generated/security.put_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_privileges.json index a42d5eb6c953e..4dbe88c526f0e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/security.put_privileges.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_privileges.json @@ -12,8 +12,8 @@ "POST" ], "patterns": [ - "_security/privilege" + "_security/privilege/" ], - "documentation": "TODO" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-privileges.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.put_role.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_role.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.put_role.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_role.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.put_role_mapping.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_role_mapping.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.put_role_mapping.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_role_mapping.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/security.put_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/security.put_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/security.put_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.delete_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json similarity index 79% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.delete_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json index 621aa9327e798..ee63fd52eeb5b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.delete_lifecycle.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.delete_lifecycle.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/policy/{policy_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-delete.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-delete-policy.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.execute_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json similarity index 78% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.execute_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json index 6d0b5fe02a9ee..9e50e2fc1009b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.execute_lifecycle.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.execute_lifecycle.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/policy/{policy_id}/_execute" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-execute.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-execute-lifecycle.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.execute_retention.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.execute_retention.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.execute_retention.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.execute_retention.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json similarity index 81% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.get_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json index 869438deb9219..93c32091be8e3 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_lifecycle.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_lifecycle.json @@ -7,6 +7,6 @@ "_slm/policy/{policy_id}", "_slm/policy" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-get.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-get-policy.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_stats.json similarity index 79% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.get_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_stats.json index e980534105b3c..b5af57beb2f79 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_stats.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_stats.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/stats" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/slm-get-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/slm-api-get-stats.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_status.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_status.json similarity index 78% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.get_status.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_status.json index a7ffde10b316d..3a01a414b5afd 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.get_status.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.get_status.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/status" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-get-status.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-get-status.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.put_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json similarity index 80% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.put_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json index 1391669ed293b..09bc2b7bf836b 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.put_lifecycle.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.put_lifecycle.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/policy/{policy_id}" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-put.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-put-policy.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.start.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.start.json similarity index 80% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.start.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.start.json index a5b94d98f08fb..1dff975cb2625 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.start.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.start.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/start" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-start.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-start.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/slm.stop.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.stop.json similarity index 80% rename from x-pack/plugins/console_extensions/server/spec/generated/slm.stop.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.stop.json index 0b76fe68d2b5e..2970c9a355005 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/slm.stop.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/slm.stop.json @@ -6,6 +6,6 @@ "patterns": [ "_slm/stop" ], - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-stop.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-api-stop.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/sql.clear_cursor.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.clear_cursor.json similarity index 51% rename from x-pack/plugins/console_extensions/server/spec/generated/sql.clear_cursor.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.clear_cursor.json index 6f15e1b979c51..3c98c9d295710 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/sql.clear_cursor.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.clear_cursor.json @@ -6,6 +6,6 @@ "patterns": [ "_sql/close" ], - "documentation": "Clear SQL cursor" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-pagination.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/sql.query.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.query.json similarity index 59% rename from x-pack/plugins/console_extensions/server/spec/generated/sql.query.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.query.json index 0e4274e772f30..75d0989fb779e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/sql.query.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.query.json @@ -10,6 +10,6 @@ "patterns": [ "_sql" ], - "documentation": "Execute SQL" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-rest-overview.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/sql.translate.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.translate.json similarity index 54% rename from x-pack/plugins/console_extensions/server/spec/generated/sql.translate.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.translate.json index e80ae7f8e3c5f..f93669ad58dc8 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/sql.translate.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/sql.translate.json @@ -7,6 +7,6 @@ "patterns": [ "_sql/translate" ], - "documentation": "Translate SQL into Elasticsearch queries" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-translate.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ssl.certificates.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ssl.certificates.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/ssl.certificates.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/ssl.certificates.json diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.cat_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.cat_transform.json new file mode 100644 index 0000000000000..6fe19a6e53d28 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.cat_transform.json @@ -0,0 +1,31 @@ +{ + "transform.cat_transform": { + "url_params": { + "from": 0, + "size": 0, + "allow_no_match": "__flag__", + "format": "", + "h": [], + "help": "__flag__", + "s": [], + "time": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ], + "v": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cat/transforms", + "_cat/transforms/{transform_id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/cat-transforms.html" + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.delete_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.delete_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.delete_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.delete_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.get_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.get_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.get_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.get_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.get_transform_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.get_transform_stats.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.get_transform_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.get_transform_stats.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.preview_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.preview_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.preview_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.preview_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.put_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.put_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.put_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.put_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.start_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.start_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.start_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.start_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.stop_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.stop_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.stop_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.stop_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/transform.update_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.update_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/transform.update_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/transform.update_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.ack_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.ack_watch.json similarity index 63% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.ack_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.ack_watch.json index bedaa40c10548..0eacab92ba98d 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.ack_watch.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.ack_watch.json @@ -8,6 +8,6 @@ "_watcher/watch/{watch_id}/_ack", "_watcher/watch/{watch_id}/_ack/{action_id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-ack-watch.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-ack-watch.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.activate_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.activate_watch.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.activate_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.activate_watch.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.deactivate_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.deactivate_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.deactivate_watch.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.delete_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.delete_watch.json similarity index 52% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.delete_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.delete_watch.json index 63e76c78c0d4a..4e0153423f540 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.delete_watch.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.delete_watch.json @@ -6,6 +6,6 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-delete-watch.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-delete-watch.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.execute_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.execute_watch.json similarity index 66% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.execute_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.execute_watch.json index 7319d68d249ff..249c912637d5e 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.execute_watch.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.execute_watch.json @@ -11,6 +11,6 @@ "_watcher/watch/{id}/_execute", "_watcher/watch/_execute" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-execute-watch.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-execute-watch.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.get_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.get_watch.json similarity index 51% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.get_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.get_watch.json index d9e646712edd6..bc244ed9415d2 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.get_watch.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.get_watch.json @@ -6,6 +6,6 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-watch.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-get-watch.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.put_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.put_watch.json similarity index 69% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.put_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.put_watch.json index 98250da734222..59eba35f7fcbd 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.put_watch.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.put_watch.json @@ -13,6 +13,6 @@ "patterns": [ "_watcher/watch/{id}" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-put-watch.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-put-watch.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.start.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.start.json similarity index 51% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.start.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.start.json index 28bc2db990ebd..e1d9e4c820ad7 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.start.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.start.json @@ -6,6 +6,6 @@ "patterns": [ "_watcher/_start" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-start.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-start.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stats.json similarity index 77% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stats.json index 62c6c5fea123e..d19446e0f5bb2 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.stats.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stats.json @@ -19,6 +19,6 @@ "queued_watches" ] }, - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stats.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stats.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/watcher.stop.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stop.json similarity index 50% rename from x-pack/plugins/console_extensions/server/spec/generated/watcher.stop.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stop.json index c2f370981d8e6..ac8fdaf365346 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/watcher.stop.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/watcher.stop.json @@ -6,6 +6,6 @@ "patterns": [ "_watcher/_stop" ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stop.html" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-stop.html" } } diff --git a/x-pack/plugins/console_extensions/server/spec/generated/xpack.info.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.info.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/xpack.info.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.info.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/xpack.ssl.certificates.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.ssl.certificates.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/generated/xpack.ssl.certificates.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.ssl.certificates.json diff --git a/x-pack/plugins/console_extensions/server/spec/generated/xpack.usage.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.usage.json similarity index 61% rename from x-pack/plugins/console_extensions/server/spec/generated/xpack.usage.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.usage.json index cd43f16ec45f8..90d50ce8aa533 100644 --- a/x-pack/plugins/console_extensions/server/spec/generated/xpack.usage.json +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated/xpack.usage.json @@ -9,6 +9,6 @@ "patterns": [ "_xpack/usage" ], - "documentation": "Retrieve information about xpack features usage" + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/usage-api.html" } } diff --git a/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/async_search.submit.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/async_search.submit.json new file mode 100644 index 0000000000000..f176bf64fadd3 --- /dev/null +++ b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/async_search.submit.json @@ -0,0 +1,7 @@ +{ + "async_search.submit": { + "data_autocomplete_rules": { + "__scope_link": "search" + } + } +} diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ccr.follow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.follow.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ccr.follow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.follow.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ccr.forget_follower.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.forget_follower.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ccr.forget_follower.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.forget_follower.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ccr.put_auto_follow_pattern.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.put_auto_follow_pattern.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ccr.put_auto_follow_pattern.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.put_auto_follow_pattern.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ccr.resume_follow.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.resume_follow.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ccr.resume_follow.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ccr.resume_follow.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/enrich.put_policy.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/enrich.put_policy.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/enrich.put_policy.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/enrich.put_policy.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ilm.move_to_step.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ilm.move_to_step.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ilm.move_to_step.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ilm.move_to_step.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ilm.put_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ilm.put_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.evaluate_data_frame.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.evaluate_data_frame.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.evaluate_data_frame.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.evaluate_data_frame.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.explain_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.explain_data_frame_analytics.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.explain_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.explain_data_frame_analytics.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_buckets.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_buckets.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_buckets.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_buckets.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_calendar_events.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_calendar_events.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_calendar_events.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_calendar_events.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_calendars.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_calendars.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_calendars.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_calendars.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_categories.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_categories.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_categories.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_categories.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_influencers.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_influencers.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_influencers.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_influencers.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_model_snapshots.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_model_snapshots.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_model_snapshots.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_model_snapshots.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_overall_buckets.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_overall_buckets.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_overall_buckets.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_overall_buckets.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.get_records.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_records.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.get_records.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.get_records.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.post_calendar_events.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.post_calendar_events.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.post_calendar_events.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.post_calendar_events.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.put_calendar.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_calendar.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.put_calendar.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_calendar.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.put_data_frame_analytics.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_data_frame_analytics.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.put_data_frame_analytics.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_data_frame_analytics.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.put_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_datafeed.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.put_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_datafeed.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.put_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.put_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.put_trained_model.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_trained_model.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.put_trained_model.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.put_trained_model.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.revert_model_snapshot.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.revert_model_snapshot.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.revert_model_snapshot.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.revert_model_snapshot.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.update_datafeed.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_datafeed.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.update_datafeed.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_datafeed.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.update_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.update_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.update_model_snapshot.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_model_snapshot.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/ml.update_model_snapshot.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/ml.update_model_snapshot.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.authenticate.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.authenticate.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.authenticate.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.authenticate.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.change_password.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.change_password.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.change_password.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.change_password.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.create_api_key.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.create_api_key.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.create_api_key.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.create_api_key.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.get_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.get_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.get_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.get_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.has_privileges.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.has_privileges.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.has_privileges.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.has_privileges.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.invalidate_api_key.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.invalidate_api_key.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.invalidate_api_key.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.invalidate_api_key.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.invalidate_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.invalidate_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.invalidate_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.invalidate_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.put_role.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_role.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.put_role.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_role.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.put_role_mapping.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_role_mapping.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.put_role_mapping.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_role_mapping.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.put_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/security.put_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/security.put_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/slm.put_lifecycle.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/slm.put_lifecycle.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/slm.start.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.start.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/slm.start.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.start.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/slm.stop.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.stop.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/slm.stop.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/slm.stop.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/sql.query.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/sql.query.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/sql.query.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/sql.query.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/transform.get_transform_stats.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.get_transform_stats.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/transform.get_transform_stats.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.get_transform_stats.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/transform.preview_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.preview_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/transform.preview_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.preview_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/transform.put_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.put_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/transform.put_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.put_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/transform.stop_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.stop_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/transform.stop_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.stop_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/transform.update_transform.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.update_transform.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/transform.update_transform.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/transform.update_transform.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.graph.explore.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.graph.explore.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.graph.explore.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.graph.explore.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.info.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.info.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.info.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.info.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.license.post.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.license.post.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.license.post.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.license.post.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.delete_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.delete_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.delete_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.delete_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.put_job.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.put_job.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.put_job.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.put_job.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.rollup_search.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.rollup_search.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.rollup.rollup_search.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.rollup.rollup_search.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.authenticate.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.authenticate.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.authenticate.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.authenticate.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.change_password.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.change_password.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.change_password.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.change_password.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.get_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.get_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.get_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.get_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.invalidate_token.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.invalidate_token.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.invalidate_token.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.invalidate_token.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_role.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_role.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_role.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_role.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_role_mapping.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_role_mapping.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_role_mapping.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_role_mapping.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_user.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_user.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.security.put_user.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.security.put_user.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.watcher.execute_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.watcher.execute_watch.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.watcher.execute_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.watcher.execute_watch.json diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/xpack.watcher.put_watch.json b/x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.watcher.put_watch.json similarity index 100% rename from x-pack/plugins/console_extensions/server/spec/overrides/xpack.watcher.put_watch.json rename to x-pack/plugins/console_extensions/server/lib/spec_definitions/json/overrides/xpack.watcher.put_watch.json diff --git a/x-pack/plugins/console_extensions/server/plugin.ts b/x-pack/plugins/console_extensions/server/plugin.ts index 8c2cb4d0db42b..2a08c258f4bbd 100644 --- a/x-pack/plugins/console_extensions/server/plugin.ts +++ b/x-pack/plugins/console_extensions/server/plugin.ts @@ -8,7 +8,7 @@ import { CoreSetup, CoreStart, Logger, Plugin, PluginInitializerContext } from ' import { ConsoleSetup, ConsoleStart } from '../../../../src/plugins/console/server'; -import { processors } from './spec/ingest/index'; +import { processors } from './lib/spec_definitions/js'; interface SetupDependencies { console: ConsoleSetup; @@ -18,7 +18,7 @@ interface StartDependencies { console: ConsoleStart; } -const CONSOLE_XPACK_JSON_SPEC_PATH = join(__dirname, 'spec/'); +const CONSOLE_XPACK_JSON_SPEC_PATH = join(__dirname, 'lib/spec_definitions/json'); export class ConsoleExtensionsServerPlugin implements Plugin { log: Logger; diff --git a/x-pack/plugins/console_extensions/server/spec/generated/enrich.delete_policy.json b/x-pack/plugins/console_extensions/server/spec/generated/enrich.delete_policy.json deleted file mode 100644 index 3d3c40fa093a4..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/enrich.delete_policy.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "enrich.delete_policy": { - "methods": [ - "DELETE" - ], - "patterns": [ - "_enrich/policy/{name}" - ] - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/enrich.put_policy.json b/x-pack/plugins/console_extensions/server/spec/generated/enrich.put_policy.json deleted file mode 100644 index 96d854f04dcfc..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/enrich.put_policy.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "enrich.put_policy": { - "methods": [ - "PUT" - ], - "patterns": [ - "_enrich/policy/{name}" - ] - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/enrich.stats.json b/x-pack/plugins/console_extensions/server/spec/generated/enrich.stats.json deleted file mode 100644 index e6d1b04d63e45..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/enrich.stats.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "enrich.stats": { - "methods": [ - "GET" - ], - "patterns": [ - "_enrich/_stats" - ] - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.estimate_memory_usage.json b/x-pack/plugins/console_extensions/server/spec/generated/ml.estimate_memory_usage.json deleted file mode 100644 index 2195b74640c79..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.estimate_memory_usage.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ml.estimate_memory_usage": { - "methods": [ - "PUT" - ], - "patterns": [ - "_ml/data_frame/analytics/_estimate_memory_usage" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/estimate-memory-usage-dfanalytics.html" - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_datafeed.json b/x-pack/plugins/console_extensions/server/spec/generated/ml.put_datafeed.json deleted file mode 100644 index a61f9ab465724..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.put_datafeed.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ml.put_datafeed": { - "methods": [ - "PUT" - ], - "patterns": [ - "_ml/datafeeds/{datafeed_id}" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-put-datafeed.html" - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_datafeed.json b/x-pack/plugins/console_extensions/server/spec/generated/ml.update_datafeed.json deleted file mode 100644 index 9c0d7502d2fbe..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/generated/ml.update_datafeed.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ml.update_datafeed": { - "methods": [ - "POST" - ], - "patterns": [ - "_ml/datafeeds/{datafeed_id}/_update" - ], - "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/ml-update-datafeed.html" - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/ml.estimate_memory_usage.json b/x-pack/plugins/console_extensions/server/spec/overrides/ml.estimate_memory_usage.json deleted file mode 100644 index 4954fd81a55d1..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/overrides/ml.estimate_memory_usage.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "ml.estimate_memory_usage": { - "data_autocomplete_rules": { - "data_frame_analytics_config": { - "source": { - "index": { "__one_of": ["SOURCE_INDEX_NAME", []] }, - "query": {} - }, - "dest": { - "index": "", - "results_field": "" - }, - "analysis": { - "outlier_detection": { - "n_neighbors": 1, - "method": {"__one_of": ["lof", "ldof", "distance_knn_nn", "distance_knn"]}, - "feature_influence_threshold": 1.0 - } - }, - "analyzed_fields": { - "__one_of": [ - "FIELD_NAME", - [], - { - "includes": { - "__one_of": ["FIELD_NAME", []] - }, - "excludes": { - "__one_of": ["FIELD_NAME", []] - } - } - ] - }, - "model_memory_limit": "" - } - } - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.delete_privileges.json b/x-pack/plugins/console_extensions/server/spec/overrides/security.delete_privileges.json deleted file mode 100644 index 5486098ff7bd8..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/overrides/security.delete_privileges.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "security.delete_privileges": { - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-delete-privilege.html" - } -} diff --git a/x-pack/plugins/console_extensions/server/spec/overrides/security.put_privileges.json b/x-pack/plugins/console_extensions/server/spec/overrides/security.put_privileges.json deleted file mode 100644 index 9ebb1046047a7..0000000000000 --- a/x-pack/plugins/console_extensions/server/spec/overrides/security.put_privileges.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "security.put_privileges": { - "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-put-privileges.html" - } -} diff --git a/x-pack/plugins/dashboard_enhanced/README.md b/x-pack/plugins/dashboard_enhanced/README.md deleted file mode 100644 index d9296ae158621..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/README.md +++ /dev/null @@ -1 +0,0 @@ -# X-Pack part of Dashboard app diff --git a/x-pack/plugins/dashboard_enhanced/kibana.json b/x-pack/plugins/dashboard_enhanced/kibana.json deleted file mode 100644 index acbca5c33295c..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/kibana.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id": "dashboardEnhanced", - "version": "kibana", - "server": true, - "ui": true, - "requiredPlugins": ["uiActions", "embeddable", "dashboard", "drilldowns"], - "configPath": ["xpack", "dashboardEnhanced"] -} diff --git a/x-pack/plugins/dashboard_enhanced/public/components/README.md b/x-pack/plugins/dashboard_enhanced/public/components/README.md deleted file mode 100644 index 8081f8a2451cf..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/components/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Presentation React components - -Here we keep reusable *presentation* (aka *dumb*) React components—these -components should not be connected to state and ideally should not know anything -about Kibana. diff --git a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.story.tsx b/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.story.tsx deleted file mode 100644 index 8e204b044a136..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.story.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -/* eslint-disable no-console */ - -import * as React from 'react'; -import { storiesOf } from '@storybook/react'; -import { DashboardDrilldownConfig } from '.'; - -export const dashboards = [ - { id: 'dashboard1', title: 'Dashboard 1' }, - { id: 'dashboard2', title: 'Dashboard 2' }, - { id: 'dashboard3', title: 'Dashboard 3' }, -]; - -const InteractiveDemo: React.FC = () => { - const [activeDashboardId, setActiveDashboardId] = React.useState('dashboard1'); - const [currentFilters, setCurrentFilters] = React.useState(false); - const [keepRange, setKeepRange] = React.useState(false); - - return ( - setActiveDashboardId(id)} - onCurrentFiltersToggle={() => setCurrentFilters(old => !old)} - onKeepRangeToggle={() => setKeepRange(old => !old)} - /> - ); -}; - -storiesOf('components/DashboardDrilldownConfig', module) - .add('default', () => ( - console.log('onDashboardSelect', e)} - /> - )) - .add('with switches', () => ( - console.log('onDashboardSelect', e)} - onCurrentFiltersToggle={() => console.log('onCurrentFiltersToggle')} - onKeepRangeToggle={() => console.log('onKeepRangeToggle')} - /> - )) - .add('interactive demo', () => ); diff --git a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.test.tsx b/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.test.tsx deleted file mode 100644 index 911ff6f632635..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.test.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -test.todo('renders list of dashboards'); -test.todo('renders correct selected dashboard'); -test.todo('can change dashboard'); -test.todo('can toggle "use current filters" switch'); -test.todo('can toggle "date range" switch'); diff --git a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx b/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx deleted file mode 100644 index b45ba602b9bb1..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiFormRow, EuiSelect, EuiSwitch } from '@elastic/eui'; -import { txtChooseDestinationDashboard } from './i18n'; - -export interface DashboardItem { - id: string; - title: string; -} - -export interface DashboardDrilldownConfigProps { - activeDashboardId?: string; - dashboards: DashboardItem[]; - currentFilters?: boolean; - keepRange?: boolean; - onDashboardSelect: (dashboardId: string) => void; - onCurrentFiltersToggle?: () => void; - onKeepRangeToggle?: () => void; -} - -export const DashboardDrilldownConfig: React.FC = ({ - activeDashboardId, - dashboards, - currentFilters, - keepRange, - onDashboardSelect, - onCurrentFiltersToggle, - onKeepRangeToggle, -}) => { - // TODO: use i18n below. - return ( - <> - - ({ value: id, text: title }))} - value={activeDashboardId} - onChange={e => onDashboardSelect(e.target.value)} - /> - - {!!onCurrentFiltersToggle && ( - - - - )} - {!!onKeepRangeToggle && ( - - - - )} - - ); -}; diff --git a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/i18n.ts b/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/i18n.ts deleted file mode 100644 index 38fe6dd150853..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/i18n.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const txtChooseDestinationDashboard = i18n.translate( - 'xpack.dashboard.components.DashboardDrilldownConfig.chooseDestinationDashboard', - { - defaultMessage: 'Choose destination dashboard', - } -); diff --git a/x-pack/plugins/dashboard_enhanced/public/index.ts b/x-pack/plugins/dashboard_enhanced/public/index.ts deleted file mode 100644 index 53540a4a1ad2e..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { PluginInitializerContext } from 'src/core/public'; -import { DashboardEnhancedPlugin } from './plugin'; - -export { - SetupContract as DashboardEnhancedSetupContract, - SetupDependencies as DashboardEnhancedSetupDependencies, - StartContract as DashboardEnhancedStartContract, - StartDependencies as DashboardEnhancedStartDependencies, -} from './plugin'; - -export function plugin(context: PluginInitializerContext) { - return new DashboardEnhancedPlugin(context); -} diff --git a/x-pack/plugins/dashboard_enhanced/public/mocks.ts b/x-pack/plugins/dashboard_enhanced/public/mocks.ts deleted file mode 100644 index 67dc1fd97d521..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/mocks.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { DashboardEnhancedSetupContract, DashboardEnhancedStartContract } from '.'; - -export type Setup = jest.Mocked; -export type Start = jest.Mocked; - -const createSetupContract = (): Setup => { - const setupContract: Setup = {}; - - return setupContract; -}; - -const createStartContract = (): Start => { - const startContract: Start = {}; - - return startContract; -}; - -export const dashboardEnhancedPluginMock = { - createSetupContract, - createStartContract, -}; diff --git a/x-pack/plugins/dashboard_enhanced/public/plugin.ts b/x-pack/plugins/dashboard_enhanced/public/plugin.ts deleted file mode 100644 index 30b3f3c080f49..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/plugin.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; -import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public'; -import { DashboardDrilldownsService } from './services'; -import { DrilldownsSetup, DrilldownsStart } from '../../drilldowns/public'; - -export interface SetupDependencies { - uiActions: UiActionsSetup; - drilldowns: DrilldownsSetup; -} - -export interface StartDependencies { - uiActions: UiActionsStart; - drilldowns: DrilldownsStart; -} - -// eslint-disable-next-line -export interface SetupContract {} - -// eslint-disable-next-line -export interface StartContract {} - -export class DashboardEnhancedPlugin - implements Plugin { - public readonly drilldowns = new DashboardDrilldownsService(); - public readonly config: { drilldowns: { enabled: boolean } }; - - constructor(protected readonly context: PluginInitializerContext) { - this.config = context.config.get(); - } - - public setup(core: CoreSetup, plugins: SetupDependencies): SetupContract { - this.drilldowns.bootstrap(core, plugins, { - enableDrilldowns: this.config.drilldowns.enabled, - }); - - return {}; - } - - public start(core: CoreStart, plugins: StartDependencies): StartContract { - return {}; - } - - public stop() {} -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx deleted file mode 100644 index 31ee9e29938cb..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - FlyoutCreateDrilldownAction, - OpenFlyoutAddDrilldownParams, -} from './flyout_create_drilldown'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { drilldownsPluginMock } from '../../../../../../drilldowns/public/mocks'; -import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { uiActionsPluginMock } from '../../../../../../../../src/plugins/ui_actions/public/mocks'; -import { TriggerContextMapping } from '../../../../../../../../src/plugins/ui_actions/public'; -import { MockEmbeddable } from '../test_helpers'; - -const overlays = coreMock.createStart().overlays; -const drilldowns = drilldownsPluginMock.createStartContract(); -const uiActions = uiActionsPluginMock.createStartContract(); - -const actionParams: OpenFlyoutAddDrilldownParams = { - drilldowns: () => Promise.resolve(drilldowns), - overlays: () => Promise.resolve(overlays), -}; - -test('should create', () => { - expect(() => new FlyoutCreateDrilldownAction(actionParams)).not.toThrow(); -}); - -test('title is a string', () => { - expect(typeof new FlyoutCreateDrilldownAction(actionParams).getDisplayName() === 'string').toBe( - true - ); -}); - -test('icon exists', () => { - expect(typeof new FlyoutCreateDrilldownAction(actionParams).getIconType() === 'string').toBe( - true - ); -}); - -describe('isCompatible', () => { - const drilldownAction = new FlyoutCreateDrilldownAction(actionParams); - - function checkCompatibility(params: { - isEdit: boolean; - withUiActions: boolean; - isValueClickTriggerSupported: boolean; - }): Promise { - return drilldownAction.isCompatible({ - embeddable: new MockEmbeddable( - { id: '', viewMode: params.isEdit ? ViewMode.EDIT : ViewMode.VIEW }, - { - supportedTriggers: (params.isValueClickTriggerSupported - ? ['VALUE_CLICK_TRIGGER'] - : []) as Array, - uiActions: params.withUiActions ? uiActions : undefined, // dynamic actions support - } - ), - }); - } - - test("compatible if dynamicUiActions enabled, 'VALUE_CLICK_TRIGGER' is supported, in edit mode", async () => { - expect( - await checkCompatibility({ - withUiActions: true, - isEdit: true, - isValueClickTriggerSupported: true, - }) - ).toBe(true); - }); - - test('not compatible if dynamicUiActions disabled', async () => { - expect( - await checkCompatibility({ - withUiActions: false, - isEdit: true, - isValueClickTriggerSupported: true, - }) - ).toBe(false); - }); - - test("not compatible if 'VALUE_CLICK_TRIGGER' is not supported", async () => { - expect( - await checkCompatibility({ - withUiActions: true, - isEdit: true, - isValueClickTriggerSupported: false, - }) - ).toBe(false); - }); - - test('not compatible if in view mode', async () => { - expect( - await checkCompatibility({ - withUiActions: true, - isEdit: false, - isValueClickTriggerSupported: true, - }) - ).toBe(false); - }); -}); - -describe('execute', () => { - const drilldownAction = new FlyoutCreateDrilldownAction(actionParams); - test('throws error if no dynamicUiActions', async () => { - await expect( - drilldownAction.execute({ - embeddable: new MockEmbeddable({ id: '' }, {}), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Can't execute FlyoutCreateDrilldownAction without dynamicActionsManager"` - ); - }); - - test('should open flyout', async () => { - const spy = jest.spyOn(overlays, 'openFlyout'); - await drilldownAction.execute({ - embeddable: new MockEmbeddable({ id: '' }, { uiActions }), - }); - expect(spy).toBeCalled(); - }); -}); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx deleted file mode 100644 index 00e74ea570a11..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { CoreStart } from 'src/core/public'; -import { ActionByType } from '../../../../../../../../src/plugins/ui_actions/public'; -import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public'; -import { DrilldownsStart } from '../../../../../../drilldowns/public'; -import { EmbeddableContext } from '../../../../../../../../src/plugins/embeddable/public'; - -export const OPEN_FLYOUT_ADD_DRILLDOWN = 'OPEN_FLYOUT_ADD_DRILLDOWN'; - -export interface OpenFlyoutAddDrilldownParams { - overlays: () => Promise; - drilldowns: () => Promise; -} - -export class FlyoutCreateDrilldownAction implements ActionByType { - public readonly type = OPEN_FLYOUT_ADD_DRILLDOWN; - public readonly id = OPEN_FLYOUT_ADD_DRILLDOWN; - public order = 12; - - constructor(protected readonly params: OpenFlyoutAddDrilldownParams) {} - - public getDisplayName() { - return i18n.translate('xpack.dashboard.FlyoutCreateDrilldownAction.displayName', { - defaultMessage: 'Create drilldown', - }); - } - - public getIconType() { - return 'plusInCircle'; - } - - private isEmbeddableCompatible(context: EmbeddableContext) { - if (!context.embeddable.dynamicActions) return false; - const supportedTriggers = context.embeddable.supportedTriggers(); - if (!supportedTriggers || !supportedTriggers.length) return false; - return supportedTriggers.indexOf('VALUE_CLICK_TRIGGER') > -1; - } - - public async isCompatible(context: EmbeddableContext) { - const isEditMode = context.embeddable.getInput().viewMode === 'edit'; - return isEditMode && this.isEmbeddableCompatible(context); - } - - public async execute(context: EmbeddableContext) { - const overlays = await this.params.overlays(); - const drilldowns = await this.params.drilldowns(); - const dynamicActionManager = context.embeddable.dynamicActions; - - if (!dynamicActionManager) { - throw new Error(`Can't execute FlyoutCreateDrilldownAction without dynamicActionsManager`); - } - - const handle = overlays.openFlyout( - toMountPoint( - handle.close()} - placeContext={context} - viewMode={'create'} - dynamicActionManager={dynamicActionManager} - /> - ), - { - ownFocus: true, - } - ); - } -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/index.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/index.ts deleted file mode 100644 index 4d2db209fc961..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { - FlyoutCreateDrilldownAction, - OpenFlyoutAddDrilldownParams, - OPEN_FLYOUT_ADD_DRILLDOWN, -} from './flyout_create_drilldown'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx deleted file mode 100644 index a3f11eb976f90..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { FlyoutEditDrilldownAction, FlyoutEditDrilldownParams } from './flyout_edit_drilldown'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { drilldownsPluginMock } from '../../../../../../drilldowns/public/mocks'; -import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { uiActionsPluginMock } from '../../../../../../../../src/plugins/ui_actions/public/mocks'; -import { MockEmbeddable } from '../test_helpers'; - -const overlays = coreMock.createStart().overlays; -const drilldowns = drilldownsPluginMock.createStartContract(); -const uiActions = uiActionsPluginMock.createStartContract(); - -const actionParams: FlyoutEditDrilldownParams = { - drilldowns: () => Promise.resolve(drilldowns), - overlays: () => Promise.resolve(overlays), -}; - -test('should create', () => { - expect(() => new FlyoutEditDrilldownAction(actionParams)).not.toThrow(); -}); - -test('title is a string', () => { - expect(typeof new FlyoutEditDrilldownAction(actionParams).getDisplayName() === 'string').toBe( - true - ); -}); - -test('icon exists', () => { - expect(typeof new FlyoutEditDrilldownAction(actionParams).getIconType() === 'string').toBe(true); -}); - -test('MenuItem exists', () => { - expect(new FlyoutEditDrilldownAction(actionParams).MenuItem).toBeDefined(); -}); - -describe('isCompatible', () => { - const drilldownAction = new FlyoutEditDrilldownAction(actionParams); - - function checkCompatibility(params: { - isEdit: boolean; - withUiActions: boolean; - }): Promise { - return drilldownAction.isCompatible({ - embeddable: new MockEmbeddable( - { - id: '', - viewMode: params.isEdit ? ViewMode.EDIT : ViewMode.VIEW, - }, - { - uiActions: params.withUiActions ? uiActions : undefined, // dynamic actions support - } - ), - }); - } - - // TODO: need proper DynamicActionsMock and ActionFactory mock - test.todo('compatible if dynamicUiActions enabled, in edit view, and have at least 1 drilldown'); - - test('not compatible if dynamicUiActions disabled', async () => { - expect( - await checkCompatibility({ - withUiActions: false, - isEdit: true, - }) - ).toBe(false); - }); - - test('not compatible if no drilldowns', async () => { - expect( - await checkCompatibility({ - withUiActions: true, - isEdit: true, - }) - ).toBe(false); - }); -}); - -describe('execute', () => { - const drilldownAction = new FlyoutEditDrilldownAction(actionParams); - test('throws error if no dynamicUiActions', async () => { - await expect( - drilldownAction.execute({ - embeddable: new MockEmbeddable({ id: '' }, {}), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Can't execute FlyoutEditDrilldownAction without dynamicActionsManager"` - ); - }); - - test('should open flyout', async () => { - const spy = jest.spyOn(overlays, 'openFlyout'); - await drilldownAction.execute({ - embeddable: new MockEmbeddable({ id: '' }, { uiActions }), - }); - expect(spy).toBeCalled(); - }); -}); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx deleted file mode 100644 index 816b757592a72..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { CoreStart } from 'src/core/public'; -import { ActionByType } from '../../../../../../../../src/plugins/ui_actions/public'; -import { - reactToUiComponent, - toMountPoint, -} from '../../../../../../../../src/plugins/kibana_react/public'; -import { EmbeddableContext, ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { DrilldownsStart } from '../../../../../../drilldowns/public'; -import { txtDisplayName } from './i18n'; -import { MenuItem } from './menu_item'; - -export const OPEN_FLYOUT_EDIT_DRILLDOWN = 'OPEN_FLYOUT_EDIT_DRILLDOWN'; - -export interface FlyoutEditDrilldownParams { - overlays: () => Promise; - drilldowns: () => Promise; -} - -export class FlyoutEditDrilldownAction implements ActionByType { - public readonly type = OPEN_FLYOUT_EDIT_DRILLDOWN; - public readonly id = OPEN_FLYOUT_EDIT_DRILLDOWN; - public order = 10; - - constructor(protected readonly params: FlyoutEditDrilldownParams) {} - - public getDisplayName() { - return txtDisplayName; - } - - public getIconType() { - return 'list'; - } - - MenuItem = reactToUiComponent(MenuItem); - - public async isCompatible({ embeddable }: EmbeddableContext) { - if (embeddable.getInput().viewMode !== ViewMode.EDIT) return false; - if (!embeddable.dynamicActions) return false; - return embeddable.dynamicActions.state.get().events.length > 0; - } - - public async execute(context: EmbeddableContext) { - const overlays = await this.params.overlays(); - const drilldowns = await this.params.drilldowns(); - const dynamicActionManager = context.embeddable.dynamicActions; - if (!dynamicActionManager) { - throw new Error(`Can't execute FlyoutEditDrilldownAction without dynamicActionsManager`); - } - - const handle = overlays.openFlyout( - toMountPoint( - handle.close()} - placeContext={context} - viewMode={'manage'} - dynamicActionManager={dynamicActionManager} - /> - ), - { - ownFocus: true, - } - ); - } -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/index.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/index.tsx deleted file mode 100644 index 3e1b37f270708..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { - FlyoutEditDrilldownAction, - FlyoutEditDrilldownParams, - OPEN_FLYOUT_EDIT_DRILLDOWN, -} from './flyout_edit_drilldown'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx deleted file mode 100644 index be693fadf9282..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { render, cleanup, act } from '@testing-library/react/pure'; -import { MenuItem } from './menu_item'; -import { createStateContainer } from '../../../../../../../../src/plugins/kibana_utils/common'; -import { DynamicActionManager } from '../../../../../../../../src/plugins/ui_actions/public'; -import { IEmbeddable } from '../../../../../../../../src/plugins/embeddable/public/lib/embeddables'; -import '@testing-library/jest-dom'; - -afterEach(cleanup); - -test('', () => { - const state = createStateContainer<{ events: object[] }>({ events: [] }); - const { getByText, queryByText } = render( - - ); - - expect(getByText(/manage drilldowns/i)).toBeInTheDocument(); - expect(queryByText('0')).not.toBeInTheDocument(); - - act(() => { - state.set({ events: [{}] }); - }); - - expect(queryByText('1')).toBeInTheDocument(); -}); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx deleted file mode 100644 index 4f99fca511b07..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiNotificationBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { EmbeddableContext } from '../../../../../../../../src/plugins/embeddable/public'; -import { txtDisplayName } from './i18n'; -import { useContainerState } from '../../../../../../../../src/plugins/kibana_utils/common'; - -export const MenuItem: React.FC<{ context: EmbeddableContext }> = ({ context }) => { - if (!context.embeddable.dynamicActions) - throw new Error('Flyout edit drillldown context menu item requires `dynamicActions`'); - - const { events } = useContainerState(context.embeddable.dynamicActions.state); - const count = events.length; - - return ( - - {txtDisplayName} - {count > 0 && ( - - {count} - - )} - - ); -}; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts deleted file mode 100644 index 9b156b0ba85b4..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Embeddable, EmbeddableInput } from '../../../../../../../src/plugins/embeddable/public/'; -import { - TriggerContextMapping, - UiActionsStart, -} from '../../../../../../../src/plugins/ui_actions/public'; - -export class MockEmbeddable extends Embeddable { - public readonly type = 'mock'; - private readonly triggers: Array = []; - constructor( - initialInput: EmbeddableInput, - params: { uiActions?: UiActionsStart; supportedTriggers?: Array } - ) { - super(initialInput, {}, undefined, params); - this.triggers = params.supportedTriggers ?? []; - } - public render(node: HTMLElement) {} - public reload() {} - public supportedTriggers(): Array { - return this.triggers; - } -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts deleted file mode 100644 index 4bdf03dff3531..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup } from 'src/core/public'; -import { SetupDependencies } from '../../plugin'; -import { - CONTEXT_MENU_TRIGGER, - EmbeddableContext, -} from '../../../../../../src/plugins/embeddable/public'; -import { - FlyoutCreateDrilldownAction, - FlyoutEditDrilldownAction, - OPEN_FLYOUT_ADD_DRILLDOWN, - OPEN_FLYOUT_EDIT_DRILLDOWN, -} from './actions'; -import { DrilldownsStart } from '../../../../drilldowns/public'; -import { DashboardToDashboardDrilldown } from './dashboard_to_dashboard_drilldown'; - -declare module '../../../../../../src/plugins/ui_actions/public' { - export interface ActionContextMapping { - [OPEN_FLYOUT_ADD_DRILLDOWN]: EmbeddableContext; - [OPEN_FLYOUT_EDIT_DRILLDOWN]: EmbeddableContext; - } -} - -interface BootstrapParams { - enableDrilldowns: boolean; -} - -export class DashboardDrilldownsService { - bootstrap( - core: CoreSetup<{ drilldowns: DrilldownsStart }>, - plugins: SetupDependencies, - { enableDrilldowns }: BootstrapParams - ) { - if (enableDrilldowns) { - this.setupDrilldowns(core, plugins); - } - } - - setupDrilldowns(core: CoreSetup<{ drilldowns: DrilldownsStart }>, plugins: SetupDependencies) { - const overlays = async () => (await core.getStartServices())[0].overlays; - const drilldowns = async () => (await core.getStartServices())[1].drilldowns; - const savedObjects = async () => (await core.getStartServices())[0].savedObjects.client; - - const actionFlyoutCreateDrilldown = new FlyoutCreateDrilldownAction({ overlays, drilldowns }); - plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, actionFlyoutCreateDrilldown); - - const actionFlyoutEditDrilldown = new FlyoutEditDrilldownAction({ overlays, drilldowns }); - plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, actionFlyoutEditDrilldown); - - const dashboardToDashboardDrilldown = new DashboardToDashboardDrilldown({ - savedObjects, - }); - plugins.drilldowns.registerDrilldown(dashboardToDashboardDrilldown); - } -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.test.tsx deleted file mode 100644 index 95101605ce468..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -test.todo('displays all dashboard in a list'); -test.todo('does not display dashboard on which drilldown is being created'); -test.todo('updates config object correctly'); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.tsx deleted file mode 100644 index e463cc38b6fbf..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/collect_config.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useState, useEffect } from 'react'; -import { CollectConfigProps } from './types'; -import { DashboardDrilldownConfig } from '../../../components/dashboard_drilldown_config'; -import { Params } from './drilldown'; - -export interface CollectConfigContainerProps extends CollectConfigProps { - params: Params; -} - -export const CollectConfigContainer: React.FC = ({ - config, - onConfig, - params: { savedObjects }, -}) => { - const [dashboards] = useState([ - { id: 'dashboard1', title: 'Dashboard 1' }, - { id: 'dashboard2', title: 'Dashboard 2' }, - { id: 'dashboard3', title: 'Dashboard 3' }, - { id: 'dashboard4', title: 'Dashboard 4' }, - ]); - - useEffect(() => { - // TODO: Load dashboards... - }, [savedObjects]); - - return ( - { - onConfig({ ...config, dashboardId }); - }} - onCurrentFiltersToggle={() => - onConfig({ - ...config, - useCurrentFilters: !config.useCurrentFilters, - }) - } - onKeepRangeToggle={() => - onConfig({ - ...config, - useCurrentDateRange: !config.useCurrentDateRange, - }) - } - /> - ); -}; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/constants.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/constants.ts deleted file mode 100644 index e2a530b156da5..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export const DASHBOARD_TO_DASHBOARD_DRILLDOWN = 'DASHBOARD_TO_DASHBOARD_DRILLDOWN'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx deleted file mode 100644 index 0fb60bb1064a1..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -describe('.isConfigValid()', () => { - test.todo('returns false for incorrect config'); - test.todo('returns true for incorrect config'); -}); - -describe('.execute()', () => { - test.todo('navigates to correct dashboard'); - test.todo( - 'when user chooses to keep current filters, current fileters are set on destination dashboard' - ); - test.todo( - 'when user chooses to keep current time range, current time range is set on destination dashboard' - ); -}); diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx deleted file mode 100644 index 9d2a378f08acd..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { CoreStart } from 'src/core/public'; -import { reactToUiComponent } from '../../../../../../../src/plugins/kibana_react/public'; -import { PlaceContext, ActionContext, Config, CollectConfigProps } from './types'; -import { CollectConfigContainer } from './collect_config'; -import { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from './constants'; -import { DrilldownDefinition as Drilldown } from '../../../../../drilldowns/public'; -import { txtGoToDashboard } from './i18n'; - -export interface Params { - savedObjects: () => Promise; -} - -export class DashboardToDashboardDrilldown - implements Drilldown { - constructor(protected readonly params: Params) {} - - public readonly id = DASHBOARD_TO_DASHBOARD_DRILLDOWN; - - public readonly order = 100; - - public readonly getDisplayName = () => txtGoToDashboard; - - public readonly euiIcon = 'dashboardApp'; - - private readonly ReactCollectConfig: React.FC = props => ( - - ); - - public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig); - - public readonly createConfig = () => ({ - dashboardId: '123', - useCurrentFilters: true, - useCurrentDateRange: true, - }); - - public readonly isConfigValid = (config: Config): config is Config => { - if (!config.dashboardId) return false; - return true; - }; - - public readonly execute = () => { - alert('Go to another dashboard!'); - }; -} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/index.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/index.ts deleted file mode 100644 index 9daa485bb6e6c..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { DASHBOARD_TO_DASHBOARD_DRILLDOWN } from './constants'; -export { - DashboardToDashboardDrilldown, - Params as DashboardToDashboardDrilldownParams, -} from './drilldown'; -export { - PlaceContext as DashboardToDashboardPlaceContext, - ActionContext as DashboardToDashboardActionContext, - Config as DashboardToDashboardConfig, -} from './types'; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts deleted file mode 100644 index 398a259491e3e..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EmbeddableVisTriggerContext, - EmbeddableContext, -} from '../../../../../../../src/plugins/embeddable/public'; -import { UiActionsCollectConfigProps } from '../../../../../../../src/plugins/ui_actions/public'; - -export type PlaceContext = EmbeddableContext; -export type ActionContext = EmbeddableVisTriggerContext; - -export interface Config { - dashboardId?: string; - useCurrentFilters: boolean; - useCurrentDateRange: boolean; -} - -export type CollectConfigProps = UiActionsCollectConfigProps; diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/index.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/index.ts deleted file mode 100644 index 7be8f1c65da12..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './dashboard_drilldowns_services'; diff --git a/x-pack/plugins/dashboard_enhanced/server/config.ts b/x-pack/plugins/dashboard_enhanced/server/config.ts deleted file mode 100644 index b75c95d5f8832..0000000000000 --- a/x-pack/plugins/dashboard_enhanced/server/config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema, TypeOf } from '@kbn/config-schema'; -import { PluginConfigDescriptor } from '../../../../src/core/server'; - -export const configSchema = schema.object({ - drilldowns: schema.object({ - enabled: schema.boolean({ defaultValue: false }), - }), -}); - -export type ConfigSchema = TypeOf; - -export const config: PluginConfigDescriptor = { - schema: configSchema, - exposeToBrowser: { - drilldowns: true, - }, -}; diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index b2d5f42d9e468..443bb63a27799 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -3,7 +3,7 @@ "version": "8.0.0", "kibanaVersion": "kibana", "configPath": [ - "xpack" + "xpack", "data_enhanced" ], "requiredPlugins": [ "data" diff --git a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts index c493e8ce86781..70bdcdfd3cf1f 100644 --- a/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/public/search/es_search_strategy.ts @@ -33,7 +33,7 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider { + const mockCoreSetup = coreMock.createSetup(); + const mockApiCaller = jest.fn(); + const mockSearch = jest.fn(); + const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + + beforeEach(() => { + mockApiCaller.mockClear(); + mockSearch.mockClear(); + }); + + it('returns a strategy with `search`', () => { + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + expect(typeof esSearch.search).toBe('function'); + }); + + it('makes a POST request to async search with params when no ID is provided', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path, body } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('logstash-*/_async_search'); + expect(body).toEqual({ query: {} }); + }); + + it('makes a GET request to async search with ID when ID is provided', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'logstash-*', body: { query: {} } }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ id: 'foo', params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path, body } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('GET'); + expect(path).toBe('_async_search/foo'); + expect(body).toEqual(undefined); + }); + + it('encodes special characters in the path', async () => { + mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); + + const params = { index: 'foo-程', body: {} }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('foo-%E7%A8%8B/_async_search'); + }); + + it('calls the rollup API if the index is a rollup type', async () => { + mockApiCaller.mockResolvedValueOnce(mockRollupResponse); + + const params = { index: 'foo-程', body: {} }; + const esSearch = enhancedEsSearchStrategyProvider( + { + core: mockCoreSetup, + config$: mockConfig$, + }, + mockApiCaller, + mockSearch + ); + + await esSearch.search({ indexType: 'rollup', params }); + + expect(mockApiCaller).toBeCalled(); + expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request'); + const { method, path } = mockApiCaller.mock.calls[0][1]; + expect(method).toBe('POST'); + expect(path).toBe('foo-%E7%A8%8B/_rollup_search'); + }); +}); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 004e57f71464a..95ffd7b06df21 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -16,6 +16,7 @@ import { ISearchOptions, ISearchCancel, getDefaultSearchParams, + getTotalLoaded, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; @@ -36,31 +37,21 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider) - : (response as AsyncSearchResponse).response; - - const id = (response as AsyncSearchResponse).id; - const { total, failed, successful } = rawResponse._shards; - const loaded = failed + successful; - return { id, total, loaded, rawResponse }; + : asyncSearch(caller, { ...request, params }, options); }; const cancel: ISearchCancel = async id => { const method = 'DELETE'; - const path = `_async_search/${id}`; + const path = encodeURI(`_async_search/${id}`); await caller('transport.request', { method, path }); }; return { search, cancel }; }; -function asyncSearch( +async function asyncSearch( caller: APICaller, request: IEnhancedEsSearchRequest, options?: ISearchOptions @@ -69,12 +60,18 @@ function asyncSearch( // If we have an ID, then just poll for that ID, otherwise send the entire request body const method = request.id ? 'GET' : 'POST'; - const path = request.id ? `_async_search/${request.id}` : `${index}/_async_search`; + const path = encodeURI(request.id ? `_async_search/${request.id}` : `${index}/_async_search`); // Wait up to 1s for the response to return - const query = toSnakeCase({ waitForCompletion: '1s', ...params }); + const query = toSnakeCase({ /* waitForCompletion: '1s', */ ...params }); + + const { response: rawResponse, id } = (await caller( + 'transport.request', + { method, path, body, query }, + options + )) as AsyncSearchResponse; - return caller('transport.request', { method, path, body, query }, options); + return { id, rawResponse, ...getTotalLoaded(rawResponse._shards) }; } async function rollupSearch( @@ -84,9 +81,16 @@ async function rollupSearch( ) { const { body, index, ...params } = request.params; const method = 'POST'; - const path = `${index}/_rollup_search`; + const path = encodeURI(`${index}/_rollup_search`); const query = toSnakeCase(params); - return caller('transport.request', { method, path, body, query }, options); + + const rawResponse = await ((caller( + 'transport.request', + { method, path, body, query }, + options + ) as unknown) as SearchResponse); + + return { rawResponse, ...getTotalLoaded(rawResponse._shards) }; } function toSnakeCase(obj: Record) { diff --git a/x-pack/plugins/drilldowns/kibana.json b/x-pack/plugins/drilldowns/kibana.json index 8372d87166364..4dba07b5a7be3 100644 --- a/x-pack/plugins/drilldowns/kibana.json +++ b/x-pack/plugins/drilldowns/kibana.json @@ -3,5 +3,9 @@ "version": "kibana", "server": false, "ui": true, - "requiredPlugins": ["uiActions", "embeddable", "advancedUiActions"] + "configPath": ["xpack", "drilldowns"], + "requiredPlugins": [ + "uiActions", + "embeddable" + ] } diff --git a/x-pack/plugins/drilldowns/public/actions/flyout_create_drilldown/index.tsx b/x-pack/plugins/drilldowns/public/actions/flyout_create_drilldown/index.tsx new file mode 100644 index 0000000000000..4834cc8081374 --- /dev/null +++ b/x-pack/plugins/drilldowns/public/actions/flyout_create_drilldown/index.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'src/core/public'; +import { ActionByType } from '../../../../../../src/plugins/ui_actions/public'; +import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; +import { IEmbeddable } from '../../../../../../src/plugins/embeddable/public'; +import { FlyoutCreateDrilldown } from '../../components/flyout_create_drilldown'; + +export const OPEN_FLYOUT_ADD_DRILLDOWN = 'OPEN_FLYOUT_ADD_DRILLDOWN'; + +export interface FlyoutCreateDrilldownActionContext { + embeddable: IEmbeddable; +} + +export interface OpenFlyoutAddDrilldownParams { + overlays: () => Promise; +} + +export class FlyoutCreateDrilldownAction implements ActionByType { + public readonly type = OPEN_FLYOUT_ADD_DRILLDOWN; + public readonly id = OPEN_FLYOUT_ADD_DRILLDOWN; + public order = 100; + + constructor(protected readonly params: OpenFlyoutAddDrilldownParams) {} + + public getDisplayName() { + return i18n.translate('xpack.drilldowns.FlyoutCreateDrilldownAction.displayName', { + defaultMessage: 'Create drilldown', + }); + } + + public getIconType() { + return 'plusInCircle'; + } + + public async isCompatible({ embeddable }: FlyoutCreateDrilldownActionContext) { + return embeddable.getInput().viewMode === 'edit'; + } + + public async execute(context: FlyoutCreateDrilldownActionContext) { + const overlays = await this.params.overlays(); + const handle = overlays.openFlyout( + toMountPoint( handle.close()} />) + ); + } +} diff --git a/x-pack/plugins/drilldowns/public/actions/flyout_edit_drilldown/index.tsx b/x-pack/plugins/drilldowns/public/actions/flyout_edit_drilldown/index.tsx new file mode 100644 index 0000000000000..f109da94fcaca --- /dev/null +++ b/x-pack/plugins/drilldowns/public/actions/flyout_edit_drilldown/index.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'src/core/public'; +import { EuiNotificationBadge } from '@elastic/eui'; +import { ActionByType } from '../../../../../../src/plugins/ui_actions/public'; +import { + toMountPoint, + reactToUiComponent, +} from '../../../../../../src/plugins/kibana_react/public'; +import { IEmbeddable } from '../../../../../../src/plugins/embeddable/public'; +import { FormCreateDrilldown } from '../../components/form_create_drilldown'; + +export const OPEN_FLYOUT_EDIT_DRILLDOWN = 'OPEN_FLYOUT_EDIT_DRILLDOWN'; + +export interface FlyoutEditDrilldownActionContext { + embeddable: IEmbeddable; +} + +export interface FlyoutEditDrilldownParams { + overlays: () => Promise; +} + +const displayName = i18n.translate('xpack.drilldowns.panel.openFlyoutEditDrilldown.displayName', { + defaultMessage: 'Manage drilldowns', +}); + +// mocked data +const drilldrownCount = 2; + +export class FlyoutEditDrilldownAction implements ActionByType { + public readonly type = OPEN_FLYOUT_EDIT_DRILLDOWN; + public readonly id = OPEN_FLYOUT_EDIT_DRILLDOWN; + public order = 100; + + constructor(protected readonly params: FlyoutEditDrilldownParams) {} + + public getDisplayName() { + return displayName; + } + + public getIconType() { + return 'list'; + } + + private ReactComp: React.FC<{ context: FlyoutEditDrilldownActionContext }> = () => { + return ( + <> + {displayName}{' '} + + {drilldrownCount} + + + ); + }; + + MenuItem = reactToUiComponent(this.ReactComp); + + public async isCompatible({ embeddable }: FlyoutEditDrilldownActionContext) { + return embeddable.getInput().viewMode === 'edit' && drilldrownCount > 0; + } + + public async execute({ embeddable }: FlyoutEditDrilldownActionContext) { + const overlays = await this.params.overlays(); + overlays.openFlyout(toMountPoint()); + } +} diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/index.ts b/x-pack/plugins/drilldowns/public/actions/index.ts similarity index 100% rename from x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/index.ts rename to x-pack/plugins/drilldowns/public/actions/index.ts diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx deleted file mode 100644 index 16b4d3a25d9e5..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as React from 'react'; -import { EuiFlyout } from '@elastic/eui'; -import { storiesOf } from '@storybook/react'; -import { createFlyoutManageDrilldowns } from './connected_flyout_manage_drilldowns'; -import { - dashboardFactory, - urlFactory, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data'; -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; -import { StubBrowserStorage } from '../../../../../../src/test_utils/public/stub_browser_storage'; -import { mockDynamicActionManager } from './test_data'; - -const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({ - advancedUiActions: { - getActionFactories() { - return [dashboardFactory, urlFactory]; - }, - } as any, - storage: new Storage(new StubBrowserStorage()), - notifications: { - toasts: { - addError: (...args: any[]) => { - alert(JSON.stringify(args)); - }, - addSuccess: (...args: any[]) => { - alert(JSON.stringify(args)); - }, - } as any, - }, -}); - -storiesOf('components/FlyoutManageDrilldowns', module).add('default', () => ( - {}}> - - -)); diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx deleted file mode 100644 index 6749b41e81fc7..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { cleanup, fireEvent, render, wait } from '@testing-library/react/pure'; -import '@testing-library/jest-dom/extend-expect'; -import { createFlyoutManageDrilldowns } from './connected_flyout_manage_drilldowns'; -import { - dashboardFactory, - urlFactory, -} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data'; -import { StubBrowserStorage } from '../../../../../../src/test_utils/public/stub_browser_storage'; -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; -import { mockDynamicActionManager } from './test_data'; -import { TEST_SUBJ_DRILLDOWN_ITEM } from '../list_manage_drilldowns'; -import { WELCOME_MESSAGE_TEST_SUBJ } from '../drilldown_hello_bar'; -import { coreMock } from '../../../../../../src/core/public/mocks'; -import { NotificationsStart } from 'kibana/public'; -import { toastDrilldownsCRUDError } from './i18n'; - -const storage = new Storage(new StubBrowserStorage()); -const notifications = coreMock.createStart().notifications; -const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({ - advancedUiActions: { - getActionFactories() { - return [dashboardFactory, urlFactory]; - }, - } as any, - storage, - notifications, -}); - -// https://github.com/elastic/kibana/issues/59469 -afterEach(cleanup); - -beforeEach(() => { - storage.clear(); - (notifications.toasts as jest.Mocked).addSuccess.mockClear(); - (notifications.toasts as jest.Mocked).addError.mockClear(); -}); - -test('Allows to manage drilldowns', async () => { - const screen = render( - - ); - - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible()); - - // no drilldowns in the list - expect(screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(0); - - fireEvent.click(screen.getByText(/Create new/i)); - - let [createHeading, createButton] = screen.getAllByText(/Create Drilldown/i); - expect(createHeading).toBeVisible(); - expect(screen.getByLabelText(/Back/i)).toBeVisible(); - - expect(createButton).toBeDisabled(); - - // input drilldown name - const name = 'Test name'; - fireEvent.change(screen.getByLabelText(/name/i), { - target: { value: name }, - }); - - // select URL one - fireEvent.click(screen.getByText(/Go to URL/i)); - - // Input url - const URL = 'https://elastic.co'; - fireEvent.change(screen.getByLabelText(/url/i), { - target: { value: URL }, - }); - - [createHeading, createButton] = screen.getAllByText(/Create Drilldown/i); - - expect(createButton).toBeEnabled(); - fireEvent.click(createButton); - - expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible(); - - await wait(() => expect(screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(1)); - expect(screen.getByText(name)).toBeVisible(); - const editButton = screen.getByText(/edit/i); - fireEvent.click(editButton); - - expect(screen.getByText(/Edit Drilldown/i)).toBeVisible(); - // check that wizard is prefilled with current drilldown values - expect(screen.getByLabelText(/name/i)).toHaveValue(name); - expect(screen.getByLabelText(/url/i)).toHaveValue(URL); - - // input new drilldown name - const newName = 'New drilldown name'; - fireEvent.change(screen.getByLabelText(/name/i), { - target: { value: newName }, - }); - fireEvent.click(screen.getByText(/save/i)); - - expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible(); - await wait(() => screen.getByText(newName)); - - // delete drilldown from edit view - fireEvent.click(screen.getByText(/edit/i)); - fireEvent.click(screen.getByText(/delete/i)); - - expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible(); - await wait(() => expect(screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(0)); -}); - -test('Can delete multiple drilldowns', async () => { - const screen = render( - - ); - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible()); - - const createDrilldown = async () => { - const oldCount = screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM).length; - fireEvent.click(screen.getByText(/Create new/i)); - fireEvent.change(screen.getByLabelText(/name/i), { - target: { value: 'test' }, - }); - fireEvent.click(screen.getByText(/Go to URL/i)); - fireEvent.change(screen.getByLabelText(/url/i), { - target: { value: 'https://elastic.co' }, - }); - fireEvent.click(screen.getAllByText(/Create Drilldown/i)[1]); - await wait(() => - expect(screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(oldCount + 1) - ); - }; - - await createDrilldown(); - await createDrilldown(); - await createDrilldown(); - - const checkboxes = screen.getAllByLabelText(/Select this drilldown/i); - expect(checkboxes).toHaveLength(3); - checkboxes.forEach(checkbox => fireEvent.click(checkbox)); - expect(screen.queryByText(/Create/i)).not.toBeInTheDocument(); - fireEvent.click(screen.getByText(/Delete \(3\)/i)); - - await wait(() => expect(screen.queryAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(0)); -}); - -test('Create only mode', async () => { - const onClose = jest.fn(); - const screen = render( - - ); - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getAllByText(/Create/i).length).toBeGreaterThan(0)); - fireEvent.change(screen.getByLabelText(/name/i), { - target: { value: 'test' }, - }); - fireEvent.click(screen.getByText(/Go to URL/i)); - fireEvent.change(screen.getByLabelText(/url/i), { - target: { value: 'https://elastic.co' }, - }); - fireEvent.click(screen.getAllByText(/Create Drilldown/i)[1]); - - await wait(() => expect(notifications.toasts.addSuccess).toBeCalled()); - expect(onClose).toBeCalled(); - expect(await mockDynamicActionManager.state.get().events.length).toBe(1); -}); - -test.todo("Error when can't fetch drilldown list"); - -test("Error when can't save drilldown changes", async () => { - const error = new Error('Oops'); - jest.spyOn(mockDynamicActionManager, 'createEvent').mockImplementationOnce(async () => { - throw error; - }); - const screen = render( - - ); - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible()); - fireEvent.click(screen.getByText(/Create new/i)); - fireEvent.change(screen.getByLabelText(/name/i), { - target: { value: 'test' }, - }); - fireEvent.click(screen.getByText(/Go to URL/i)); - fireEvent.change(screen.getByLabelText(/url/i), { - target: { value: 'https://elastic.co' }, - }); - fireEvent.click(screen.getAllByText(/Create Drilldown/i)[1]); - await wait(() => - expect(notifications.toasts.addError).toBeCalledWith(error, { title: toastDrilldownsCRUDError }) - ); -}); - -test('Should show drilldown welcome message. Should be able to dismiss it', async () => { - let screen = render( - - ); - - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible()); - - expect(screen.getByTestId(WELCOME_MESSAGE_TEST_SUBJ)).toBeVisible(); - fireEvent.click(screen.getByText(/hide/i)); - expect(screen.queryByTestId(WELCOME_MESSAGE_TEST_SUBJ)).toBeNull(); - cleanup(); - - screen = render( - - ); - // wait for initial render. It is async because resolving compatible action factories is async - await wait(() => expect(screen.getByText(/Manage Drilldowns/i)).toBeVisible()); - expect(screen.queryByTestId(WELCOME_MESSAGE_TEST_SUBJ)).toBeNull(); -}); diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx deleted file mode 100644 index f22ccc2f26f02..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useEffect, useState } from 'react'; -import useMountedState from 'react-use/lib/useMountedState'; -import { - AdvancedUiActionsActionFactory as ActionFactory, - AdvancedUiActionsStart, -} from '../../../../advanced_ui_actions/public'; -import { NotificationsStart } from '../../../../../../src/core/public'; -import { DrilldownWizardConfig, FlyoutDrilldownWizard } from '../flyout_drilldown_wizard'; -import { FlyoutListManageDrilldowns } from '../flyout_list_manage_drilldowns'; -import { IStorageWrapper } from '../../../../../../src/plugins/kibana_utils/public'; -import { - DynamicActionManager, - UiActionsSerializedEvent, - UiActionsSerializedAction, - VALUE_CLICK_TRIGGER, - SELECT_RANGE_TRIGGER, - TriggerContextMapping, -} from '../../../../../../src/plugins/ui_actions/public'; -import { useContainerState } from '../../../../../../src/plugins/kibana_utils/common'; -import { DrilldownListItem } from '../list_manage_drilldowns'; -import { - toastDrilldownCreated, - toastDrilldownDeleted, - toastDrilldownEdited, - toastDrilldownsCRUDError, - toastDrilldownsDeleted, -} from './i18n'; -import { DrilldownFactoryContext } from '../../types'; - -interface ConnectedFlyoutManageDrilldownsProps { - placeContext: Context; - dynamicActionManager: DynamicActionManager; - viewMode?: 'create' | 'manage'; - onClose?: () => void; -} - -/** - * Represent current state (route) of FlyoutManageDrilldowns - */ -enum Routes { - Manage = 'manage', - Create = 'create', - Edit = 'edit', -} - -export function createFlyoutManageDrilldowns({ - advancedUiActions, - storage, - notifications, -}: { - advancedUiActions: AdvancedUiActionsStart; - storage: IStorageWrapper; - notifications: NotificationsStart; -}) { - // fine to assume this is static, - // because all action factories should be registered in setup phase - const allActionFactories = advancedUiActions.getActionFactories(); - const allActionFactoriesById = allActionFactories.reduce((acc, next) => { - acc[next.id] = next; - return acc; - }, {} as Record); - - return (props: ConnectedFlyoutManageDrilldownsProps) => { - const isCreateOnly = props.viewMode === 'create'; - - const selectedTriggers: Array = React.useMemo( - () => [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER], - [] - ); - - const factoryContext: DrilldownFactoryContext = React.useMemo( - () => ({ - placeContext: props.placeContext, - triggers: selectedTriggers, - }), - [props.placeContext, selectedTriggers] - ); - - const actionFactories = useCompatibleActionFactoriesForCurrentContext( - allActionFactories, - factoryContext - ); - - const [route, setRoute] = useState( - () => (isCreateOnly ? Routes.Create : Routes.Manage) // initial state is different depending on `viewMode` - ); - const [currentEditId, setCurrentEditId] = useState(null); - - const [shouldShowWelcomeMessage, onHideWelcomeMessage] = useWelcomeMessage(storage); - - const { - drilldowns, - createDrilldown, - editDrilldown, - deleteDrilldown, - } = useDrilldownsStateManager(props.dynamicActionManager, notifications); - - /** - * isCompatible promise is not yet resolved. - * Skip rendering until it is resolved - */ - if (!actionFactories) return null; - /** - * Drilldowns are not fetched yet or error happened during fetching - * In case of error user is notified with toast - */ - if (!drilldowns) return null; - - /** - * Needed for edit mode to prefill wizard fields with data from current edited drilldown - */ - function resolveInitialDrilldownWizardConfig(): DrilldownWizardConfig | undefined { - if (route !== Routes.Edit) return undefined; - if (!currentEditId) return undefined; - const drilldownToEdit = drilldowns?.find(d => d.eventId === currentEditId); - if (!drilldownToEdit) return undefined; - - return { - actionFactory: allActionFactoriesById[drilldownToEdit.action.factoryId], - actionConfig: drilldownToEdit.action.config as object, // TODO: config is unknown, but we know it always extends object - name: drilldownToEdit.action.name, - }; - } - - /** - * Maps drilldown to list item view model - */ - function mapToDrilldownToDrilldownListItem( - drilldown: UiActionsSerializedEvent - ): DrilldownListItem { - const actionFactory = allActionFactoriesById[drilldown.action.factoryId]; - return { - id: drilldown.eventId, - drilldownName: drilldown.action.name, - actionName: actionFactory?.getDisplayName(factoryContext) ?? drilldown.action.factoryId, - icon: actionFactory?.getIconType(factoryContext), - }; - } - - switch (route) { - case Routes.Create: - case Routes.Edit: - return ( - setRoute(Routes.Manage)} - onSubmit={({ actionConfig, actionFactory, name }) => { - if (route === Routes.Create) { - createDrilldown( - { - name, - config: actionConfig, - factoryId: actionFactory.id, - }, - selectedTriggers - ); - } else { - editDrilldown( - currentEditId!, - { - name, - config: actionConfig, - factoryId: actionFactory.id, - }, - selectedTriggers - ); - } - - if (isCreateOnly) { - if (props.onClose) { - props.onClose(); - } - } else { - setRoute(Routes.Manage); - } - - setCurrentEditId(null); - }} - onDelete={() => { - deleteDrilldown(currentEditId!); - setRoute(Routes.Manage); - setCurrentEditId(null); - }} - actionFactoryContext={factoryContext} - initialDrilldownWizardConfig={resolveInitialDrilldownWizardConfig()} - /> - ); - - case Routes.Manage: - default: - return ( - { - setCurrentEditId(null); - deleteDrilldown(ids); - }} - onEdit={id => { - setCurrentEditId(id); - setRoute(Routes.Edit); - }} - onCreate={() => { - setCurrentEditId(null); - setRoute(Routes.Create); - }} - onClose={props.onClose} - /> - ); - } - }; -} - -function useCompatibleActionFactoriesForCurrentContext( - actionFactories: Array>, - context: Context -) { - const [compatibleActionFactories, setCompatibleActionFactories] = useState< - Array> - >(); - useEffect(() => { - let canceled = false; - async function updateCompatibleFactoriesForContext() { - const compatibility = await Promise.all( - actionFactories.map(factory => factory.isCompatible(context)) - ); - if (canceled) return; - setCompatibleActionFactories(actionFactories.filter((_, i) => compatibility[i])); - } - updateCompatibleFactoriesForContext(); - return () => { - canceled = true; - }; - }, [context, actionFactories]); - - return compatibleActionFactories; -} - -function useWelcomeMessage(storage: IStorageWrapper): [boolean, () => void] { - const key = `drilldowns:hidWelcomeMessage`; - const [hidWelcomeMessage, setHidWelcomeMessage] = useState(storage.get(key) ?? false); - - return [ - !hidWelcomeMessage, - () => { - if (hidWelcomeMessage) return; - setHidWelcomeMessage(true); - storage.set(key, true); - }, - ]; -} - -function useDrilldownsStateManager( - actionManager: DynamicActionManager, - notifications: NotificationsStart -) { - const { events: drilldowns } = useContainerState(actionManager.state); - const [isLoading, setIsLoading] = useState(false); - const isMounted = useMountedState(); - - async function run(op: () => Promise) { - setIsLoading(true); - try { - await op(); - } catch (e) { - notifications.toasts.addError(e, { - title: toastDrilldownsCRUDError, - }); - if (!isMounted) return; - setIsLoading(false); - return; - } - } - - async function createDrilldown( - action: UiActionsSerializedAction, - selectedTriggers: Array - ) { - await run(async () => { - await actionManager.createEvent(action, selectedTriggers); - notifications.toasts.addSuccess({ - title: toastDrilldownCreated.title, - text: toastDrilldownCreated.text(action.name), - }); - }); - } - - async function editDrilldown( - drilldownId: string, - action: UiActionsSerializedAction, - selectedTriggers: Array - ) { - await run(async () => { - await actionManager.updateEvent(drilldownId, action, selectedTriggers); - notifications.toasts.addSuccess({ - title: toastDrilldownEdited.title, - text: toastDrilldownEdited.text(action.name), - }); - }); - } - - async function deleteDrilldown(drilldownIds: string | string[]) { - await run(async () => { - drilldownIds = Array.isArray(drilldownIds) ? drilldownIds : [drilldownIds]; - await actionManager.deleteEvents(drilldownIds); - notifications.toasts.addSuccess( - drilldownIds.length === 1 - ? { - title: toastDrilldownDeleted.title, - text: toastDrilldownDeleted.text, - } - : { - title: toastDrilldownsDeleted.title, - text: toastDrilldownsDeleted.text(drilldownIds.length), - } - ); - }); - } - - return { drilldowns, isLoading, createDrilldown, editDrilldown, deleteDrilldown }; -} diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/i18n.ts b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/i18n.ts deleted file mode 100644 index 70f4d735e2a74..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/i18n.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const toastDrilldownCreated = { - title: i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownCreatedTitle', - { - defaultMessage: 'Drilldown created', - } - ), - text: (drilldownName: string) => - i18n.translate('xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownCreatedText', { - defaultMessage: 'You created "{drilldownName}"', - values: { - drilldownName, - }, - }), -}; - -export const toastDrilldownEdited = { - title: i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownEditedTitle', - { - defaultMessage: 'Drilldown edited', - } - ), - text: (drilldownName: string) => - i18n.translate('xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownEditedText', { - defaultMessage: 'You edited "{drilldownName}"', - values: { - drilldownName, - }, - }), -}; - -export const toastDrilldownDeleted = { - title: i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownDeletedTitle', - { - defaultMessage: 'Drilldown deleted', - } - ), - text: i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownDeletedText', - { - defaultMessage: 'You deleted a drilldown', - } - ), -}; - -export const toastDrilldownsDeleted = { - title: i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownsDeletedTitle', - { - defaultMessage: 'Drilldowns deleted', - } - ), - text: (n: number) => - i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownsDeletedText', - { - defaultMessage: 'You deleted {n} drilldowns', - values: { - n, - }, - } - ), -}; - -export const toastDrilldownsCRUDError = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownsCRUDErrorTitle', - { - defaultMessage: 'Error saving drilldown', - description: 'Title for generic error toast when persisting drilldown updates failed', - } -); - -export const toastDrilldownsFetchError = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.toast.drilldownsFetchErrorTitle', - { - defaultMessage: 'Error fetching drilldowns', - } -); diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/index.ts b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/index.ts deleted file mode 100644 index f084a3e563c23..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './connected_flyout_manage_drilldowns'; diff --git a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts b/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts deleted file mode 100644 index b8deaa8b842bc..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/connected_flyout_manage_drilldowns/test_data.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import uuid from 'uuid'; -import { - DynamicActionManager, - DynamicActionManagerState, - UiActionsSerializedAction, - TriggerContextMapping, -} from '../../../../../../src/plugins/ui_actions/public'; -import { createStateContainer } from '../../../../../../src/plugins/kibana_utils/common'; - -class MockDynamicActionManager implements PublicMethodsOf { - public readonly state = createStateContainer({ - isFetchingEvents: false, - fetchCount: 0, - events: [], - }); - - async count() { - return this.state.get().events.length; - } - - async list() { - return this.state.get().events; - } - - async createEvent( - action: UiActionsSerializedAction, - triggers: Array - ) { - const event = { - action, - triggers, - eventId: uuid(), - }; - const state = this.state.get(); - this.state.set({ - ...state, - events: [...state.events, event], - }); - } - - async deleteEvents(eventIds: string[]) { - const state = this.state.get(); - let events = state.events; - - eventIds.forEach(id => { - events = events.filter(e => e.eventId !== id); - }); - - this.state.set({ - ...state, - events, - }); - } - - async updateEvent( - eventId: string, - action: UiActionsSerializedAction, - triggers: Array - ) { - const state = this.state.get(); - const events = state.events; - const idx = events.findIndex(e => e.eventId === eventId); - const event = { - eventId, - action, - triggers, - }; - - this.state.set({ - ...state, - events: [...events.slice(0, idx), event, ...events.slice(idx + 1)], - }); - } - - async deleteEvent() { - throw new Error('not implemented'); - } - - async start() {} - async stop() {} -} - -export const mockDynamicActionManager = (new MockDynamicActionManager() as unknown) as DynamicActionManager; diff --git a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.story.tsx b/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.story.tsx index c4a4630397f1c..7a9e19342f27c 100644 --- a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.story.tsx +++ b/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.story.tsx @@ -8,16 +8,6 @@ import * as React from 'react'; import { storiesOf } from '@storybook/react'; import { DrilldownHelloBar } from '.'; -const Demo = () => { - const [show, setShow] = React.useState(true); - return show ? ( - { - setShow(false); - }} - /> - ) : null; -}; - -storiesOf('components/DrilldownHelloBar', module).add('default', () => ); +storiesOf('components/DrilldownHelloBar', module).add('default', () => { + return ; +}); diff --git a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.tsx b/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.tsx index 8c6739a8ad6c8..1ef714f7b86e2 100644 --- a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.tsx +++ b/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/drilldown_hello_bar.tsx @@ -5,58 +5,22 @@ */ import React from 'react'; -import { - EuiCallOut, - EuiFlexGroup, - EuiFlexItem, - EuiTextColor, - EuiText, - EuiLink, - EuiSpacer, - EuiButtonEmpty, - EuiIcon, -} from '@elastic/eui'; -import { txtHideHelpButtonLabel, txtHelpText, txtViewDocsLinkLabel } from './i18n'; export interface DrilldownHelloBarProps { docsLink?: string; - onHideClick?: () => void; } -export const WELCOME_MESSAGE_TEST_SUBJ = 'drilldowns-welcome-message-test-subj'; - -export const DrilldownHelloBar: React.FC = ({ - docsLink, - onHideClick = () => {}, -}) => { +/** + * @todo https://github.com/elastic/kibana/issues/55311 + */ +export const DrilldownHelloBar: React.FC = ({ docsLink }) => { return ( - - -
- -
-
- - - {txtHelpText} - - {docsLink && ( - <> - - {txtViewDocsLinkLabel} - - )} - - - - {txtHideHelpButtonLabel} - - - - } - /> +
+

+ Drilldowns provide the ability to define a new behavior when interacting with a panel. You + can add multiple options or simply override the default filtering behavior. +

+ View docs +
); }; diff --git a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/i18n.ts b/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/i18n.ts deleted file mode 100644 index 63dc95dabc0fb..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/drilldown_hello_bar/i18n.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const txtHelpText = i18n.translate( - 'xpack.drilldowns.components.DrilldownHelloBar.helpText', - { - defaultMessage: - 'Drilldowns provide the ability to define a new behavior when interacting with a panel. You can add multiple options or simply override the default filtering behavior.', - } -); - -export const txtViewDocsLinkLabel = i18n.translate( - 'xpack.drilldowns.components.DrilldownHelloBar.viewDocsLinkLabel', - { - defaultMessage: 'View docs', - } -); - -export const txtHideHelpButtonLabel = i18n.translate( - 'xpack.drilldowns.components.DrilldownHelloBar.hideHelpButtonLabel', - { - defaultMessage: 'Hide', - } -); diff --git a/x-pack/plugins/dashboard_enhanced/scripts/storybook.js b/x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.story.tsx similarity index 53% rename from x-pack/plugins/dashboard_enhanced/scripts/storybook.js rename to x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.story.tsx index f2cbe4135f4cb..5627a5d6f4522 100644 --- a/x-pack/plugins/dashboard_enhanced/scripts/storybook.js +++ b/x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.story.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { join } from 'path'; +import * as React from 'react'; +import { storiesOf } from '@storybook/react'; +import { DrilldownPicker } from '.'; -// eslint-disable-next-line -require('@kbn/storybook').runStorybookCli({ - name: 'dashboard_enhanced', - storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.story.tsx')], +storiesOf('components/DrilldownPicker', module).add('default', () => { + return ; }); diff --git a/x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.tsx b/x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.tsx new file mode 100644 index 0000000000000..3748fc666c81c --- /dev/null +++ b/x-pack/plugins/drilldowns/public/components/drilldown_picker/drilldown_picker.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +// eslint-disable-next-line +export interface DrilldownPickerProps {} + +export const DrilldownPicker: React.FC = () => { + return ( + + ); +}; diff --git a/x-pack/plugins/advanced_ui_actions/public/components/index.ts b/x-pack/plugins/drilldowns/public/components/drilldown_picker/index.tsx similarity index 87% rename from x-pack/plugins/advanced_ui_actions/public/components/index.ts rename to x-pack/plugins/drilldowns/public/components/drilldown_picker/index.tsx index 236b1a6ec4611..3be289fe6d46e 100644 --- a/x-pack/plugins/advanced_ui_actions/public/components/index.ts +++ b/x-pack/plugins/drilldowns/public/components/drilldown_picker/index.tsx @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './action_wizard'; +export * from './drilldown_picker'; diff --git a/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.story.tsx b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.story.tsx new file mode 100644 index 0000000000000..4f024b7d9cd6a --- /dev/null +++ b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.story.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* eslint-disable no-console */ + +import * as React from 'react'; +import { EuiFlyout } from '@elastic/eui'; +import { storiesOf } from '@storybook/react'; +import { FlyoutCreateDrilldown } from '.'; + +storiesOf('components/FlyoutCreateDrilldown', module) + .add('default', () => { + return ; + }) + .add('open in flyout', () => { + return ( + + + + ); + }); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.tsx b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.tsx new file mode 100644 index 0000000000000..b45ac9197c7e0 --- /dev/null +++ b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/flyout_create_drilldown.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiButton } from '@elastic/eui'; +import { FormCreateDrilldown } from '../form_create_drilldown'; +import { FlyoutFrame } from '../flyout_frame'; +import { txtCreateDrilldown } from './i18n'; +import { FlyoutCreateDrilldownActionContext } from '../../actions'; + +export interface FlyoutCreateDrilldownProps { + context: FlyoutCreateDrilldownActionContext; + onClose?: () => void; +} + +export const FlyoutCreateDrilldown: React.FC = ({ + context, + onClose, +}) => { + const footer = ( + {}} fill> + {txtCreateDrilldown} + + ); + + return ( + + + + ); +}; diff --git a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/i18n.ts b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/i18n.ts similarity index 62% rename from x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/i18n.ts rename to x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/i18n.ts index 0dd4e37d4dddd..ceabc6d3a9aa5 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/i18n.ts +++ b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/i18n.ts @@ -6,9 +6,9 @@ import { i18n } from '@kbn/i18n'; -export const txtManageDrilldowns = i18n.translate( - 'xpack.drilldowns.components.FlyoutListManageDrilldowns.manageDrilldownsTitle', +export const txtCreateDrilldown = i18n.translate( + 'xpack.drilldowns.components.FlyoutCreateDrilldown.CreateDrilldown', { - defaultMessage: 'Manage Drilldowns', + defaultMessage: 'Create drilldown', } ); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/index.ts b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/index.ts similarity index 84% rename from x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/index.ts rename to x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/index.ts index 96ed23bf112c9..ce235043b4ef6 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/index.ts +++ b/x-pack/plugins/drilldowns/public/components/flyout_create_drilldown/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './flyout_drilldown_wizard'; +export * from './flyout_create_drilldown'; diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx deleted file mode 100644 index 152cd393b9d3e..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -/* eslint-disable no-console */ - -import * as React from 'react'; -import { EuiFlyout } from '@elastic/eui'; -import { storiesOf } from '@storybook/react'; -import { FlyoutDrilldownWizard } from '.'; -import { - dashboardFactory, - urlFactory, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../advanced_ui_actions/public/components/action_wizard/test_data'; - -storiesOf('components/FlyoutDrilldownWizard', module) - .add('default', () => { - return ; - }) - .add('open in flyout - create', () => { - return ( - {}}> - {}} - drilldownActionFactories={[urlFactory, dashboardFactory]} - /> - - ); - }) - .add('open in flyout - edit', () => { - return ( - {}}> - {}} - drilldownActionFactories={[urlFactory, dashboardFactory]} - initialDrilldownWizardConfig={{ - name: 'My fancy drilldown', - actionFactory: urlFactory as any, - actionConfig: { - url: 'https://elastic.co', - openInNewTab: true, - }, - }} - mode={'edit'} - /> - - ); - }) - .add('open in flyout - edit, just 1 action type', () => { - return ( - {}}> - {}} - drilldownActionFactories={[dashboardFactory]} - initialDrilldownWizardConfig={{ - name: 'My fancy drilldown', - actionFactory: urlFactory as any, - actionConfig: { - url: 'https://elastic.co', - openInNewTab: true, - }, - }} - mode={'edit'} - /> - - ); - }); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx deleted file mode 100644 index faa965a98a4bb..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/flyout_drilldown_wizard.tsx +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useState } from 'react'; -import { EuiButton, EuiSpacer } from '@elastic/eui'; -import { FormDrilldownWizard } from '../form_drilldown_wizard'; -import { FlyoutFrame } from '../flyout_frame'; -import { - txtCreateDrilldownButtonLabel, - txtCreateDrilldownTitle, - txtDeleteDrilldownButtonLabel, - txtEditDrilldownButtonLabel, - txtEditDrilldownTitle, -} from './i18n'; -import { DrilldownHelloBar } from '../drilldown_hello_bar'; -import { AdvancedUiActionsActionFactory as ActionFactory } from '../../../../advanced_ui_actions/public'; - -export interface DrilldownWizardConfig { - name: string; - actionFactory?: ActionFactory; - actionConfig?: ActionConfig; -} - -export interface FlyoutDrilldownWizardProps { - drilldownActionFactories: Array>; - - onSubmit?: (drilldownWizardConfig: Required) => void; - onDelete?: () => void; - onClose?: () => void; - onBack?: () => void; - - mode?: 'create' | 'edit'; - initialDrilldownWizardConfig?: DrilldownWizardConfig; - - showWelcomeMessage?: boolean; - onWelcomeHideClick?: () => void; - - actionFactoryContext?: object; -} - -export function FlyoutDrilldownWizard({ - onClose, - onBack, - onSubmit = () => {}, - initialDrilldownWizardConfig, - mode = 'create', - onDelete = () => {}, - showWelcomeMessage = true, - onWelcomeHideClick, - drilldownActionFactories, - actionFactoryContext, -}: FlyoutDrilldownWizardProps) { - const [wizardConfig, setWizardConfig] = useState( - () => - initialDrilldownWizardConfig ?? { - name: '', - } - ); - - const isActionValid = ( - config: DrilldownWizardConfig - ): config is Required => { - if (!wizardConfig.name) return false; - if (!wizardConfig.actionFactory) return false; - if (!wizardConfig.actionConfig) return false; - - return wizardConfig.actionFactory.isConfigValid(wizardConfig.actionConfig); - }; - - const footer = ( - { - if (isActionValid(wizardConfig)) { - onSubmit(wizardConfig); - } - }} - fill - isDisabled={!isActionValid(wizardConfig)} - > - {mode === 'edit' ? txtEditDrilldownButtonLabel : txtCreateDrilldownButtonLabel} - - ); - - return ( - } - > - { - setWizardConfig({ - ...wizardConfig, - name: newName, - }); - }} - actionConfig={wizardConfig.actionConfig} - onActionConfigChange={newActionConfig => { - setWizardConfig({ - ...wizardConfig, - actionConfig: newActionConfig, - }); - }} - currentActionFactory={wizardConfig.actionFactory} - onActionFactoryChange={actionFactory => { - if (!actionFactory) { - setWizardConfig({ - ...wizardConfig, - actionFactory: undefined, - actionConfig: undefined, - }); - } else { - setWizardConfig({ - ...wizardConfig, - actionFactory, - actionConfig: actionFactory.createConfig(), - }); - } - }} - actionFactories={drilldownActionFactories} - actionFactoryContext={actionFactoryContext!} - /> - {mode === 'edit' && ( - <> - - - {txtDeleteDrilldownButtonLabel} - - - )} - - ); -} diff --git a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/i18n.ts b/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/i18n.ts deleted file mode 100644 index a4a2754a444ab..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_drilldown_wizard/i18n.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const txtCreateDrilldownTitle = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.createDrilldownTitle', - { - defaultMessage: 'Create Drilldown', - } -); - -export const txtEditDrilldownTitle = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.editDrilldownTitle', - { - defaultMessage: 'Edit Drilldown', - } -); - -export const txtCreateDrilldownButtonLabel = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.createDrilldownButtonLabel', - { - defaultMessage: 'Create drilldown', - } -); - -export const txtEditDrilldownButtonLabel = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.editDrilldownButtonLabel', - { - defaultMessage: 'Save', - } -); - -export const txtDeleteDrilldownButtonLabel = i18n.translate( - 'xpack.drilldowns.components.flyoutDrilldownWizard.deleteDrilldownButtonLabel', - { - defaultMessage: 'Delete drilldown', - } -); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.story.tsx b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.story.tsx index cb223db556f56..2715637f6392f 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.story.tsx +++ b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.story.tsx @@ -21,13 +21,6 @@ storiesOf('components/FlyoutFrame', module) .add('with onClose', () => { return console.log('onClose')}>test; }) - .add('with onBack', () => { - return ( - console.log('onClose')} title={'Title'}> - test - - ); - }) .add('custom footer', () => { return click me!}>test; }) diff --git a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.test.tsx b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.test.tsx index 0a3989487745f..b5fb52fcf5c18 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.test.tsx +++ b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.test.tsx @@ -6,11 +6,9 @@ import React from 'react'; import { render } from 'react-dom'; -import { render as renderTestingLibrary, fireEvent, cleanup } from '@testing-library/react/pure'; +import { render as renderTestingLibrary, fireEvent } from '@testing-library/react'; import { FlyoutFrame } from '.'; -afterEach(cleanup); - describe('', () => { test('renders without crashing', () => { const div = document.createElement('div'); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.tsx b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.tsx index b55cbd88d0dc0..2945cfd739482 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.tsx +++ b/x-pack/plugins/drilldowns/public/components/flyout_frame/flyout_frame.tsx @@ -13,16 +13,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, - EuiButtonIcon, } from '@elastic/eui'; -import { txtClose, txtBack } from './i18n'; +import { txtClose } from './i18n'; export interface FlyoutFrameProps { title?: React.ReactNode; footer?: React.ReactNode; - banner?: React.ReactNode; onClose?: () => void; - onBack?: () => void; } /** @@ -33,31 +30,11 @@ export const FlyoutFrame: React.FC = ({ footer, onClose, children, - onBack, - banner, }) => { - const headerFragment = (title || onBack) && ( + const headerFragment = title && ( - - {onBack && ( - -
- -
-
- )} - {title && ( - -

{title}

-
- )} -
+

{title}

); @@ -87,7 +64,7 @@ export const FlyoutFrame: React.FC = ({ return ( <> {headerFragment} - {children} + {children} {footerFragment} ); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_frame/i18n.ts b/x-pack/plugins/drilldowns/public/components/flyout_frame/i18n.ts index 23af89ebf9bc7..257d7d36dbee1 100644 --- a/x-pack/plugins/drilldowns/public/components/flyout_frame/i18n.ts +++ b/x-pack/plugins/drilldowns/public/components/flyout_frame/i18n.ts @@ -6,10 +6,6 @@ import { i18n } from '@kbn/i18n'; -export const txtClose = i18n.translate('xpack.drilldowns.components.FlyoutFrame.CloseButtonLabel', { +export const txtClose = i18n.translate('xpack.drilldowns.components.FlyoutFrame.Close', { defaultMessage: 'Close', }); - -export const txtBack = i18n.translate('xpack.drilldowns.components.FlyoutFrame.BackButtonLabel', { - defaultMessage: 'Back', -}); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.story.tsx b/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.story.tsx deleted file mode 100644 index 0529f0451b16a..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.story.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as React from 'react'; -import { EuiFlyout } from '@elastic/eui'; -import { storiesOf } from '@storybook/react'; -import { FlyoutListManageDrilldowns } from './flyout_list_manage_drilldowns'; - -storiesOf('components/FlyoutListManageDrilldowns', module).add('default', () => ( - {}}> - - -)); diff --git a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.tsx b/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.tsx deleted file mode 100644 index a44a7ccccb4dc..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/flyout_list_manage_drilldowns.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { FlyoutFrame } from '../flyout_frame'; -import { DrilldownListItem, ListManageDrilldowns } from '../list_manage_drilldowns'; -import { txtManageDrilldowns } from './i18n'; -import { DrilldownHelloBar } from '../drilldown_hello_bar'; - -export interface FlyoutListManageDrilldownsProps { - drilldowns: DrilldownListItem[]; - onClose?: () => void; - onCreate?: () => void; - onEdit?: (drilldownId: string) => void; - onDelete?: (drilldownIds: string[]) => void; - showWelcomeMessage?: boolean; - onWelcomeHideClick?: () => void; -} - -export function FlyoutListManageDrilldowns({ - drilldowns, - onClose = () => {}, - onCreate, - onDelete, - onEdit, - showWelcomeMessage = true, - onWelcomeHideClick, -}: FlyoutListManageDrilldownsProps) { - return ( - } - > - - - ); -} diff --git a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/index.ts b/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/index.ts deleted file mode 100644 index f8c9d224fb292..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/flyout_list_manage_drilldowns/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './flyout_list_manage_drilldowns'; diff --git a/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.story.tsx b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.story.tsx new file mode 100644 index 0000000000000..e7e1d67473e8c --- /dev/null +++ b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.story.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* eslint-disable no-console */ + +import * as React from 'react'; +import { EuiFlyout } from '@elastic/eui'; +import { storiesOf } from '@storybook/react'; +import { FormCreateDrilldown } from '.'; + +const DemoEditName: React.FC = () => { + const [name, setName] = React.useState(''); + + return ; +}; + +storiesOf('components/FormCreateDrilldown', module) + .add('default', () => { + return ; + }) + .add('[name=foobar]', () => { + return ; + }) + .add('can edit name', () => ) + .add('open in flyout', () => { + return ( + + + + ); + }); diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.test.tsx similarity index 70% rename from x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx rename to x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.test.tsx index 4560773cc8a6d..6691966e47e64 100644 --- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.test.tsx +++ b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.test.tsx @@ -6,23 +6,21 @@ import React from 'react'; import { render } from 'react-dom'; -import { FormDrilldownWizard } from './form_drilldown_wizard'; -import { render as renderTestingLibrary, fireEvent, cleanup } from '@testing-library/react/pure'; +import { FormCreateDrilldown } from '.'; +import { render as renderTestingLibrary, fireEvent } from '@testing-library/react'; import { txtNameOfDrilldown } from './i18n'; -afterEach(cleanup); - -describe('', () => { +describe('', () => { test('renders without crashing', () => { const div = document.createElement('div'); - render( {}} actionFactoryContext={{}} />, div); + render( {}} />, div); }); describe('[name=]', () => { test('if name not provided, uses to empty string', () => { const div = document.createElement('div'); - render(, div); + render(, div); const input = div.querySelector( '[data-test-subj="dynamicActionNameInput"]' @@ -31,10 +29,10 @@ describe('', () => { expect(input?.value).toBe(''); }); - test('can set initial name input field value', () => { + test('can set name input field value', () => { const div = document.createElement('div'); - render(, div); + render(, div); const input = div.querySelector( '[data-test-subj="dynamicActionNameInput"]' @@ -42,7 +40,7 @@ describe('', () => { expect(input?.value).toBe('foo'); - render(, div); + render(, div); expect(input?.value).toBe('bar'); }); @@ -50,7 +48,7 @@ describe('', () => { test('fires onNameChange callback on name change', () => { const onNameChange = jest.fn(); const utils = renderTestingLibrary( - + ); const input = utils.getByLabelText(txtNameOfDrilldown); diff --git a/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.tsx b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.tsx new file mode 100644 index 0000000000000..4422de604092b --- /dev/null +++ b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/form_create_drilldown.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiForm, EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { DrilldownHelloBar } from '../drilldown_hello_bar'; +import { txtNameOfDrilldown, txtUntitledDrilldown, txtDrilldownAction } from './i18n'; +import { DrilldownPicker } from '../drilldown_picker'; + +const noop = () => {}; + +export interface FormCreateDrilldownProps { + name?: string; + onNameChange?: (name: string) => void; +} + +export const FormCreateDrilldown: React.FC = ({ + name = '', + onNameChange = noop, +}) => { + const nameFragment = ( + + onNameChange(event.target.value)} + data-test-subj="dynamicActionNameInput" + /> + + ); + + const triggerPicker =
Trigger Picker will be here
; + const actionPicker = ( + + + + ); + + return ( + <> + + {nameFragment} + {triggerPicker} + {actionPicker} + + ); +}; diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/i18n.ts b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/i18n.ts similarity index 89% rename from x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/i18n.ts rename to x-pack/plugins/drilldowns/public/components/form_create_drilldown/i18n.ts index e9b19ab0afa97..4c0e287935edd 100644 --- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/i18n.ts +++ b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/i18n.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; export const txtNameOfDrilldown = i18n.translate( 'xpack.drilldowns.components.FormCreateDrilldown.nameOfDrilldown', { - defaultMessage: 'Name', + defaultMessage: 'Name of drilldown', } ); @@ -23,6 +23,6 @@ export const txtUntitledDrilldown = i18n.translate( export const txtDrilldownAction = i18n.translate( 'xpack.drilldowns.components.FormCreateDrilldown.drilldownAction', { - defaultMessage: 'Action', + defaultMessage: 'Drilldown action', } ); diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/index.tsx b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/index.tsx similarity index 85% rename from x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/index.tsx rename to x-pack/plugins/drilldowns/public/components/form_create_drilldown/index.tsx index 4aea824de00d7..c2c5a7e435b39 100644 --- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/index.tsx +++ b/x-pack/plugins/drilldowns/public/components/form_create_drilldown/index.tsx @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './form_drilldown_wizard'; +export * from './form_create_drilldown'; diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.story.tsx b/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.story.tsx deleted file mode 100644 index 2fc35eb6b5298..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.story.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as React from 'react'; -import { storiesOf } from '@storybook/react'; -import { FormDrilldownWizard } from '.'; - -const DemoEditName: React.FC = () => { - const [name, setName] = React.useState(''); - - return ( - <> - {' '} -
name: {name}
- - ); -}; - -storiesOf('components/FormDrilldownWizard', module) - .add('default', () => { - return ; - }) - .add('[name=foobar]', () => { - return ; - }) - .add('can edit name', () => ); diff --git a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx b/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx deleted file mode 100644 index bdafaaf07873c..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/form_drilldown_wizard/form_drilldown_wizard.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiFieldText, EuiForm, EuiFormRow, EuiSpacer } from '@elastic/eui'; -import { txtDrilldownAction, txtNameOfDrilldown, txtUntitledDrilldown } from './i18n'; -import { - AdvancedUiActionsActionFactory as ActionFactory, - ActionWizard, -} from '../../../../advanced_ui_actions/public'; - -const noopFn = () => {}; - -export interface FormDrilldownWizardProps { - name?: string; - onNameChange?: (name: string) => void; - - currentActionFactory?: ActionFactory; - onActionFactoryChange?: (actionFactory: ActionFactory | null) => void; - actionFactoryContext: object; - - actionConfig?: object; - onActionConfigChange?: (config: object) => void; - - actionFactories?: ActionFactory[]; -} - -export const FormDrilldownWizard: React.FC = ({ - name = '', - actionConfig, - currentActionFactory, - onNameChange = noopFn, - onActionConfigChange = noopFn, - onActionFactoryChange = noopFn, - actionFactories = [], - actionFactoryContext, -}) => { - const nameFragment = ( - - onNameChange(event.target.value)} - data-test-subj="dynamicActionNameInput" - /> - - ); - - const actionWizard = ( - 1 ? txtDrilldownAction : undefined} - fullWidth={true} - > - onActionFactoryChange(actionFactory)} - onConfigChange={config => onActionConfigChange(config)} - context={actionFactoryContext} - /> - - ); - - return ( - <> - - {nameFragment} - - {actionWizard} - - - ); -}; diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts deleted file mode 100644 index fbc7c9dcfb4a1..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/i18n.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -export const txtCreateDrilldown = i18n.translate( - 'xpack.drilldowns.components.ListManageDrilldowns.createDrilldownButtonLabel', - { - defaultMessage: 'Create new', - } -); - -export const txtEditDrilldown = i18n.translate( - 'xpack.drilldowns.components.ListManageDrilldowns.editDrilldownButtonLabel', - { - defaultMessage: 'Edit', - } -); - -export const txtDeleteDrilldowns = (count: number) => - i18n.translate('xpack.drilldowns.components.ListManageDrilldowns.deleteDrilldownsButtonLabel', { - defaultMessage: 'Delete ({count})', - values: { - count, - }, - }); - -export const txtSelectDrilldown = i18n.translate( - 'xpack.drilldowns.components.ListManageDrilldowns.selectThisDrilldownCheckboxLabel', - { - defaultMessage: 'Select this drilldown', - } -); diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx deleted file mode 100644 index 82b6ce27af6d4..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './list_manage_drilldowns'; diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx deleted file mode 100644 index eafe50bab2016..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.story.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as React from 'react'; -import { storiesOf } from '@storybook/react'; -import { ListManageDrilldowns } from './list_manage_drilldowns'; - -storiesOf('components/ListManageDrilldowns', module).add('default', () => ( - -)); diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx deleted file mode 100644 index 4a4d67b08b1d3..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { cleanup, fireEvent, render } from '@testing-library/react/pure'; -import '@testing-library/jest-dom/extend-expect'; // TODO: this should be global -import { - DrilldownListItem, - ListManageDrilldowns, - TEST_SUBJ_DRILLDOWN_ITEM, -} from './list_manage_drilldowns'; - -// TODO: for some reason global cleanup from RTL doesn't work -// afterEach is not available for it globally during setup -afterEach(cleanup); - -const drilldowns: DrilldownListItem[] = [ - { id: '1', actionName: 'Dashboard', drilldownName: 'Drilldown 1' }, - { id: '2', actionName: 'Dashboard', drilldownName: 'Drilldown 2' }, - { id: '3', actionName: 'Dashboard', drilldownName: 'Drilldown 3' }, -]; - -test('Render list of drilldowns', () => { - const screen = render(); - expect(screen.getAllByTestId(TEST_SUBJ_DRILLDOWN_ITEM)).toHaveLength(drilldowns.length); -}); - -test('Emit onEdit() when clicking on edit drilldown', () => { - const fn = jest.fn(); - const screen = render(); - - const editButtons = screen.getAllByText('Edit'); - expect(editButtons).toHaveLength(drilldowns.length); - fireEvent.click(editButtons[1]); - expect(fn).toBeCalledWith(drilldowns[1].id); -}); - -test('Emit onCreate() when clicking on create drilldown', () => { - const fn = jest.fn(); - const screen = render(); - fireEvent.click(screen.getByText('Create new')); - expect(fn).toBeCalled(); -}); - -test('Delete button is not visible when non is selected', () => { - const fn = jest.fn(); - const screen = render(); - expect(screen.queryByText(/Delete/i)).not.toBeInTheDocument(); - expect(screen.queryByText(/Create/i)).toBeInTheDocument(); -}); - -test('Can delete drilldowns', () => { - const fn = jest.fn(); - const screen = render(); - - const checkboxes = screen.getAllByLabelText(/Select this drilldown/i); - expect(checkboxes).toHaveLength(3); - - fireEvent.click(checkboxes[1]); - fireEvent.click(checkboxes[2]); - - expect(screen.queryByText(/Create/i)).not.toBeInTheDocument(); - - fireEvent.click(screen.getByText(/Delete \(2\)/i)); - - expect(fn).toBeCalledWith([drilldowns[1].id, drilldowns[2].id]); -}); diff --git a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx b/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx deleted file mode 100644 index 5a15781a1faf2..0000000000000 --- a/x-pack/plugins/drilldowns/public/components/list_manage_drilldowns/list_manage_drilldowns.tsx +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - EuiBasicTable, - EuiBasicTableColumn, - EuiButton, - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiSpacer, - EuiTextColor, -} from '@elastic/eui'; -import React, { useState } from 'react'; -import { - txtCreateDrilldown, - txtDeleteDrilldowns, - txtEditDrilldown, - txtSelectDrilldown, -} from './i18n'; - -export interface DrilldownListItem { - id: string; - actionName: string; - drilldownName: string; - icon?: string; -} - -export interface ListManageDrilldownsProps { - drilldowns: DrilldownListItem[]; - - onEdit?: (id: string) => void; - onCreate?: () => void; - onDelete?: (ids: string[]) => void; -} - -const noop = () => {}; - -export const TEST_SUBJ_DRILLDOWN_ITEM = 'list-manage-drilldowns-item'; - -export function ListManageDrilldowns({ - drilldowns, - onEdit = noop, - onCreate = noop, - onDelete = noop, -}: ListManageDrilldownsProps) { - const [selectedDrilldowns, setSelectedDrilldowns] = useState([]); - - const columns: Array> = [ - { - field: 'drilldownName', - name: 'Name', - truncateText: true, - width: '50%', - }, - { - name: 'Action', - render: (drilldown: DrilldownListItem) => ( - - {drilldown.icon && ( - - - - )} - - {drilldown.actionName} - - - ), - }, - { - align: 'right', - render: (drilldown: DrilldownListItem) => ( - onEdit(drilldown.id)}> - {txtEditDrilldown} - - ), - }, - ]; - - return ( - <> - { - setSelectedDrilldowns(selection.map(drilldown => drilldown.id)); - }, - selectableMessage: () => txtSelectDrilldown, - }} - rowProps={{ - 'data-test-subj': TEST_SUBJ_DRILLDOWN_ITEM, - }} - hasActions={true} - /> - - {selectedDrilldowns.length === 0 ? ( - onCreate()}> - {txtCreateDrilldown} - - ) : ( - onDelete(selectedDrilldowns)}> - {txtDeleteDrilldowns(selectedDrilldowns.length)} - - )} - - ); -} diff --git a/x-pack/plugins/drilldowns/public/index.ts b/x-pack/plugins/drilldowns/public/index.ts index 044e29c671de4..63e7a12235462 100644 --- a/x-pack/plugins/drilldowns/public/index.ts +++ b/x-pack/plugins/drilldowns/public/index.ts @@ -7,14 +7,12 @@ import { DrilldownsPlugin } from './plugin'; export { - SetupContract as DrilldownsSetup, - SetupDependencies as DrilldownsSetupDependencies, - StartContract as DrilldownsStart, - StartDependencies as DrilldownsStartDependencies, + DrilldownsSetupContract, + DrilldownsSetupDependencies, + DrilldownsStartContract, + DrilldownsStartDependencies, } from './plugin'; export function plugin() { return new DrilldownsPlugin(); } - -export { DrilldownDefinition } from './types'; diff --git a/x-pack/plugins/drilldowns/public/mocks.ts b/x-pack/plugins/drilldowns/public/mocks.ts index 18816243a3572..bfade1674072a 100644 --- a/x-pack/plugins/drilldowns/public/mocks.ts +++ b/x-pack/plugins/drilldowns/public/mocks.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DrilldownsSetup, DrilldownsStart } from '.'; +import { DrilldownsSetupContract, DrilldownsStartContract } from '.'; -export type Setup = jest.Mocked; -export type Start = jest.Mocked; +export type Setup = jest.Mocked; +export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { @@ -17,14 +17,12 @@ const createSetupContract = (): Setup => { }; const createStartContract = (): Start => { - const startContract: Start = { - FlyoutManageDrilldowns: jest.fn(), - }; + const startContract: Start = {}; return startContract; }; -export const drilldownsPluginMock = { +export const bfetchPluginMock = { createSetupContract, createStartContract, }; diff --git a/x-pack/plugins/drilldowns/public/plugin.ts b/x-pack/plugins/drilldowns/public/plugin.ts index bbc06847d5842..b89172541b91e 100644 --- a/x-pack/plugins/drilldowns/public/plugin.ts +++ b/x-pack/plugins/drilldowns/public/plugin.ts @@ -6,46 +6,52 @@ import { CoreStart, CoreSetup, Plugin } from 'src/core/public'; import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public'; -import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../advanced_ui_actions/public'; -import { DrilldownService, DrilldownServiceSetupContract } from './services'; -import { createFlyoutManageDrilldowns } from './components/connected_flyout_manage_drilldowns'; -import { Storage } from '../../../../src/plugins/kibana_utils/public'; - -export interface SetupDependencies { +import { DrilldownService } from './service'; +import { + FlyoutCreateDrilldownActionContext, + FlyoutEditDrilldownActionContext, + OPEN_FLYOUT_ADD_DRILLDOWN, + OPEN_FLYOUT_EDIT_DRILLDOWN, +} from './actions'; + +export interface DrilldownsSetupDependencies { uiActions: UiActionsSetup; - advancedUiActions: AdvancedUiActionsSetup; } -export interface StartDependencies { +export interface DrilldownsStartDependencies { uiActions: UiActionsStart; - advancedUiActions: AdvancedUiActionsStart; } -export type SetupContract = DrilldownServiceSetupContract; +export type DrilldownsSetupContract = Pick; // eslint-disable-next-line -export interface StartContract { - FlyoutManageDrilldowns: ReturnType; +export interface DrilldownsStartContract {} + +declare module '../../../../src/plugins/ui_actions/public' { + export interface ActionContextMapping { + [OPEN_FLYOUT_ADD_DRILLDOWN]: FlyoutCreateDrilldownActionContext; + [OPEN_FLYOUT_EDIT_DRILLDOWN]: FlyoutEditDrilldownActionContext; + } } export class DrilldownsPlugin - implements Plugin { + implements + Plugin< + DrilldownsSetupContract, + DrilldownsStartContract, + DrilldownsSetupDependencies, + DrilldownsStartDependencies + > { private readonly service = new DrilldownService(); - public setup(core: CoreSetup, plugins: SetupDependencies): SetupContract { - const setup = this.service.setup(core, plugins); + public setup(core: CoreSetup, plugins: DrilldownsSetupDependencies): DrilldownsSetupContract { + this.service.bootstrap(core, plugins); - return setup; + return this.service; } - public start(core: CoreStart, plugins: StartDependencies): StartContract { - return { - FlyoutManageDrilldowns: createFlyoutManageDrilldowns({ - advancedUiActions: plugins.advancedUiActions, - storage: new Storage(localStorage), - notifications: core.notifications, - }), - }; + public start(core: CoreStart, plugins: DrilldownsStartDependencies): DrilldownsStartContract { + return {}; } public stop() {} diff --git a/x-pack/plugins/drilldowns/public/service/drilldown_service.ts b/x-pack/plugins/drilldowns/public/service/drilldown_service.ts new file mode 100644 index 0000000000000..7745c30b4e335 --- /dev/null +++ b/x-pack/plugins/drilldowns/public/service/drilldown_service.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 { CoreSetup } from 'src/core/public'; +// import { CONTEXT_MENU_TRIGGER } from '../../../../../src/plugins/embeddable/public'; +import { FlyoutCreateDrilldownAction, FlyoutEditDrilldownAction } from '../actions'; +import { DrilldownsSetupDependencies } from '../plugin'; + +export class DrilldownService { + bootstrap(core: CoreSetup, { uiActions }: DrilldownsSetupDependencies) { + const overlays = async () => (await core.getStartServices())[0].overlays; + + const actionFlyoutCreateDrilldown = new FlyoutCreateDrilldownAction({ overlays }); + uiActions.registerAction(actionFlyoutCreateDrilldown); + // uiActions.attachAction(CONTEXT_MENU_TRIGGER, actionFlyoutCreateDrilldown); + + const actionFlyoutEditDrilldown = new FlyoutEditDrilldownAction({ overlays }); + uiActions.registerAction(actionFlyoutEditDrilldown); + // uiActions.attachAction(CONTEXT_MENU_TRIGGER, actionFlyoutEditDrilldown); + } + + /** + * Convenience method to register a drilldown. (It should set-up all the + * necessary triggers and actions.) + */ + registerDrilldown = (): void => { + throw new Error('not implemented'); + }; +} diff --git a/x-pack/plugins/drilldowns/public/services/index.ts b/x-pack/plugins/drilldowns/public/service/index.ts similarity index 100% rename from x-pack/plugins/drilldowns/public/services/index.ts rename to x-pack/plugins/drilldowns/public/service/index.ts diff --git a/x-pack/plugins/drilldowns/public/services/drilldown_service.ts b/x-pack/plugins/drilldowns/public/services/drilldown_service.ts deleted file mode 100644 index bfbe514d46095..0000000000000 --- a/x-pack/plugins/drilldowns/public/services/drilldown_service.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup } from 'src/core/public'; -import { AdvancedUiActionsSetup } from '../../../advanced_ui_actions/public'; -import { DrilldownDefinition, DrilldownFactoryContext } from '../types'; -import { UiActionsActionFactoryDefinition as ActionFactoryDefinition } from '../../../../../src/plugins/ui_actions/public'; - -export interface DrilldownServiceSetupDeps { - advancedUiActions: AdvancedUiActionsSetup; -} - -export interface DrilldownServiceSetupContract { - /** - * Convenience method to register a drilldown. - */ - registerDrilldown: < - Config extends object = object, - CreationContext extends object = object, - ExecutionContext extends object = object - >( - drilldown: DrilldownDefinition - ) => void; -} - -export class DrilldownService { - setup( - core: CoreSetup, - { advancedUiActions }: DrilldownServiceSetupDeps - ): DrilldownServiceSetupContract { - const registerDrilldown = < - Config extends object = object, - CreationContext extends object = object, - ExecutionContext extends object = object - >({ - id: factoryId, - CollectConfig, - createConfig, - isConfigValid, - getDisplayName, - euiIcon, - execute, - }: DrilldownDefinition) => { - const actionFactory: ActionFactoryDefinition< - Config, - DrilldownFactoryContext, - ExecutionContext - > = { - id: factoryId, - CollectConfig, - createConfig, - isConfigValid, - getDisplayName, - getIconType: () => euiIcon, - isCompatible: async () => true, - create: serializedAction => ({ - id: '', - type: factoryId, - getIconType: () => euiIcon, - getDisplayName: () => serializedAction.name, - execute: async context => await execute(serializedAction.config, context), - }), - } as ActionFactoryDefinition< - Config, - DrilldownFactoryContext, - ExecutionContext - >; - - advancedUiActions.registerActionFactory(actionFactory); - }; - - return { - registerDrilldown, - }; - } -} diff --git a/x-pack/plugins/drilldowns/public/types.ts b/x-pack/plugins/drilldowns/public/types.ts deleted file mode 100644 index a8232887f9ca6..0000000000000 --- a/x-pack/plugins/drilldowns/public/types.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { AdvancedUiActionsActionFactoryDefinition as ActionFactoryDefinition } from '../../advanced_ui_actions/public'; - -/** - * This is a convenience interface to register a drilldown. Drilldown has - * ability to collect configuration from user. Once drilldown is executed it - * receives the collected information together with the context of the - * user's interaction. - * - * `Config` is a serializable object containing the configuration that the - * drilldown is able to collect using UI. - * - * `PlaceContext` is an object that the app that opens drilldown management - * flyout provides to the React component, specifying the contextual information - * about that app. For example, on Dashboard app this context contains - * information about the current embeddable and dashboard. - * - * `ExecutionContext` is an object created in response to user's interaction - * and provided to the `execute` function of the drilldown. This object contains - * information about the action user performed. - */ -export interface DrilldownDefinition< - Config extends object = object, - PlaceContext extends object = object, - ExecutionContext extends object = object -> { - /** - * Globally unique identifier for this drilldown. - */ - id: string; - - /** - * Function that returns default config for this drilldown. - */ - createConfig: ActionFactoryDefinition< - Config, - DrilldownFactoryContext, - ExecutionContext - >['createConfig']; - - /** - * `UiComponent` that collections config for this drilldown. You can create - * a React component and transform it `UiComponent` using `uiToReactComponent` - * helper from `kibana_utils` plugin. - * - * ```tsx - * import React from 'react'; - * import { uiToReactComponent } from 'src/plugins/kibana_utils'; - * import { UiActionsCollectConfigProps as CollectConfigProps } from 'src/plugins/ui_actions/public'; - * - * type Props = CollectConfigProps; - * - * const ReactCollectConfig: React.FC = () => { - * return
Collecting config...'
; - * }; - * - * export const CollectConfig = uiToReactComponent(ReactCollectConfig); - * ``` - */ - CollectConfig: ActionFactoryDefinition< - Config, - DrilldownFactoryContext, - ExecutionContext - >['CollectConfig']; - - /** - * A validator function for the config object. Should always return a boolean - * given any input. - */ - isConfigValid: ActionFactoryDefinition< - Config, - DrilldownFactoryContext, - ExecutionContext - >['isConfigValid']; - - /** - * Name of EUI icon to display when showing this drilldown to user. - */ - euiIcon?: string; - - /** - * Should return an internationalized name of the drilldown, which will be - * displayed to the user. - */ - getDisplayName: () => string; - - /** - * Implements the "navigation" action of the drilldown. This happens when - * user clicks something in the UI that executes a trigger to which this - * drilldown was attached. - * - * @param config Config object that user configured this drilldown with. - * @param context Object that represents context in which the underlying - * `UIAction` of this drilldown is being executed in. - */ - execute(config: Config, context: ExecutionContext): void; -} - -/** - * Context object used when creating a drilldown. - */ -export interface DrilldownFactoryContext { - /** - * Context provided to the drilldown factory by the place where the UI is - * rendered. For example, for the "dashboard" place, this context contains - * the ID of the current dashboard, which could be used for filtering it out - * of the list. - */ - placeContext: T; - - /** - * List of triggers that user selected in the UI. - */ - triggers: string[]; -} diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts index d101b55d6ad37..f691e62b9352a 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts @@ -743,6 +743,34 @@ describe('#bulkGet', () => { undefined ); }); + + it('redirects request to underlying base client and return errors result if type is registered', async () => { + const mockedResponse = { + saved_objects: [ + { + id: 'bad', + type: 'known-type', + error: { statusCode: 404, message: 'Not found' }, + }, + ], + total: 1, + per_page: 1, + page: 1, + }; + mockBaseClient.bulkGet.mockResolvedValue(mockedResponse as any); + const bulkGetParams = [{ type: 'known-type', id: 'bad' }]; + + const options = { namespace: 'some-ns' }; + await expect(wrapper.bulkGet(bulkGetParams, options)).resolves.toEqual({ + ...mockedResponse, + saved_objects: [ + { + ...mockedResponse.saved_objects[0], + }, + ], + }); + expect(mockBaseClient.bulkGet).toHaveBeenCalledTimes(1); + }); }); describe('#get', () => { diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts index 849bfda2bc86f..b4f1de52c9ce3 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts @@ -195,7 +195,7 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon private stripEncryptedAttributesFromResponse( response: T ): T { - if (this.options.service.isRegistered(response.type)) { + if (this.options.service.isRegistered(response.type) && response.attributes) { response.attributes = this.options.service.stripEncryptedAttributes( response.type, response.attributes as Record @@ -214,7 +214,7 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon T extends SavedObjectsBulkResponse | SavedObjectsFindResponse | SavedObjectsBulkUpdateResponse >(response: T): T { for (const savedObject of response.saved_objects) { - if (this.options.service.isRegistered(savedObject.type)) { + if (this.options.service.isRegistered(savedObject.type) && savedObject.attributes) { savedObject.attributes = this.options.service.stripEncryptedAttributes( savedObject.type, savedObject.attributes as Record diff --git a/x-pack/plugins/endpoint/common/schema/alert_index.ts b/x-pack/plugins/endpoint/common/schema/alert_index.ts index ca27bb646d625..7b48780f2d86b 100644 --- a/x-pack/plugins/endpoint/common/schema/alert_index.ts +++ b/x-pack/plugins/endpoint/common/schema/alert_index.ts @@ -18,6 +18,7 @@ export const alertingIndexGetQuerySchema = schema.object( schema.number({ min: 1, max: 100, + defaultValue: EndpointAppConstants.ALERT_LIST_DEFAULT_PAGE_SIZE, }) ), page_index: schema.maybe( @@ -37,6 +38,7 @@ export const alertingIndexGetQuerySchema = schema.object( maxSize: 2, }) as Type<[string, string]> // Cast this to a string tuple. `@kbn/config-schema` doesn't do this automatically ), + empty_string_is_undefined: schema.maybe(schema.boolean()), sort: schema.maybe(schema.string()), order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), query: schema.maybe( @@ -103,18 +105,6 @@ export const alertingIndexGetQuerySchema = schema.object( defaultMessage: '[before] cannot be used with [after]', }); } - if ( - value.before !== undefined && - value.sort !== undefined && - value.sort !== EndpointAppConstants.ALERT_LIST_DEFAULT_SORT - ) { - return i18n.translate( - 'xpack.endpoint.alerts.errors.before_cannot_be_used_with_custom_sort', - { - defaultMessage: '[before] cannot be used with custom sort', - } - ); - } }, } ); diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts index 7e4cf3d700ec8..b3eb518e35ae3 100644 --- a/x-pack/plugins/endpoint/common/types.ts +++ b/x-pack/plugins/endpoint/common/types.ts @@ -44,6 +44,7 @@ export class EndpointAppConstants { **/ static ALERT_LIST_DEFAULT_PAGE_SIZE = 10; static ALERT_LIST_DEFAULT_SORT = '@timestamp'; + static MAX_LONG_INT = '9223372036854775807'; // 2^63-1 } export interface AlertResultList { @@ -238,11 +239,19 @@ interface AlertMetadata { prev: string | null; } +interface AlertState { + state: { + host_metadata: HostMetadata; + }; +} + /** * Union of alert data and metadata. */ export type AlertData = AlertEvent & AlertMetadata; +export type AlertDetails = AlertData & AlertState; + export type HostMetadata = Immutable<{ '@timestamp': number; event: { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/link_to_app.test.tsx.snap b/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/link_to_app.test.tsx.snap new file mode 100644 index 0000000000000..6838b673b90d8 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/link_to_app.test.tsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LinkToApp component should render with href 1`] = ` + + + + link + + + +`; + +exports[`LinkToApp component should render with minimum input 1`] = ` + + + + + +`; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/page_view.test.tsx.snap b/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/page_view.test.tsx.snap new file mode 100644 index 0000000000000..34420e653049c --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/page_view.test.tsx.snap @@ -0,0 +1,646 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageView component should display body header custom element 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + body header +

+ } +> + + +
+ +
+ + +
+ +
+ +
+

+ body header +

+
+
+
+
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should display body header wrapped in EuiTitle 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ + +
+ +
+ +
+ +

+ body header +

+
+
+
+
+
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should display header left and right 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ +
+ +
+ +

+ page title +

+
+
+
+ +
+ right side actions +
+
+
+
+ + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should display only body if not header props used 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should display only header left 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ +
+ +
+ +

+ page title +

+
+
+
+
+
+ + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should display only header right but include an empty left side 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ +
+ +
+ + +
+ right side actions +
+
+
+ + + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should pass through EuiPage props 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + + +
+ +
+ + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`PageView component should use custom element for header left and not wrap in EuiTitle 1`] = ` +.c0 { + padding: 0; +} + +.c0 .endpoint-header { + padding: 24px; +} + +.c0 .endpoint-page-content { + border-left: none; + border-right: none; +} + + + title here +

+ } +> + + +
+ +
+ +
+ +
+

+ title here +

+
+
+
+
+ + +
+ +
+ body content +
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx index 1bafcbec93f5f..3fb06d6b4a56e 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { MouseEvent } from 'react'; +import React, { MouseEvent, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiTabs, EuiTab } from '@elastic/eui'; import { useHistory, useLocation } from 'react-router-dom'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; export interface NavTabs { name: string; @@ -46,30 +47,33 @@ export const navTabs: NavTabs[] = [ }, ]; -export const HeaderNavigation: React.FunctionComponent<{ basename: string }> = React.memo( - ({ basename }) => { - const history = useHistory(); - const location = useLocation(); +export const HeaderNavigation: React.FunctionComponent = React.memo(() => { + const history = useHistory(); + const location = useLocation(); + const { services } = useKibana(); + const BASE_PATH = services.application.getUrlForApp('endpoint'); - function renderNavTabs(tabs: NavTabs[]) { - return tabs.map((tab, index) => { - return ( - { - event.preventDefault(); - history.push(tab.href); - }} - isSelected={tab.href === location.pathname} - > - {tab.name} - - ); - }); - } + const tabList = useMemo(() => { + return navTabs.map((tab, index) => { + return ( + { + event.preventDefault(); + history.push(tab.href); + }} + isSelected={ + tab.href === location.pathname || + (tab.href !== '/' && location.pathname.startsWith(tab.href)) + } + > + {tab.name} + + ); + }); + }, [BASE_PATH, history, location.pathname]); - return {renderNavTabs(navTabs)}; - } -); + return {tabList}; +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx new file mode 100644 index 0000000000000..902c215434aac --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { LinkToApp } from './link_to_app'; +import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public'; +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { CoreStart } from 'kibana/public'; + +describe('LinkToApp component', () => { + let fakeCoreStart: jest.Mocked; + const render = (ui: Parameters[0]) => + mount(ui, { + wrappingComponent: KibanaContextProvider, + wrappingComponentProps: { + services: { application: fakeCoreStart.application }, + }, + }); + + beforeEach(() => { + fakeCoreStart = coreMock.createStart(); + }); + + it('should render with minimum input', () => { + expect(render(link)).toMatchSnapshot(); + }); + it('should render with href', () => { + expect( + render( + + link + + ) + ).toMatchSnapshot(); + }); + it('should support onClick prop', () => { + const spyOnClickHandler = jest.fn(); + const renderResult = render( + + link + + ); + + renderResult.find('EuiLink').simulate('click', { button: 0 }); + const clickEventArg = spyOnClickHandler.mock.calls[0][0]; + + expect(spyOnClickHandler).toHaveBeenCalled(); + expect(clickEventArg.preventDefault).toBeInstanceOf(Function); + expect(clickEventArg.isDefaultPrevented()).toBe(true); + expect(fakeCoreStart.application.navigateToApp).toHaveBeenCalledWith('ingestManager', { + path: undefined, + state: undefined, + }); + }); + it('should navigate to App with specific path', () => { + const renderResult = render( + + link + + ); + renderResult.find('EuiLink').simulate('click', { button: 0 }); + expect(fakeCoreStart.application.navigateToApp).toHaveBeenCalledWith('ingestManager', { + path: '/some/path', + state: undefined, + }); + }); + it('should passes through EuiLinkProps', () => { + const renderResult = render( + + link + + ); + expect(renderResult.find('EuiLink').props()).toEqual({ + children: 'link', + className: 'my-class', + color: 'primary', + 'data-test-subj': 'my-test-subject', + href: '/app/ingest', + onClick: expect.any(Function), + }); + }); + it('should still preventDefault if onClick callback throws', () => { + const spyOnClickHandler = jest.fn(ev => { + throw new Error('test'); + }); + const renderResult = render( + + link + + ); + expect(() => renderResult.find('EuiLink').simulate('click')).toThrow(); + const clickEventArg = spyOnClickHandler.mock.calls[0][0]; + expect(clickEventArg.isDefaultPrevented()).toBe(true); + }); + it('should not navigate if onClick callback prevents defalut', () => { + const spyOnClickHandler = jest.fn(ev => { + ev.preventDefault(); + }); + const renderResult = render( + + link + + ); + renderResult.find('EuiLink').simulate('click', { button: 0 }); + expect(fakeCoreStart.application.navigateToApp).not.toHaveBeenCalled(); + }); + it('should not to navigate if it was not left click', () => { + const renderResult = render(link); + renderResult.find('EuiLink').simulate('click', { button: 1 }); + expect(fakeCoreStart.application.navigateToApp).not.toHaveBeenCalled(); + }); + it('should not to navigate if it includes an anchor target', () => { + const renderResult = render( + + link + + ); + renderResult.find('EuiLink').simulate('click', { button: 0 }); + expect(fakeCoreStart.application.navigateToApp).not.toHaveBeenCalled(); + }); + it('should not to navigate if if meta|alt|ctrl|shift keys are pressed', () => { + const renderResult = render( + + link + + ); + const euiLink = renderResult.find('EuiLink'); + ['meta', 'alt', 'ctrl', 'shift'].forEach(key => { + euiLink.simulate('click', { button: 0, [`${key}Key`]: true }); + expect(fakeCoreStart.application.navigateToApp).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx new file mode 100644 index 0000000000000..b110d32442c2c --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo, MouseEventHandler } from 'react'; +import { EuiLink } from '@elastic/eui'; +import { EuiLinkProps } from '@elastic/eui'; +import { useNavigateToAppEventHandler } from '../hooks/use_navigate_to_app_event_handler'; + +export type LinkToAppProps = EuiLinkProps & { + /** the app id - normally the value of the `id` in that plugin's `kibana.json` */ + appId: string; + /** Any app specic path (route) */ + appPath?: string; + appState?: any; + onClick?: MouseEventHandler; +}; + +/** + * An `EuiLink` that will use Kibana's `.application.navigateToApp()` to redirect the user to the + * a given app without causing a full browser refresh + */ +export const LinkToApp = memo( + ({ appId, appPath: path, appState: state, onClick, children, ...otherProps }) => { + const handleOnClick = useNavigateToAppEventHandler(appId, { path, state, onClick }); + return ( + // eslint-disable-next-line @elastic/eui/href-or-on-click + + {children} + + ); + } +); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx new file mode 100644 index 0000000000000..867c9101fe79b --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { PageView } from './page_view'; +import { EuiThemeProvider } from '../../../../../../legacy/common/eui_styled_components'; + +describe('PageView component', () => { + const render = (ui: Parameters[0]) => + mount(ui, { wrappingComponent: EuiThemeProvider }); + + it('should display only body if not header props used', () => { + expect(render(body content)).toMatchSnapshot(); + }); + it('should display header left and right', () => { + expect( + render( + + body content + + ) + ).toMatchSnapshot(); + }); + it('should display only header left', () => { + expect(render(body content)).toMatchSnapshot(); + }); + it('should display only header right but include an empty left side', () => { + expect( + render(body content) + ).toMatchSnapshot(); + }); + it(`should use custom element for header left and not wrap in EuiTitle`, () => { + expect( + render(title here

}>body content
) + ).toMatchSnapshot(); + }); + it('should display body header wrapped in EuiTitle', () => { + expect(render(body content)).toMatchSnapshot(); + }); + it('should display body header custom element', () => { + expect( + render(body header

}>body content
) + ).toMatchSnapshot(); + }); + it('should pass through EuiPage props', () => { + expect( + render( + + body content + + ) + ).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.tsx new file mode 100644 index 0000000000000..04401f06d344a --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.tsx @@ -0,0 +1,96 @@ +/* + * 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 { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiPageHeader, + EuiPageHeaderSection, + EuiPageProps, + EuiTitle, +} from '@elastic/eui'; +import React, { memo, ReactNode } from 'react'; +import styled from 'styled-components'; + +const StyledEuiPage = styled(EuiPage)` + padding: 0; + + .endpoint-header { + padding: ${props => props.theme.eui.euiSizeL}; + } + .endpoint-page-content { + border-left: none; + border-right: none; + } +`; + +const isStringOrNumber = /(string|number)/; + +/** + * Page View layout for use in Endpoint + */ +export const PageView = memo< + EuiPageProps & { + /** + * content to be placed on the left side of the header. If a `string` is used, then it will + * be wrapped with `

`, else it will just be used as is. + */ + headerLeft?: ReactNode; + /** Content for the right side of the header */ + headerRight?: ReactNode; + /** + * body (sub-)header section. If a `string` is used, then it will be wrapped with + * `

` + */ + bodyHeader?: ReactNode; + children?: ReactNode; + } +>(({ children, headerLeft, headerRight, bodyHeader, ...otherProps }) => { + return ( + + + {(headerLeft || headerRight) && ( + + + {isStringOrNumber.test(typeof headerLeft) ? ( + +

{headerLeft}

+
+ ) : ( + headerLeft + )} +
+ {headerRight && ( + + {headerRight} + + )} +
+ )} + + {bodyHeader && ( + + + {isStringOrNumber.test(typeof bodyHeader) ? ( + +

{bodyHeader}

+
+ ) : ( + bodyHeader + )} +
+
+ )} + {children} +
+
+
+ ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts b/x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts new file mode 100644 index 0000000000000..5fbfa5e0e58a8 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts @@ -0,0 +1,75 @@ +/* + * 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 { MouseEventHandler, useCallback } from 'react'; +import { ApplicationStart } from 'kibana/public'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; + +type NavigateToAppHandlerProps = Parameters; +type EventHandlerCallback = MouseEventHandler; + +/** + * Provides an event handlers that can be used with (for example) `onClick` to prevent the + * event's default behaviour and instead use Kibana's `navigateToApp()` to send user to a + * different app. Use of `navigateToApp()` prevents a full browser refresh for apps that have + * been converted to the New Platform. + * + * @param appId + * @param [options] + * + * @example + * + * const handleOnClick = useNavigateToAppEventHandler('ingestManager', {path: '#/configs'}) + * return See configs + */ +export const useNavigateToAppEventHandler = ( + /** the app id - normally the value of the `id` in that plugin's `kibana.json` */ + appId: NavigateToAppHandlerProps[0], + + /** Options, some of which are passed along to the app route */ + options?: NavigateToAppHandlerProps[1] & { + onClick?: EventHandlerCallback; + } +): EventHandlerCallback => { + const { services } = useKibana(); + const { path, state, onClick } = options || {}; + return useCallback( + ev => { + try { + if (onClick) { + onClick(ev); + } + } catch (error) { + ev.preventDefault(); + throw error; + } + + if (ev.defaultPrevented) { + return; + } + + if (ev.button !== 0) { + return; + } + + if ( + ev.currentTarget instanceof HTMLAnchorElement && + ev.currentTarget.target !== '' && + ev.currentTarget.target !== '_self' + ) { + return; + } + + if (ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey) { + return; + } + + ev.preventDefault(); + services.application.navigateToApp(appId, { path, state }); + }, + [appId, onClick, path, services.application, state] + ); +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx index 884646369b4b1..fa9055e0d9bbd 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx @@ -6,9 +6,9 @@ import * as React from 'react'; import ReactDOM from 'react-dom'; -import { CoreStart, AppMountParameters } from 'kibana/public'; +import { CoreStart, AppMountParameters, ScopedHistory } from 'kibana/public'; import { I18nProvider, FormattedMessage } from '@kbn/i18n/react'; -import { Route, Switch, BrowserRouter } from 'react-router-dom'; +import { Route, Switch, Router } from 'react-router-dom'; import { Provider } from 'react-redux'; import { Store } from 'redux'; import { useObservable } from 'react-use'; @@ -29,12 +29,11 @@ import { EuiThemeProvider } from '../../../../../legacy/common/eui_styled_compon export function renderApp( coreStart: CoreStart, depsStart: EndpointPluginStartDependencies, - { appBasePath, element }: AppMountParameters + { element, history }: AppMountParameters ) { - coreStart.http.get('/api/endpoint/hello-world'); const store = appStoreFactory({ coreStart, depsStart }); ReactDOM.render( - , + , element ); return () => { @@ -43,7 +42,7 @@ export function renderApp( } interface RouterProps { - basename: string; + history: ScopedHistory; store: Store; coreStart: CoreStart; depsStart: EndpointPluginStartDependencies; @@ -51,7 +50,7 @@ interface RouterProps { const AppRoot: React.FunctionComponent = React.memo( ({ - basename, + history, store, coreStart: { http, notifications, uiSettings, application }, depsStart: { data }, @@ -63,9 +62,9 @@ const AppRoot: React.FunctionComponent = React.memo( - + - + = React.memo( /> - + diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts new file mode 100644 index 0000000000000..1900516cb539b --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PolicyConfig } from '../types'; + +/** + * A typed Object.entries() function where the keys and values are typed based on the given object + */ +const entries = (o: T): Array<[keyof T, T[keyof T]]> => + Object.entries(o) as Array<[keyof T, T[keyof T]]>; +type DeepPartial = { [K in keyof T]?: DeepPartial }; + +/** + * Returns a deep copy of PolicyDetailsConfig + */ +export function clone(policyDetailsConfig: PolicyConfig): PolicyConfig { + const clonedConfig: DeepPartial = {}; + for (const [key, val] of entries(policyDetailsConfig)) { + if (typeof val === 'object') { + const valClone: Partial = {}; + clonedConfig[key] = valClone; + for (const [key2, val2] of entries(val)) { + if (typeof val2 === 'object') { + valClone[key2] = { + ...val2, + }; + } else { + clonedConfig[key] = { + ...val, + }; + } + } + } else { + clonedConfig[key] = val; + } + } + + /** + * clonedConfig is typed as DeepPartial so we can construct the copy from an empty object + */ + return clonedConfig as PolicyConfig; +} diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts index 42c24400d12d3..80b7fd87e13be 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/action.ts @@ -5,7 +5,7 @@ */ import { IIndexPattern } from 'src/plugins/data/public'; -import { Immutable, AlertData } from '../../../../../common/types'; +import { Immutable, AlertDetails } from '../../../../../common/types'; import { AlertListData } from '../../types'; interface ServerReturnedAlertsData { @@ -15,7 +15,7 @@ interface ServerReturnedAlertsData { interface ServerReturnedAlertDetailsData { readonly type: 'serverReturnedAlertDetailsData'; - readonly payload: Immutable; + readonly payload: Immutable; } interface ServerReturnedSearchBarIndexPatterns { 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 b37ba0c0983d3..2c6ebf52189f5 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 @@ -5,7 +5,7 @@ */ import { IIndexPattern } from 'src/plugins/data/public'; -import { AlertResultList, AlertData } from '../../../../../common/types'; +import { AlertResultList, AlertDetails } from '../../../../../common/types'; import { AppAction } from '../action'; import { MiddlewareFactory, AlertListState } from '../../types'; import { isOnAlertPage, apiQueryParams, hasSelectedAlert, uiQueryParams } from './selectors'; @@ -40,7 +40,7 @@ export const alertMiddlewareFactory: MiddlewareFactory = (coreSt if (action.type === 'userChangedUrl' && isOnAlertPage(state) && hasSelectedAlert(state)) { const uiParams = uiQueryParams(state); - const response: AlertData = await coreStart.http.get( + const response: AlertDetails = await coreStart.http.get( `/api/endpoint/alerts/${uiParams.selected_alert}` ); api.dispatch({ type: 'serverReturnedAlertDetailsData', payload: response }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts index 3931723a55505..6a13e0f92471b 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/mock_alert_result_list.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AlertResultList } from '../../../../../common/types'; +import { AlertResultList, AlertDetails } from '../../../../../common/types'; import { EndpointDocGenerator } from '../../../../../common/generate_data'; export const mockAlertResultList: (options?: { @@ -47,3 +47,18 @@ export const mockAlertResultList: (options?: { }; return mock; }; + +export const mockAlertDetailsResult = (): AlertDetails => { + const generator = new EndpointDocGenerator(); + return { + ...generator.generateAlert(new Date().getTime()), + ...{ + id: 'xDUYMHABAKk0XnHd8rrd', + prev: null, + next: null, + state: { + host_metadata: generator.generateHostMetadata(), + }, + }, + }; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/action.ts index cf875e01a6fde..e7e523a9287b8 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/action.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PolicyData } from '../../types'; +import { PolicyData, PolicyConfig } from '../../types'; interface ServerReturnedPolicyDetailsData { type: 'serverReturnedPolicyDetailsData'; @@ -13,4 +13,14 @@ interface ServerReturnedPolicyDetailsData { }; } -export type PolicyDetailsAction = ServerReturnedPolicyDetailsData; +/** + * When users change a policy via forms, this action is dispatched with a payload that modifies the configuration of a cloned policy config. + */ +interface UserChangedPolicyConfig { + type: 'userChangedPolicyConfig'; + payload: { + policyConfig: PolicyConfig; + }; +} + +export type PolicyDetailsAction = ServerReturnedPolicyDetailsData | UserChangedPolicyConfig; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts new file mode 100644 index 0000000000000..b20df84fdf575 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts @@ -0,0 +1,92 @@ +/* + * 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 { PolicyDetailsState } from '../../types'; +import { createStore, Dispatch, Store } from 'redux'; +import { policyDetailsReducer, PolicyDetailsAction } from './index'; +import { policyConfig, windowsEventing } from './selectors'; +import { clone } from '../../models/policy_details_config'; + +describe('policy details: ', () => { + let store: Store; + let getState: typeof store['getState']; + let dispatch: Dispatch; + + beforeEach(() => { + store = createStore(policyDetailsReducer); + getState = store.getState; + dispatch = store.dispatch; + + dispatch({ + type: 'serverReturnedPolicyDetailsData', + payload: { + policyItem: { + id: '', + name: '', + description: '', + config_id: '', + enabled: true, + output_id: '', + inputs: [], + namespace: '', + package: { + name: '', + title: '', + version: '', + }, + revision: 1, + }, + policyConfig: { + windows: { + malware: { + mode: 'detect', + }, + eventing: { + process: false, + network: false, + }, + }, + mac: { + malware: { + mode: '', + }, + eventing: { + process: false, + network: false, + }, + }, + linux: { + eventing: { + process: false, + network: false, + }, + }, + }, + }, + }); + }); + + describe('when the user has enabled windows process eventing', () => { + beforeEach(() => { + const config = policyConfig(getState()); + if (!config) { + throw new Error(); + } + + const newPayload1 = clone(config); + newPayload1.windows.eventing.process = true; + + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: newPayload1 }, + }); + }); + + it('windows process eventing is enabled', async () => { + expect(windowsEventing(getState())!.process).toEqual(true); + }); + }); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts index 39d7eb93569e2..1942538aa9df9 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts @@ -5,7 +5,7 @@ */ import { MiddlewareFactory, PolicyDetailsState } from '../../types'; -import { selectPolicyIdFromParams, isOnPolicyDetailsPage } from './selectors'; +import { policyIdFromParams, isOnPolicyDetailsPage } from './selectors'; import { sendGetDatasource } from '../../services/ingest'; export const policyDetailsMiddlewareFactory: MiddlewareFactory = coreStart => { @@ -16,7 +16,7 @@ export const policyDetailsMiddlewareFactory: MiddlewareFactory { return { policyItem: undefined, + policyConfig: undefined, isLoading: false, }; }; @@ -34,5 +35,12 @@ export const policyDetailsReducer: Reducer = ( }; } + if (action.type === 'userChangedPolicyConfig') { + return { + ...state, + policyConfig: action.payload.policyConfig, + }; + } + return state; }; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts index a08130d0f4b30..6a5d4077b3c32 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts @@ -6,9 +6,12 @@ import { createSelector } from 'reselect'; import { PolicyDetailsState } from '../../types'; +import { Immutable } from '../../../../../common/types'; -export const selectPolicyDetails = (state: PolicyDetailsState) => state.policyItem; +/** Returns the policy details */ +export const policyDetails = (state: PolicyDetailsState) => state.policyItem; +/** Returns a boolean of whether the user is on the policy details page or not */ export const isOnPolicyDetailsPage = (state: PolicyDetailsState) => { if (state.location) { const pathnameParts = state.location.pathname.split('/'); @@ -18,7 +21,8 @@ export const isOnPolicyDetailsPage = (state: PolicyDetailsState) => { } }; -export const selectPolicyIdFromParams: (state: PolicyDetailsState) => string = createSelector( +/** Returns the policyId from the url */ +export const policyIdFromParams: (state: PolicyDetailsState) => string = createSelector( (state: PolicyDetailsState) => state.location, (location: PolicyDetailsState['location']) => { if (location) { @@ -27,3 +31,32 @@ export const selectPolicyIdFromParams: (state: PolicyDetailsState) => string = c return ''; } ); + +/** Returns the policy configuration */ +export const policyConfig = (state: Immutable) => state.policyConfig; + +/** Returns an object of all the windows eventing configuration */ +export const windowsEventing = (state: PolicyDetailsState) => { + const config = policyConfig(state); + return config && config.windows.eventing; +}; + +/** Returns the total number of possible windows eventing configurations */ +export const totalWindowsEventing = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.keys(config.windows.eventing).length; + } + return 0; +}; + +/** Returns the number of selected windows eventing configurations */ +export const selectedWindowsEventing = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.values(config.windows.eventing).reduce((count, event) => { + return event === true ? count + 1 : count; + }, 0); + } + return 0; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index dae2c93c9dd04..7947a35068234 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -12,6 +12,7 @@ import { AlertResultList, Immutable, ImmutableArray, + AlertDetails, } from '../../../common/types'; import { EndpointPluginStartDependencies } from '../../plugin'; import { AppAction } from './store/action'; @@ -75,17 +76,77 @@ export interface PolicyListState { } /** - * Policy list store state + * Policy details store state */ export interface PolicyDetailsState { /** A single policy item */ - policyItem: PolicyData | undefined; + policyItem?: PolicyData; /** data is being retrieved from server */ + policyConfig?: PolicyConfig; isLoading: boolean; /** current location of the application */ location?: Immutable; } +/** + * Policy Details configuration + */ +export interface PolicyConfig { + windows: WindowsPolicyConfig; + mac: MacPolicyConfig; + linux: LinuxPolicyConfig; +} + +/** + * Windows-specific policy configuration + */ +interface WindowsPolicyConfig { + /** malware mode can be detect, prevent or prevent and notify user */ + malware: { + mode: string; + }; + eventing: { + process: boolean; + network: boolean; + }; +} + +/** + * Mac-specific policy configuration + */ +interface MacPolicyConfig { + /** malware mode can be detect, prevent or prevent and notify user */ + malware: { + mode: string; + }; + eventing: { + process: boolean; + network: boolean; + }; +} +/** + * Linux-specific policy configuration + */ +interface LinuxPolicyConfig { + eventing: { + process: boolean; + network: boolean; + }; +} + +/** OS used in Policy */ +export enum OS { + windows = 'windows', + mac = 'mac', + linux = 'linux', +} + +/** Used in Policy */ +export enum EventingFields { + process = 'process', + network = 'network', +} + export interface GlobalState { readonly hostList: HostListState; readonly alertList: AlertListState; @@ -136,7 +197,7 @@ export interface AlertListState { readonly location?: Immutable; /** Specific Alert data to be shown in the details view */ - readonly alertDetails?: Immutable; + readonly alertDetails?: Immutable; /** Search bar state including indexPatterns */ readonly searchBar: AlertsSearchBarState; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details.test.tsx index 0f5a9dd7fed17..e3639bf1cacbc 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details.test.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/alerts/alert_details.test.tsx @@ -9,7 +9,7 @@ import { appStoreFactory } from '../../store'; import { fireEvent } from '@testing-library/react'; import { MemoryHistory } from 'history'; import { AppAction } from '../../types'; -import { mockAlertResultList } from '../../store/alerts/mock_alert_result_list'; +import { mockAlertDetailsResult } from '../../store/alerts/mock_alert_result_list'; import { alertPageTestRender } from './test_helpers/render_alert_page'; describe('when the alert details flyout is open', () => { @@ -34,7 +34,7 @@ describe('when the alert details flyout is open', () => { reactTestingLibrary.act(() => { const action: AppAction = { type: 'serverReturnedAlertDetailsData', - payload: mockAlertResultList().alerts[0], + payload: mockAlertDetailsResult(), }; store.dispatch(action); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx index bdbd323eaab72..a64b3293ec6cd 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx @@ -5,32 +5,58 @@ */ import React from 'react'; -import { EuiTitle } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiButton, + EuiButtonEmpty, + EuiText, + EuiSpacer, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { usePolicyDetailsSelector } from './policy_hooks'; -import { selectPolicyDetails } from '../../store/policy_details/selectors'; +import { policyDetails } from '../../store/policy_details/selectors'; +import { WindowsEventing } from './policy_forms/eventing/windows'; +import { PageView } from '../../components/page_view'; export const PolicyDetails = React.memo(() => { - const policyItem = usePolicyDetailsSelector(selectPolicyDetails); + const policyItem = usePolicyDetailsSelector(policyDetails); - function policyName() { - if (policyItem) { - return {policyItem.name}; - } else { - return ( - - - - ); - } - } + const headerLeftContent = + policyItem?.name ?? + i18n.translate('xpack.endpoint.policyDetails.notFound', { + defaultMessage: 'Policy Not Found', + }); + + const headerRightContent = ( + + + + + + + + + + + + + ); return ( - -

{policyName()}

-
+ + +

+ +

+
+ + +
); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/config_form.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/config_form.tsx new file mode 100644 index 0000000000000..66d5932b91c2b --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/config_form.tsx @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { + EuiCard, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiHorizontalRule, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import styled from 'styled-components'; + +const PolicyDetailCard = styled.div` + .policyDetailTitleOS { + flex-grow: 2; + } + .policyDetailTitleFlexItem { + margin: 0; + } +`; +export const ConfigForm: React.FC<{ + type: string; + supportedOss: string[]; + children: React.ReactNode; + id: string; + selectedEventing: number; + totalEventing: number; +}> = React.memo(({ type, supportedOss, children, id, selectedEventing, totalEventing }) => { + const typeTitle = () => { + return ( + + + + +
+ +
+
+
+ + {type} + +
+ + + +
+ +
+
+
+ + {supportedOss.join(', ')} + +
+ + + + + +
+ ); + }; + + const events = () => { + return ( + +
+ +
+
+ ); + }; + + return ( + + + + {events()} + + {children} + + } + /> + + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx new file mode 100644 index 0000000000000..add137ea57a5e --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback } from 'react'; +import { EuiCheckbox } from '@elastic/eui'; +import { useDispatch } from 'react-redux'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { policyConfig, windowsEventing } from '../../../../store/policy_details/selectors'; +import { PolicyDetailsAction } from '../../../../store/policy_details'; +import { OS, EventingFields } from '../../../../types'; +import { clone } from '../../../../models/policy_details_config'; + +export const EventingCheckbox: React.FC<{ + id: string; + name: string; + os: OS; + protectionField: EventingFields; +}> = React.memo(({ id, name, os, protectionField }) => { + const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); + const eventing = usePolicyDetailsSelector(windowsEventing); + const dispatch = useDispatch<(action: PolicyDetailsAction) => void>(); + + const handleRadioChange = useCallback( + (event: React.ChangeEvent) => { + if (policyDetailsConfig) { + const newPayload = clone(policyDetailsConfig); + newPayload[os].eventing[protectionField] = event.target.checked; + + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: newPayload }, + }); + } + }, + [dispatch, os, policyDetailsConfig, protectionField] + ); + + return ( + + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx new file mode 100644 index 0000000000000..e92e22fc97fe6 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EventingCheckbox } from './checkbox'; +import { OS, EventingFields } from '../../../../types'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { + selectedWindowsEventing, + totalWindowsEventing, +} from '../../../../store/policy_details/selectors'; +import { ConfigForm } from '../config_form'; + +export const WindowsEventing = React.memo(() => { + const checkboxes = useMemo( + () => [ + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.eventingProcess', { + defaultMessage: 'Process', + }), + os: OS.windows, + protectionField: EventingFields.process, + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.eventingNetwork', { + defaultMessage: 'Network', + }), + os: OS.windows, + protectionField: EventingFields.network, + }, + ], + [] + ); + + const renderCheckboxes = () => { + return checkboxes.map((item, index) => { + return ( + + ); + }); + }; + + const selected = usePolicyDetailsSelector(selectedWindowsEventing); + const total = usePolicyDetailsSelector(totalWindowsEventing); + + return ( + + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx index f949efa46a2bd..7af302de8576e 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx @@ -4,20 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { SyntheticEvent, useCallback, useEffect, useMemo } from 'react'; -import { - EuiPage, - EuiPageBody, - EuiPageContent, - EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiTitle, - EuiBasicTable, - EuiText, - EuiTableFieldDataColumnType, - EuiLink, -} from '@elastic/eui'; +import React, { useCallback, useEffect, useMemo } from 'react'; +import { EuiBasicTable, EuiText, EuiTableFieldDataColumnType, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useDispatch } from 'react-redux'; @@ -35,6 +23,8 @@ import { usePolicyListSelector } from './policy_hooks'; import { PolicyListAction } from '../../store/policy_list'; import { PolicyData } from '../../types'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; +import { PageView } from '../../components/page_view'; +import { LinkToApp } from '../../components/link_to_app'; interface TableChangeCallbackArguments { page: { index: number; size: number }; @@ -145,18 +135,13 @@ export const PolicyList = React.memo(() => { }), render(version: string) { return ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - { - ev.preventDefault(); - services.application.navigateToApp('ingestManager', { - path: `#/configs/${version}`, - }); - }} > {version} - + ); }, }, @@ -165,42 +150,29 @@ export const PolicyList = React.memo(() => { ); return ( - - - - - - -

- -

-
-

- - - -

-
-
- - - -
-
-
+ + + + } + > + + ); }); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx index 799f67123ba26..3295ef0289235 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx @@ -133,52 +133,52 @@ const PaintServers = memo(() => ( /> - - + + - - + + - - + + - - + + )); @@ -187,8 +187,7 @@ const PaintServers = memo(() => ( * Ids of symbols to be linked by elements */ export const SymbolIds = { - processNode: idGenerator('nodeSymbol'), - solidHexagon: idGenerator('hexagon'), + processNodeLabel: idGenerator('nodeSymbol'), runningProcessCube: idGenerator('runningCube'), runningTriggerCube: idGenerator('runningTriggerCube'), terminatedProcessCube: idGenerator('terminatedCube'), @@ -200,7 +199,11 @@ export const SymbolIds = { */ const SymbolsAndShapes = memo(() => ( <> - + ( paintOrder="normal" /> - - - - - Running Process - - + + - - - - - - - + + - Running Trigger Process - - resolver_dark process running + + + - - - - - - - + + Terminated Process - - - - + + - - - + Terminated Trigger Process - - - - + + - - - + )); diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index f3086be1598a8..603521e2d9bb3 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -20,7 +20,7 @@ const nodeAssets = { runningProcessCube: { cubeSymbol: `#${SymbolIds.runningProcessCube}`, labelFill: `url(#${PaintServerIds.runningProcess})`, - descriptionFill: NamedColors.activeNoWarning, + descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.runningProcess', { defaultMessage: 'Running Process', }), @@ -28,7 +28,7 @@ const nodeAssets = { runningTriggerCube: { cubeSymbol: `#${SymbolIds.runningTriggerCube}`, labelFill: `url(#${PaintServerIds.runningTrigger})`, - descriptionFill: NamedColors.activeWarning, + descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.runningTrigger', { defaultMessage: 'Running Trigger', }), @@ -36,7 +36,7 @@ const nodeAssets = { terminatedProcessCube: { cubeSymbol: `#${SymbolIds.terminatedProcessCube}`, labelFill: NamedColors.fullLabelBackground, - descriptionFill: NamedColors.inertDescription, + descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedProcess', { defaultMessage: 'Terminated Process', }), @@ -44,7 +44,7 @@ const nodeAssets = { terminatedTriggerCube: { cubeSymbol: `#${SymbolIds.terminatedTriggerCube}`, labelFill: NamedColors.fullLabelBackground, - descriptionFill: NamedColors.inertDescription, + descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedTrigger', { defaultMessage: 'Terminated Trigger', }), @@ -207,7 +207,7 @@ export const ProcessEventDot = styled( { try { - const query = kibanaRequestToMetadataGetESQuery(req, endpointAppContext); - const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser( - 'search', - query - )) as SearchResponse; - - if (response.hits.hits.length === 0) { - return res.notFound({ body: 'Endpoint Not Found' }); + const doc = await getHostData(context, req.params.id); + if (doc) { + return res.ok({ body: doc }); } - - return res.ok({ body: response.hits.hits[0]._source }); + return res.notFound({ body: 'Endpoint Not Found' }); } catch (err) { return res.internalError({ body: err }); } @@ -93,6 +87,23 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp ); } +export async function getHostData( + context: RequestHandlerContext, + id: string +): Promise { + const query = getESQueryHostMetadataByID(id); + const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser( + 'search', + query + )) as SearchResponse; + + if (response.hits.hits.length === 0) { + return undefined; + } + + return response.hits.hits[0]._source; +} + function mapToHostResultList( queryParams: Record, searchResponse: SearchResponse diff --git a/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.test.ts b/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.test.ts index a3090361d4965..0966b52c79f7d 100644 --- a/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.test.ts +++ b/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.test.ts @@ -7,7 +7,7 @@ import { httpServerMock, loggingServiceMock } from '../../../../../../src/core/s import { EndpointConfigSchema } from '../../config'; import { kibanaRequestToMetadataListESQuery, - kibanaRequestToMetadataGetESQuery, + getESQueryHostMetadataByID, } from './metadata_query_builders'; import { EndpointAppConstants } from '../../../common/types'; @@ -118,15 +118,7 @@ describe('query builder', () => { describe('MetadataGetQuery', () => { it('searches for the correct ID', () => { const mockID = 'AABBCCDD-0011-2233-AA44-DEADBEEF8899'; - const mockRequest = httpServerMock.createKibanaRequest({ - params: { - id: mockID, - }, - }); - const query = kibanaRequestToMetadataGetESQuery(mockRequest, { - logFactory: loggingServiceMock.create(), - config: () => Promise.resolve(EndpointConfigSchema.validate({})), - }); + const query = getESQueryHostMetadataByID(mockID); expect(query).toEqual({ body: { query: { match: { 'host.id.keyword': mockID } }, diff --git a/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.ts b/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.ts index 300e837c4af1e..57b0a4ef10519 100644 --- a/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.ts +++ b/x-pack/plugins/endpoint/server/services/endpoint/metadata_query_builders.ts @@ -74,15 +74,12 @@ function buildQueryBody(request: KibanaRequest): Record, - endpointAppContext: EndpointAppContext -) => { +export function getESQueryHostMetadataByID(hostID: string) { return { body: { query: { match: { - 'host.id.keyword': request.params.id, + 'host.id.keyword': hostID, }, }, sort: [ @@ -96,4 +93,4 @@ export const kibanaRequestToMetadataGetESQuery = ( }, index: EndpointAppConstants.ENDPOINT_INDEX_NAME, }; -}; +} diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index fc1fdb71b0c37..50e7fdd5a9048 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -1,12 +1,15 @@ { - "dynamic": "strict", + "dynamic": "false", "properties": { "@timestamp": { "type": "date" }, "tags": { "ignore_above": 1024, - "type": "keyword" + "type": "keyword", + "meta": { + "isArray": true + } }, "message": { "norms": false, @@ -18,8 +21,7 @@ "ignore_above": 1024, "type": "keyword" } - }, - "dynamic": "strict" + } }, "event": { "properties": { @@ -40,8 +42,7 @@ "end": { "type": "date" } - }, - "dynamic": "strict" + } }, "error": { "properties": { @@ -49,8 +50,7 @@ "norms": false, "type": "text" } - }, - "dynamic": "strict" + } }, "user": { "properties": { @@ -58,8 +58,7 @@ "ignore_above": 1024, "type": "keyword" } - }, - "dynamic": "strict" + } }, "kibana": { "properties": { @@ -86,11 +85,9 @@ "ignore_above": 1024 } }, - "type": "nested", - "dynamic": "strict" + "type": "nested" } - }, - "dynamic": "strict" + } } } } \ No newline at end of file diff --git a/x-pack/plugins/event_log/scripts/create_schemas.js b/x-pack/plugins/event_log/scripts/create_schemas.js index 6e9ab00d04d1f..b46f7f295ddc7 100755 --- a/x-pack/plugins/event_log/scripts/create_schemas.js +++ b/x-pack/plugins/event_log/scripts/create_schemas.js @@ -30,11 +30,13 @@ function main() { const exportedProperties = mappings.EcsEventLogProperties; const multiValuedProperties = new Set(mappings.EcsEventLogMultiValuedProperties); + augmentMappings(ecsMappings.mappings, multiValuedProperties); + const elMappings = getEventLogMappings(ecsMappings, exportedProperties); console.log(`generating files in ${PLUGIN_DIR}`); writeEventLogMappings(elMappings); - writeEventLogConfigSchema(elMappings, ecsVersion, multiValuedProperties); + writeEventLogConfigSchema(elMappings, ecsVersion); } // return a stripped down version of the ecs schema, with only exportedProperties @@ -57,7 +59,6 @@ function getEventLogMappings(ecsSchema, exportedProperties) { const elValue = lodash.get(result.mappings.properties, prop); elValue.type = ecsValue.type; - elValue.dynamic = 'strict'; } return result; @@ -86,7 +87,7 @@ function writeEventLogMappings(elSchema) { // fixObjectTypes(elSchema.mappings); const mappings = { - dynamic: 'strict', + dynamic: 'false', properties: elSchema.mappings.properties, }; @@ -94,11 +95,10 @@ function writeEventLogMappings(elSchema) { console.log('generated:', EVENT_LOG_MAPPINGS_FILE); } -function writeEventLogConfigSchema(elSchema, ecsVersion, multiValuedProperties) { +function writeEventLogConfigSchema(elSchema, ecsVersion) { const lineWriter = LineWriter.createLineWriter(); - const elSchemaMappings = augmentMappings(elSchema.mappings, multiValuedProperties); - generateSchemaLines(lineWriter, null, elSchemaMappings); + generateSchemaLines(lineWriter, null, elSchema.mappings); // last line will have an extraneous comma const schemaLines = lineWriter.getContent().replace(/,$/, ''); @@ -113,22 +113,21 @@ const StringTypes = new Set(['string', 'keyword', 'text', 'ip']); const NumberTypes = new Set(['long', 'integer', 'float']); function augmentMappings(mappings, multiValuedProperties) { - // clone the mappings, as we're adding some additional properties - mappings = JSON.parse(JSON.stringify(mappings)); - for (const prop of multiValuedProperties) { const fullProp = replaceDotWithProperties(prop); - lodash.set(mappings.properties, `${fullProp}.multiValued`, true); + const metaPropName = `${fullProp}.meta`; + const meta = lodash.get(mappings.properties, metaPropName) || {}; + meta.isArray = true; + lodash.set(mappings.properties, metaPropName, meta); } - - return mappings; } function generateSchemaLines(lineWriter, prop, mappings) { const propKey = legalPropertyName(prop); + if (mappings == null) return; if (StringTypes.has(mappings.type)) { - if (mappings.multiValued) { + if (mappings.meta && mappings.meta.isArray) { lineWriter.addLine(`${propKey}: ecsStringMulti(),`); } else { lineWriter.addLine(`${propKey}: ecsString(),`); @@ -169,6 +168,7 @@ function generateSchemaLines(lineWriter, prop, mappings) { // write the object properties lineWriter.indent(); for (const prop of Object.keys(mappings.properties)) { + if (prop === 'meta') continue; generateSchemaLines(lineWriter, prop, mappings.properties[prop]); } lineWriter.dedent(); diff --git a/x-pack/plugins/features/kibana.json b/x-pack/plugins/features/kibana.json index e38d7be892904..325e5a0407493 100644 --- a/x-pack/plugins/features/kibana.json +++ b/x-pack/plugins/features/kibana.json @@ -3,6 +3,7 @@ "version": "8.0.0", "kibanaVersion": "kibana", "optionalPlugins": ["timelion"], + "configPath": ["xpack", "features"], "server": true, "ui": true } diff --git a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js index 25bfba93bfd84..00e852c65c7bf 100644 --- a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js +++ b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.js @@ -5,7 +5,7 @@ */ import * as jsts from 'jsts'; -import rewind from 'geojson-rewind'; +import rewind from '@mapbox/geojson-rewind'; const geoJSONReader = new jsts.io.GeoJSONReader(); const geoJSONWriter = new jsts.io.GeoJSONWriter(); diff --git a/x-pack/plugins/graph/kibana.json b/x-pack/plugins/graph/kibana.json index cf3a5fab92f56..96e7ea3ff2232 100644 --- a/x-pack/plugins/graph/kibana.json +++ b/x-pack/plugins/graph/kibana.json @@ -5,6 +5,6 @@ "server": true, "ui": true, "requiredPlugins": ["licensing", "data", "navigation"], - "optionalPlugins": ["home"], + "optionalPlugins": ["home", "features"], "configPath": ["xpack", "graph"] } diff --git a/x-pack/plugins/graph/server/plugin.ts b/x-pack/plugins/graph/server/plugin.ts index dcdf3f51d60bd..a169953d5a10b 100644 --- a/x-pack/plugins/graph/server/plugin.ts +++ b/x-pack/plugins/graph/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { Plugin, CoreSetup } from 'src/core/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { LicenseState } from './lib/license_state'; @@ -11,13 +12,22 @@ import { registerSearchRoute } from './routes/search'; import { registerExploreRoute } from './routes/explore'; import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; import { registerSampleData } from './sample_data'; +import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; export class GraphPlugin implements Plugin { private licenseState: LicenseState | null = null; public async setup( core: CoreSetup, - { licensing, home }: { licensing: LicensingPluginSetup; home?: HomeServerPluginSetup } + { + licensing, + home, + features, + }: { + licensing: LicensingPluginSetup; + home?: HomeServerPluginSetup; + features?: FeaturesPluginSetup; + } ) { const licenseState = new LicenseState(); licenseState.start(licensing.license$); @@ -27,6 +37,41 @@ export class GraphPlugin implements Plugin { registerSampleData(home.sampleData, licenseState); } + if (features) { + features.registerFeature({ + id: 'graph', + name: i18n.translate('xpack.graph.featureRegistry.graphFeatureName', { + defaultMessage: 'Graph', + }), + order: 1200, + icon: 'graphApp', + navLinkId: 'graph', + app: ['graph', 'kibana'], + catalogue: ['graph'], + validLicenses: ['platinum', 'enterprise', 'trial'], + privileges: { + all: { + app: ['graph', 'kibana'], + catalogue: ['graph'], + savedObject: { + all: ['graph-workspace'], + read: ['index-pattern'], + }, + ui: ['save', 'delete'], + }, + read: { + app: ['graph', 'kibana'], + catalogue: ['graph'], + savedObject: { + all: [], + read: ['index-pattern', 'graph-workspace'], + }, + ui: [], + }, + }, + }); + } + const router = core.http.createRouter(); registerSearchRoute({ licenseState, router }); registerExploreRoute({ licenseState, router }); diff --git a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts index 419ee021a9189..d532c079e3e9c 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts @@ -78,6 +78,11 @@ export const logEntryRT = rt.type({ id: rt.string, cursor: logEntriesCursorRT, columns: rt.array(logColumnRT), + context: rt.partial({ + 'log.file.path': rt.string, + 'host.name': rt.string, + 'container.id': rt.string, + }), }); export type LogMessageConstantPart = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/log_analysis/log_analysis.ts b/x-pack/plugins/infra/common/log_analysis/log_analysis.ts index 9b2f1a55eb8c1..f0aa2067a24c2 100644 --- a/x-pack/plugins/infra/common/log_analysis/log_analysis.ts +++ b/x-pack/plugins/infra/common/log_analysis/log_analysis.ts @@ -14,19 +14,28 @@ export type JobStatus = | 'finished' | 'failed'; +export type SetupStatusRequiredReason = + | 'missing' // jobs are missing + | 'reconfiguration' // the configurations don't match the source configurations + | 'update'; // the definitions don't match the module definitions + export type SetupStatus = - | 'initializing' // acquiring job statuses to determine setup status - | 'unknown' // job status could not be acquired (failed request etc) - | 'required' // jobs are missing - | 'requiredForReconfiguration' // the configurations don't match the source configurations - | 'requiredForUpdate' // the definitions don't match the module definitions - | 'pending' // In the process of setting up the module for the first time or retrying, waiting for response - | 'succeeded' // setup succeeded, notifying user - | 'failed' // setup failed, notifying user - | 'hiddenAfterSuccess' // hide the setup screen and we show the results for the first time - | 'skipped' // setup hidden because the module is in a correct state already - | 'skippedButReconfigurable' // setup hidden even though the job configurations are outdated - | 'skippedButUpdatable'; // setup hidden even though the job definitions are outdated + | { type: 'initializing' } // acquiring job statuses to determine setup status + | { type: 'unknown' } // job status could not be acquired (failed request etc) + | { + type: 'required'; + reason: SetupStatusRequiredReason; + } // setup required + | { type: 'pending' } // In the process of setting up the module for the first time or retrying, waiting for response + | { type: 'succeeded' } // setup succeeded, notifying user + | { + type: 'failed'; + reasons: string[]; + } // setup failed, notifying user + | { + type: 'skipped'; + newlyCreated?: boolean; + }; // setup is hidden /** * Maps a job status to the possibility that results have already been produced @@ -43,9 +52,7 @@ export const isHealthyJobStatus = (jobStatus: JobStatus) => * produced before this state was reached. */ export const isSetupStatusWithResults = (setupStatus: SetupStatus) => - ['skipped', 'hiddenAfterSuccess', 'skippedButReconfigurable', 'skippedButUpdatable'].includes( - setupStatus - ); + setupStatus.type === 'skipped'; const KIBANA_SAMPLE_DATA_INDICES = ['kibana_sample_data_logs*']; diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/alert_flyout.tsx b/x-pack/plugins/infra/public/components/alerting/metrics/alert_flyout.tsx index a00d63af8aac2..914054e1fd9b7 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/alert_flyout.tsx +++ b/x-pack/plugins/infra/public/components/alerting/metrics/alert_flyout.tsx @@ -35,6 +35,7 @@ export const AlertFlyout = (props: Props) => { }, toastNotifications: services.notifications?.toasts, http: services.http, + docLinks: services.docLinks, actionTypeRegistry: triggersActionsUI.actionTypeRegistry, alertTypeRegistry: triggersActionsUI.alertTypeRegistry, }} diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_job_status/log_analysis_job_problem_indicator.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_job_status/log_analysis_job_problem_indicator.tsx index 8a16d819e12c2..e7e89bb365e4f 100644 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_job_status/log_analysis_job_problem_indicator.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_job_status/log_analysis_job_problem_indicator.tsx @@ -6,33 +6,36 @@ import React from 'react'; -import { JobStatus, SetupStatus } from '../../../../common/log_analysis'; import { JobConfigurationOutdatedCallout } from './job_configuration_outdated_callout'; import { JobDefinitionOutdatedCallout } from './job_definition_outdated_callout'; import { JobStoppedCallout } from './job_stopped_callout'; +import { FirstUseCallout } from '../log_analysis_results'; export const LogAnalysisJobProblemIndicator: React.FC<{ - jobStatus: JobStatus; - setupStatus: SetupStatus; + hasOutdatedJobConfigurations: boolean; + hasOutdatedJobDefinitions: boolean; + hasStoppedJobs: boolean; + isFirstUse: boolean; onRecreateMlJobForReconfiguration: () => void; onRecreateMlJobForUpdate: () => void; -}> = ({ jobStatus, setupStatus, onRecreateMlJobForReconfiguration, onRecreateMlJobForUpdate }) => { - if (isStopped(jobStatus)) { - return ; - } else if (isUpdatable(setupStatus)) { - return ; - } else if (isReconfigurable(setupStatus)) { - return ; - } - - return null; // no problem to indicate +}> = ({ + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + isFirstUse, + onRecreateMlJobForReconfiguration, + onRecreateMlJobForUpdate, +}) => { + return ( + <> + {hasOutdatedJobDefinitions ? ( + + ) : null} + {hasOutdatedJobConfigurations ? ( + + ) : null} + {hasStoppedJobs ? : null} + {isFirstUse ? : null} + + ); }; - -const isStopped = (jobStatus: JobStatus) => jobStatus === 'stopped'; - -const isUpdatable = (setupStatus: SetupStatus) => setupStatus === 'skippedButUpdatable'; - -const isReconfigurable = (setupStatus: SetupStatus) => setupStatus === 'skippedButReconfigurable'; - -export const jobHasProblem = (jobStatus: JobStatus, setupStatus: SetupStatus) => - isStopped(jobStatus) || isUpdatable(setupStatus) || isReconfigurable(setupStatus); diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx index de20dd12c17bd..4ec895dfed4bc 100644 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx @@ -45,7 +45,7 @@ export const InitialConfigurationStep: React.FunctionComponent { - const disabled = useMemo(() => !editableFormStatus.includes(setupStatus), [setupStatus]); + const disabled = useMemo(() => !editableFormStatus.includes(setupStatus.type), [setupStatus]); return ( <> @@ -72,12 +72,7 @@ export const InitialConfigurationStep: React.FunctionComponent, status: - props.setupStatus === 'pending' + props.setupStatus.type === 'pending' ? 'incomplete' - : props.setupStatus === 'failed' + : props.setupStatus.type === 'failed' ? 'danger' - : props.setupStatus === 'succeeded' + : props.setupStatus.type === 'succeeded' ? 'complete' : undefined, }); @@ -55,7 +55,7 @@ export const ProcessStep: React.FunctionComponent = ({ }) => { return ( - {setupStatus === 'pending' ? ( + {setupStatus.type === 'pending' ? ( @@ -67,7 +67,7 @@ export const ProcessStep: React.FunctionComponent = ({ /> - ) : setupStatus === 'failed' ? ( + ) : setupStatus.type === 'failed' ? ( <> = ({ /> - ) : setupStatus === 'succeeded' ? ( + ) : setupStatus.type === 'succeeded' ? ( <> = ({ /> - ) : setupStatus === 'requiredForUpdate' || setupStatus === 'requiredForReconfiguration' ? ( + ) : setupStatus.type === 'required' && + (setupStatus.reason === 'update' || setupStatus.reason === 'reconfiguration') ? ( ) : ( diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts index 49112dd8ec8d8..c3c119f51ff7d 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts @@ -54,6 +54,22 @@ const jobStateRT = rt.keyof({ opening: null, }); +const jobCategorizationStatusRT = rt.keyof({ + ok: null, + warn: null, +}); + +const jobModelSizeStatsRT = rt.type({ + categorization_status: jobCategorizationStatusRT, + categorized_doc_count: rt.number, + dead_category_count: rt.number, + frequent_category_count: rt.number, + rare_category_count: rt.number, + total_category_count: rt.number, +}); + +export type JobModelSizeStats = rt.TypeOf; + export const jobSummaryRT = rt.intersection([ rt.type({ id: rt.string, @@ -65,6 +81,7 @@ export const jobSummaryRT = rt.intersection([ fullJob: rt.partial({ custom_settings: jobCustomSettingsRT, finished_time: rt.number, + model_size_stats: jobModelSizeStatsRT, }), }), ]); diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/index.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/index.ts index 185f6936662bd..9828ad72ec909 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/index.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/index.ts @@ -7,6 +7,10 @@ export * from './log_analysis_capabilities'; export * from './log_analysis_cleanup'; export * from './log_analysis_module'; +export * from './log_analysis_module_configuration'; +export * from './log_analysis_module_definition'; export * from './log_analysis_module_status'; export * from './log_analysis_module_types'; export * from './log_analysis_setup_state'; + +export { JobModelSizeStats, JobSummary } from './api/ml_get_jobs_summary_api'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx index efe9629e84e42..99c5a3df7c9b1 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { useModuleStatus } from './log_analysis_module_status'; @@ -17,36 +17,10 @@ export const useLogAnalysisModule = ({ sourceConfiguration: ModuleSourceConfiguration; moduleDescriptor: ModuleDescriptor; }) => { - const { spaceId, sourceId, timestampField, indices } = sourceConfiguration; - const [moduleStatus, dispatchModuleStatus] = useModuleStatus(moduleDescriptor.jobTypes, { - bucketSpan: moduleDescriptor.bucketSpan, - indexPattern: indices.join(','), - timestampField, - }); + const { spaceId, sourceId, timestampField } = sourceConfiguration; + const [moduleStatus, dispatchModuleStatus] = useModuleStatus(moduleDescriptor.jobTypes); - const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - dispatchModuleStatus({ type: 'fetchingModuleDefinition' }); - return await moduleDescriptor.getModuleDefinition(); - }, - onResolve: response => { - dispatchModuleStatus({ - type: 'fetchedModuleDefinition', - spaceId, - sourceId, - moduleDefinition: response, - }); - }, - onReject: () => { - dispatchModuleStatus({ type: 'failedFetchingModuleDefinition' }); - }, - }, - [moduleDescriptor.getModuleDefinition, spaceId, sourceId] - ); - - const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( + const [, fetchJobStatus] = useTrackedPromise( { cancelPreviousOn: 'resolution', createPromise: async () => { @@ -68,12 +42,6 @@ export const useLogAnalysisModule = ({ [spaceId, sourceId] ); - const isLoadingModuleStatus = useMemo( - () => - fetchJobStatusRequest.state === 'pending' || fetchModuleDefinitionRequest.state === 'pending', - [fetchJobStatusRequest.state, fetchModuleDefinitionRequest.state] - ); - const [, setUpModule] = useTrackedPromise( { cancelPreviousOn: 'resolution', @@ -83,15 +51,24 @@ export const useLogAnalysisModule = ({ end: number | undefined ) => { dispatchModuleStatus({ type: 'startedSetup' }); - return await moduleDescriptor.setUpModule(start, end, { + const setupResult = await moduleDescriptor.setUpModule(start, end, { indices: selectedIndices, sourceId, spaceId, timestampField, }); + const jobSummaries = await moduleDescriptor.getJobSummary(spaceId, sourceId); + return { setupResult, jobSummaries }; }, - onResolve: ({ datafeeds, jobs }) => { - dispatchModuleStatus({ type: 'finishedSetup', datafeeds, jobs, spaceId, sourceId }); + onResolve: ({ setupResult: { datafeeds, jobs }, jobSummaries }) => { + dispatchModuleStatus({ + type: 'finishedSetup', + datafeedSetupResults: datafeeds, + jobSetupResults: jobs, + jobSummaries, + spaceId, + sourceId, + }); }, onReject: () => { dispatchModuleStatus({ type: 'failedSetup' }); @@ -146,36 +123,14 @@ export const useLogAnalysisModule = ({ sourceId, ]); - useEffect(() => { - dispatchModuleStatus({ - type: 'updatedSourceConfiguration', - spaceId, - sourceId, - sourceConfiguration: { - timestampField, - indexPattern: indices.join(','), - bucketSpan: moduleDescriptor.bucketSpan, - }, - }); - }, [ - dispatchModuleStatus, - indices, - moduleDescriptor.bucketSpan, - sourceConfiguration, - sourceId, - spaceId, - timestampField, - ]); - return { cleanUpAndSetUpModule, cleanUpModule, fetchJobStatus, - fetchModuleDefinition, isCleaningUp, - isLoadingModuleStatus, jobIds, jobStatus: moduleStatus.jobStatus, + jobSummaries: moduleStatus.jobSummaries, lastSetupErrorMessages: moduleStatus.lastSetupErrorMessages, moduleDescriptor, setUpModule, diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_configuration.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_configuration.ts new file mode 100644 index 0000000000000..ba2185ff83784 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_configuration.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useMemo } from 'react'; +import { JobSummary } from './api/ml_get_jobs_summary_api'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './log_analysis_module_types'; + +export const useLogAnalysisModuleConfiguration = ({ + moduleDescriptor, + sourceConfiguration, +}: { + moduleDescriptor: ModuleDescriptor; + sourceConfiguration: ModuleSourceConfiguration; +}) => { + const getIsJobConfigurationOutdated = useMemo( + () => isJobConfigurationOutdated(moduleDescriptor, sourceConfiguration), + [sourceConfiguration, moduleDescriptor] + ); + + return { + getIsJobConfigurationOutdated, + }; +}; + +export const isJobConfigurationOutdated = ( + { bucketSpan }: ModuleDescriptor, + currentSourceConfiguration: ModuleSourceConfiguration +) => (jobSummary: JobSummary): boolean => { + if (!jobSummary.fullJob || !jobSummary.fullJob.custom_settings) { + return false; + } + + const jobConfiguration = jobSummary.fullJob.custom_settings.logs_source_config; + + return !( + jobConfiguration && + jobConfiguration.bucketSpan === bucketSpan && + jobConfiguration.indexPattern && + isSubset( + new Set(jobConfiguration.indexPattern.split(',')), + new Set(currentSourceConfiguration.indices) + ) && + jobConfiguration.timestampField === currentSourceConfiguration.timestampField + ); +}; + +const isSubset = (subset: Set, superset: Set) => { + return Array.from(subset).every(subsetElement => superset.has(subsetElement)); +}; diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_definition.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_definition.tsx new file mode 100644 index 0000000000000..ea0cd32c0b93e --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_definition.tsx @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useCallback, useMemo, useState } from 'react'; +import { getJobId } from '../../../../common/log_analysis'; +import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { JobSummary } from './api/ml_get_jobs_summary_api'; +import { GetMlModuleResponsePayload, JobDefinition } from './api/ml_get_module'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './log_analysis_module_types'; + +export const useLogAnalysisModuleDefinition = ({ + sourceConfiguration: { spaceId, sourceId }, + moduleDescriptor, +}: { + sourceConfiguration: ModuleSourceConfiguration; + moduleDescriptor: ModuleDescriptor; +}) => { + const [moduleDefinition, setModuleDefinition] = useState< + GetMlModuleResponsePayload | undefined + >(); + + const jobDefinitionByJobId = useMemo( + () => + moduleDefinition + ? moduleDefinition.jobs.reduce>( + (accumulatedJobDefinitions, jobDefinition) => ({ + ...accumulatedJobDefinitions, + [getJobId(spaceId, sourceId, jobDefinition.id)]: jobDefinition, + }), + {} + ) + : {}, + [moduleDefinition, sourceId, spaceId] + ); + + const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await moduleDescriptor.getModuleDefinition(); + }, + onResolve: response => { + setModuleDefinition(response); + }, + onReject: () => { + setModuleDefinition(undefined); + }, + }, + [moduleDescriptor.getModuleDefinition, spaceId, sourceId] + ); + + const getIsJobDefinitionOutdated = useCallback( + (jobSummary: JobSummary): boolean => { + const jobDefinition: JobDefinition | undefined = jobDefinitionByJobId[jobSummary.id]; + + if (jobDefinition == null) { + return false; + } + + const currentRevision = jobDefinition?.config.custom_settings.job_revision; + return (jobSummary.fullJob?.custom_settings?.job_revision ?? 0) < (currentRevision ?? 0); + }, + [jobDefinitionByJobId] + ); + + return { + fetchModuleDefinition, + fetchModuleDefinitionRequestState: fetchModuleDefinitionRequest.state, + getIsJobDefinitionOutdated, + jobDefinitionByJobId, + moduleDefinition, + }; +}; diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx index cf248f419f6f2..b5530f9ebf72e 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx @@ -7,25 +7,21 @@ import { useReducer } from 'react'; import { - JobSourceConfiguration, JobStatus, - SetupStatus, getDatafeedId, getJobId, isJobStatusWithResults, + SetupStatus, } from '../../../../common/log_analysis'; import { FetchJobStatusResponsePayload, JobSummary } from './api/ml_get_jobs_summary_api'; -import { GetMlModuleResponsePayload, JobDefinition } from './api/ml_get_module'; import { SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; import { MandatoryProperty } from '../../../../common/utility_types'; interface StatusReducerState { - jobDefinitions: JobDefinition[]; jobStatus: Record; jobSummaries: JobSummary[]; lastSetupErrorMessages: string[]; setupStatus: SetupStatus; - sourceConfiguration: JobSourceConfiguration; } type StatusReducerAction = @@ -34,8 +30,9 @@ type StatusReducerAction = type: 'finishedSetup'; sourceId: string; spaceId: string; - jobs: SetupMlModuleResponsePayload['jobs']; - datafeeds: SetupMlModuleResponsePayload['datafeeds']; + jobSetupResults: SetupMlModuleResponsePayload['jobs']; + jobSummaries: FetchJobStatusResponsePayload; + datafeedSetupResults: SetupMlModuleResponsePayload['datafeeds']; } | { type: 'failedSetup' } | { type: 'fetchingJobStatuses' } @@ -46,32 +43,15 @@ type StatusReducerAction = payload: FetchJobStatusResponsePayload; } | { type: 'failedFetchingJobStatuses' } - | { type: 'fetchingModuleDefinition' } - | { - type: 'fetchedModuleDefinition'; - spaceId: string; - sourceId: string; - moduleDefinition: GetMlModuleResponsePayload; - } - | { type: 'failedFetchingModuleDefinition' } - | { - type: 'updatedSourceConfiguration'; - spaceId: string; - sourceId: string; - sourceConfiguration: JobSourceConfiguration; - } | { type: 'requestedJobConfigurationUpdate' } | { type: 'requestedJobDefinitionUpdate' } | { type: 'viewedResults' }; const createInitialState = ({ jobTypes, - sourceConfiguration, }: { jobTypes: JobType[]; - sourceConfiguration: JobSourceConfiguration; }): StatusReducerState => ({ - jobDefinitions: [], jobStatus: jobTypes.reduce( (accumulatedJobStatus, jobType) => ({ ...accumulatedJobStatus, @@ -81,8 +61,7 @@ const createInitialState = ({ ), jobSummaries: [], lastSetupErrorMessages: [], - setupStatus: 'initializing', - sourceConfiguration, + setupStatus: { type: 'initializing' }, }); const createStatusReducer = (jobTypes: JobType[]) => ( @@ -100,39 +79,44 @@ const createStatusReducer = (jobTypes: JobType[]) => ( }), {} as Record ), - setupStatus: 'pending', + setupStatus: { type: 'pending' }, }; } case 'finishedSetup': { - const { jobs, datafeeds, spaceId, sourceId } = action; + const { datafeedSetupResults, jobSetupResults, jobSummaries, spaceId, sourceId } = action; const nextJobStatus = jobTypes.reduce( (accumulatedJobStatus, jobType) => ({ ...accumulatedJobStatus, [jobType]: - hasSuccessfullyCreatedJob(getJobId(spaceId, sourceId, jobType))(jobs) && - hasSuccessfullyStartedDatafeed(getDatafeedId(spaceId, sourceId, jobType))(datafeeds) + hasSuccessfullyCreatedJob(getJobId(spaceId, sourceId, jobType))(jobSetupResults) && + hasSuccessfullyStartedDatafeed(getDatafeedId(spaceId, sourceId, jobType))( + datafeedSetupResults + ) ? 'started' : 'failed', }), {} as Record ); - const nextSetupStatus = Object.values(nextJobStatus).every( + const nextSetupStatus: SetupStatus = Object.values(nextJobStatus).every( jobState => jobState === 'started' ) - ? 'succeeded' - : 'failed'; - const nextErrorMessages = [ - ...Object.values(datafeeds) - .filter(hasError) - .map(datafeed => datafeed.error.msg), - ...Object.values(jobs) - .filter(hasError) - .map(job => job.error.msg), - ]; + ? { type: 'succeeded' } + : { + type: 'failed', + reasons: [ + ...Object.values(datafeedSetupResults) + .filter(hasError) + .map(datafeed => datafeed.error.msg), + ...Object.values(jobSetupResults) + .filter(hasError) + .map(job => job.error.msg), + ], + }; + return { ...state, jobStatus: nextJobStatus, - lastSetupErrorMessages: nextErrorMessages, + jobSummaries, setupStatus: nextSetupStatus, }; } @@ -146,19 +130,19 @@ const createStatusReducer = (jobTypes: JobType[]) => ( }), {} as Record ), - setupStatus: 'failed', + setupStatus: { type: 'failed', reasons: ['unknown'] }, }; } - case 'fetchingModuleDefinition': case 'fetchingJobStatuses': { return { ...state, - setupStatus: state.setupStatus === 'unknown' ? 'initializing' : state.setupStatus, + setupStatus: + state.setupStatus.type === 'unknown' ? { type: 'initializing' } : state.setupStatus, }; } case 'fetchedJobStatuses': { const { payload: jobSummaries, spaceId, sourceId } = action; - const { jobDefinitions, setupStatus, sourceConfiguration } = state; + const { setupStatus } = state; const nextJobStatus = jobTypes.reduce( (accumulatedJobStatus, jobType) => ({ @@ -167,14 +151,7 @@ const createStatusReducer = (jobTypes: JobType[]) => ( }), {} as Record ); - const nextSetupStatus = getSetupStatus( - spaceId, - sourceId, - sourceConfiguration, - nextJobStatus, - jobDefinitions, - jobSummaries - )(setupStatus); + const nextSetupStatus = getSetupStatus(nextJobStatus)(setupStatus); return { ...state, @@ -186,7 +163,7 @@ const createStatusReducer = (jobTypes: JobType[]) => ( case 'failedFetchingJobStatuses': { return { ...state, - setupStatus: 'unknown', + setupStatus: { type: 'unknown' }, jobStatus: jobTypes.reduce( (accumulatedJobStatus, jobType) => ({ ...accumulatedJobStatus, @@ -196,60 +173,22 @@ const createStatusReducer = (jobTypes: JobType[]) => ( ), }; } - case 'fetchedModuleDefinition': { - const { spaceId, sourceId, moduleDefinition } = action; - const { jobStatus, jobSummaries, setupStatus, sourceConfiguration } = state; - - const nextSetupStatus = getSetupStatus( - spaceId, - sourceId, - sourceConfiguration, - jobStatus, - moduleDefinition.jobs, - jobSummaries - )(setupStatus); - - return { - ...state, - jobDefinitions: moduleDefinition.jobs, - setupStatus: nextSetupStatus, - }; - } - case 'updatedSourceConfiguration': { - const { spaceId, sourceId, sourceConfiguration } = action; - const { jobDefinitions, jobStatus, jobSummaries, setupStatus } = state; - - const nextSetupStatus = getSetupStatus( - spaceId, - sourceId, - sourceConfiguration, - jobStatus, - jobDefinitions, - jobSummaries - )(setupStatus); - - return { - ...state, - setupStatus: nextSetupStatus, - sourceConfiguration, - }; - } case 'requestedJobConfigurationUpdate': { return { ...state, - setupStatus: 'requiredForReconfiguration', + setupStatus: { type: 'required', reason: 'reconfiguration' }, }; } case 'requestedJobDefinitionUpdate': { return { ...state, - setupStatus: 'requiredForUpdate', + setupStatus: { type: 'required', reason: 'update' }, }; } case 'viewedResults': { return { ...state, - setupStatus: 'hiddenAfterSuccess', + setupStatus: { type: 'skipped', newlyCreated: true }, }; } default: { @@ -307,100 +246,28 @@ const getJobStatus = (jobId: string) => (jobSummaries: FetchJobStatusResponsePay } )[0] || 'missing'; -const getSetupStatus = ( - spaceId: string, - sourceId: string, - sourceConfiguration: JobSourceConfiguration, - everyJobStatus: Record, - jobDefinitions: JobDefinition[], - jobSummaries: JobSummary[] -) => (previousSetupStatus: SetupStatus) => - Object.entries(everyJobStatus).reduce( - (setupStatus, [jobType, jobStatus]) => { - const jobId = getJobId(spaceId, sourceId, jobType); - const jobDefinition = jobDefinitions.find(({ id }) => id === jobType); - - if (jobStatus === 'missing') { - return 'required'; - } else if ( - setupStatus === 'required' || - setupStatus === 'requiredForUpdate' || - setupStatus === 'requiredForReconfiguration' - ) { - return setupStatus; - } else if ( - jobDefinition && - !isJobRevisionCurrent( - jobId, - jobDefinition.config.custom_settings.job_revision || 0 - )(jobSummaries) - ) { - return 'skippedButUpdatable'; - } else if (!isJobConfigurationConsistent(jobId, sourceConfiguration)(jobSummaries)) { - return 'skippedButReconfigurable'; - } else if (setupStatus === 'hiddenAfterSuccess') { - return setupStatus; - } else if (setupStatus === 'skipped' || isJobStatusWithResults(jobStatus)) { - return 'skipped'; - } - +const getSetupStatus = (everyJobStatus: Record) => ( + previousSetupStatus: SetupStatus +): SetupStatus => + Object.entries(everyJobStatus).reduce((setupStatus, [, jobStatus]) => { + if (jobStatus === 'missing') { + return { type: 'required', reason: 'missing' }; + } else if (setupStatus.type === 'required') { return setupStatus; - }, - previousSetupStatus - ); - -const isJobRevisionCurrent = (jobId: string, currentRevision: number) => ( - jobSummaries: FetchJobStatusResponsePayload -): boolean => - jobSummaries - .filter(jobSummary => jobSummary.id === jobId) - .every( - jobSummary => (jobSummary?.fullJob?.custom_settings?.job_revision ?? 0) >= currentRevision - ); - -const isJobConfigurationConsistent = ( - jobId: string, - sourceConfiguration: { - bucketSpan: number; - indexPattern: string; - timestampField: string; - } -) => (jobSummaries: FetchJobStatusResponsePayload): boolean => - jobSummaries - .filter(jobSummary => jobSummary.id === jobId) - .every(jobSummary => { - if (!jobSummary.fullJob || !jobSummary.fullJob.custom_settings) { - return false; - } - - const jobConfiguration = jobSummary.fullJob.custom_settings.logs_source_config; - - return ( - jobConfiguration && - jobConfiguration.bucketSpan === sourceConfiguration.bucketSpan && - jobConfiguration.indexPattern && - isIndexPatternSubset(jobConfiguration.indexPattern, sourceConfiguration.indexPattern) && - jobConfiguration.timestampField === sourceConfiguration.timestampField - ); - }); - -const isIndexPatternSubset = (indexPatternSubset: string, indexPatternSuperset: string) => { - const subsetSubPatterns = indexPatternSubset.split(','); - const supersetSubPatterns = new Set(indexPatternSuperset.split(',')); + } else if (setupStatus.type === 'skipped' || isJobStatusWithResults(jobStatus)) { + return { + type: 'skipped', + // preserve newlyCreated status + newlyCreated: setupStatus.type === 'skipped' && setupStatus.newlyCreated, + }; + } - return subsetSubPatterns.every(subPattern => supersetSubPatterns.has(subPattern)); -}; + return setupStatus; + }, previousSetupStatus); const hasError = (value: Value): value is MandatoryProperty => value.error != null; -export const useModuleStatus = ( - jobTypes: JobType[], - sourceConfiguration: JobSourceConfiguration -) => { - return useReducer( - createStatusReducer(jobTypes), - { jobTypes, sourceConfiguration }, - createInitialState - ); +export const useModuleStatus = (jobTypes: JobType[]) => { + return useReducer(createStatusReducer(jobTypes), { jobTypes }, createInitialState); }; diff --git a/x-pack/plugins/infra/public/containers/logs/log_position/with_log_position_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_position/with_log_position_url_state.tsx index 0d3586f9376f3..ddd5b471a02c6 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_position/with_log_position_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_position/with_log_position_url_state.tsx @@ -144,5 +144,7 @@ export const replaceLogPositionInQueryString = (time: number) => time, tiebreaker: 0, }, + end: new Date(time + ONE_HOUR).toISOString(), + start: new Date(time - ONE_HOUR).toISOString(), streamLive: false, }); diff --git a/x-pack/plugins/infra/public/pages/link_to/index.ts b/x-pack/plugins/infra/public/pages/link_to/index.ts index 4c8051f8da73e..27e2d483f8fa9 100644 --- a/x-pack/plugins/infra/public/pages/link_to/index.ts +++ b/x-pack/plugins/infra/public/pages/link_to/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { LinkToPage } from './link_to'; +export { LinkToLogsPage } from './link_to_logs'; +export { LinkToMetricsPage } from './link_to_metrics'; export { getNodeLogsUrl, RedirectToNodeLogs } from './redirect_to_node_logs'; export { getNodeDetailUrl, RedirectToNodeDetail } from './redirect_to_node_detail'; diff --git a/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx b/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx new file mode 100644 index 0000000000000..04d5c454a92cc --- /dev/null +++ b/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { match as RouteMatch, Redirect, Route, Switch } from 'react-router-dom'; + +import { RedirectToLogs } from './redirect_to_logs'; +import { RedirectToNodeLogs } from './redirect_to_node_logs'; +import { inventoryModels } from '../../../common/inventory_models'; + +interface LinkToPageProps { + match: RouteMatch<{}>; + location: { + search: string; + }; +} + +const ITEM_TYPES = inventoryModels.map(m => m.id).join('|'); + +export const LinkToLogsPage: React.FC = props => { + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/infra/public/pages/link_to/link_to.tsx b/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx similarity index 68% rename from x-pack/plugins/infra/public/pages/link_to/link_to.tsx rename to x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx index ce62a0a3f4e33..3eb4a9f26fe2e 100644 --- a/x-pack/plugins/infra/public/pages/link_to/link_to.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx @@ -7,9 +7,7 @@ import React from 'react'; import { match as RouteMatch, Redirect, Route, Switch } from 'react-router-dom'; -import { RedirectToLogs } from './redirect_to_logs'; import { RedirectToNodeDetail } from './redirect_to_node_detail'; -import { RedirectToNodeLogs } from './redirect_to_node_logs'; import { RedirectToHostDetailViaIP } from './redirect_to_host_detail_via_ip'; import { inventoryModels } from '../../../common/inventory_models'; @@ -19,13 +17,9 @@ interface LinkToPageProps { const ITEM_TYPES = inventoryModels.map(m => m.id).join('|'); -export const LinkToPage: React.FC = props => { +export const LinkToMetricsPage: React.FC = props => { return ( - = props => { path={`${props.match.url}/host-detail-via-ip/:hostIp`} component={RedirectToHostDetailViaIP} /> - - + ); }; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_logs.test.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_logs.test.tsx index b4ed43f84e27f..0556955e47f66 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_logs.test.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_logs.test.tsx @@ -19,7 +19,7 @@ describe('RedirectToLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -33,7 +33,7 @@ describe('RedirectToLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx index 519ee64060932..1394fc48107ef 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx @@ -73,7 +73,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -89,7 +89,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx index d1c10820f7c9c..ed1aa9e72ebae 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx @@ -37,18 +37,13 @@ export const LogEntryCategoriesPageContent = () => { hasLogAnalysisSetupCapabilities, } = useLogAnalysisCapabilitiesContext(); - const { - fetchJobStatus, - fetchModuleDefinition, - setupStatus, - } = useLogEntryCategoriesModuleContext(); + const { fetchJobStatus, setupStatus } = useLogEntryCategoriesModuleContext(); useEffect(() => { if (hasLogAnalysisReadCapabilities) { - fetchModuleDefinition(); fetchJobStatus(); } - }, [fetchJobStatus, fetchModuleDefinition, hasLogAnalysisReadCapabilities]); + }, [fetchJobStatus, hasLogAnalysisReadCapabilities]); if (isLoadingSource || isUninitialized) { return ; @@ -58,7 +53,7 @@ export const LogEntryCategoriesPageContent = () => { return ; } else if (!hasLogAnalysisReadCapabilities) { return ; - } else if (setupStatus === 'initializing') { + } else if (setupStatus.type === 'initializing') { return ( { })} /> ); - } else if (setupStatus === 'unknown') { + } else if (setupStatus.type === 'unknown') { return ; } else if (isSetupStatusWithResults(setupStatus)) { return ; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx index b783aa9c79007..e304a8835e99c 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx @@ -9,17 +9,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiPage, EuiPanel, EuiSuperDatePicker } from import { i18n } from '@kbn/i18n'; import moment from 'moment'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; - import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; -import { euiStyled } from '../../../../../observability/public'; +import { euiStyled, useTrackPageview } from '../../../../../observability/public'; import { TimeRange } from '../../../../common/http_api/shared/time_range'; -import { - LogAnalysisJobProblemIndicator, - jobHasProblem, -} from '../../../components/logging/log_analysis_job_status'; -import { FirstUseCallout } from '../../../components/logging/log_analysis_results'; import { useInterval } from '../../../hooks/use_interval'; -import { useTrackPageview } from '../../../../../observability/public'; +import { CategoryJobNoticesSection } from './sections/notices/notices_section'; import { TopCategoriesSection } from './sections/top_categories'; import { useLogEntryCategoriesModuleContext } from './use_log_entry_categories_module'; import { useLogEntryCategoriesResults } from './use_log_entry_categories_results'; @@ -36,11 +30,15 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => { const { fetchJobStatus, - jobStatus, + fetchModuleDefinition, setupStatus, viewSetupForReconfiguration, viewSetupForUpdate, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, jobIds, + categoryQualityWarnings, sourceConfiguration: { sourceId }, } = useLogEntryCategoriesModuleContext(); @@ -124,12 +122,15 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => { [setAutoRefresh] ); - const isFirstUse = useMemo(() => setupStatus === 'hiddenAfterSuccess', [setupStatus]); - const hasResults = useMemo(() => topLogEntryCategories.length > 0, [ topLogEntryCategories.length, ]); + const isFirstUse = useMemo( + () => setupStatus.type === 'skipped' && !!setupStatus.newlyCreated && !hasResults, + [hasResults, setupStatus] + ); + useEffect(() => { getTopLogEntryCategories(); }, [getTopLogEntryCategories, categoryQueryDatasets, categoryQueryTimeRange.lastChangedTime]); @@ -138,6 +139,10 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => { getLogEntryCategoryDatasets(); }, [getLogEntryCategoryDatasets, categoryQueryTimeRange.lastChangedTime]); + useEffect(() => { + fetchModuleDefinition(); + }, [fetchModuleDefinition]); + useInterval(() => { fetchJobStatus(); }, JOB_STATUS_POLLING_INTERVAL); @@ -172,21 +177,17 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => { - {jobHasProblem(jobStatus['log-entry-categories-count'], setupStatus) ? ( - - - - ) : null} - {isFirstUse && !hasResults ? ( - - - - ) : null} + + + void; + onRecreateMlJobForUpdate: () => void; + qualityWarnings: QualityWarning[]; +}> = ({ + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + isFirstUse, + onRecreateMlJobForReconfiguration, + onRecreateMlJobForUpdate, + qualityWarnings, +}) => ( + <> + + + +); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warning_notices.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warning_notices.tsx new file mode 100644 index 0000000000000..73b6b88db873a --- /dev/null +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warning_notices.tsx @@ -0,0 +1,98 @@ +/* + * 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 { EuiCallOut } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React from 'react'; +import { CategoryQualityWarningReason, QualityWarning } from './quality_warnings'; + +export const CategoryQualityWarnings: React.FC<{ qualityWarnings: QualityWarning[] }> = ({ + qualityWarnings, +}) => ( + <> + {qualityWarnings.map((qualityWarning, qualityWarningIndex) => ( + +

+ +

+
    + {qualityWarning.reasons.map((reason, reasonIndex) => ( +
  • + +
  • + ))} +
+
+ ))} + +); + +const categoryQualityWarningCalloutTitle = i18n.translate( + 'xpack.infra.logs.logEntryCategories.categoryQUalityWarningCalloutTitle', + { + defaultMessage: 'Quality warning', + } +); + +const CategoryQualityWarningReasonDescription: React.FC<{ + reason: CategoryQualityWarningReason; +}> = ({ reason }) => { + switch (reason.type) { + case 'singleCategory': + return ( + + ); + case 'manyRareCategories': + return ( + + ); + case 'manyCategories': + return ( + + ); + case 'noFrequentCategories': + return ( + + ); + case 'manyDeadCategories': + return ( + + ); + } +}; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warnings.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warnings.tsx new file mode 100644 index 0000000000000..e0d3aa105e004 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/notices/quality_warnings.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +interface ManyCategoriesWarningReason { + type: 'manyCategories'; + categoriesDocumentRatio: number; +} + +interface ManyDeadCategoriesWarningReason { + type: 'manyDeadCategories'; + deadCategoriesRatio: number; +} + +interface ManyRareCategoriesWarningReason { + type: 'manyRareCategories'; + rareCategoriesRatio: number; +} + +interface NoFrequentCategoriesWarningReason { + type: 'noFrequentCategories'; +} + +interface SingleCategoryWarningReason { + type: 'singleCategory'; +} + +export type CategoryQualityWarningReason = + | ManyCategoriesWarningReason + | ManyDeadCategoriesWarningReason + | ManyRareCategoriesWarningReason + | NoFrequentCategoriesWarningReason + | SingleCategoryWarningReason; + +export type CategoryQualityWarningReasonType = CategoryQualityWarningReason['type']; + +export interface CategoryQualityWarning { + type: 'categoryQualityWarning'; + jobId: string; + reasons: CategoryQualityWarningReason[]; +} + +export type QualityWarning = CategoryQualityWarning; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx index 918c252f6350c..2917719af283b 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx @@ -6,12 +6,14 @@ import createContainer from 'constate'; import { useMemo } from 'react'; - import { - useLogAnalysisModule, ModuleSourceConfiguration, + useLogAnalysisModule, + useLogAnalysisModuleConfiguration, + useLogAnalysisModuleDefinition, } from '../../../containers/logs/log_analysis'; import { logEntryCategoriesModule } from './module_descriptor'; +import { useLogEntryCategoriesQuality } from './use_log_entry_categories_quality'; export const useLogEntryCategoriesModule = ({ indexPattern, @@ -34,10 +36,51 @@ export const useLogEntryCategoriesModule = ({ [indexPattern, sourceId, spaceId, timestampField] ); - return useLogAnalysisModule({ + const logAnalysisModule = useLogAnalysisModule({ + moduleDescriptor: logEntryCategoriesModule, + sourceConfiguration, + }); + + const { getIsJobConfigurationOutdated } = useLogAnalysisModuleConfiguration({ + sourceConfiguration, moduleDescriptor: logEntryCategoriesModule, + }); + + const { fetchModuleDefinition, getIsJobDefinitionOutdated } = useLogAnalysisModuleDefinition({ sourceConfiguration, + moduleDescriptor: logEntryCategoriesModule, + }); + + const { categoryQualityWarnings } = useLogEntryCategoriesQuality({ + jobSummaries: logAnalysisModule.jobSummaries, }); + + const hasOutdatedJobConfigurations = useMemo( + () => logAnalysisModule.jobSummaries.some(getIsJobConfigurationOutdated), + [getIsJobConfigurationOutdated, logAnalysisModule.jobSummaries] + ); + + const hasOutdatedJobDefinitions = useMemo( + () => logAnalysisModule.jobSummaries.some(getIsJobDefinitionOutdated), + [getIsJobDefinitionOutdated, logAnalysisModule.jobSummaries] + ); + + const hasStoppedJobs = useMemo( + () => + Object.values(logAnalysisModule.jobStatus).some( + currentJobStatus => currentJobStatus === 'stopped' + ), + [logAnalysisModule.jobStatus] + ); + + return { + ...logAnalysisModule, + categoryQualityWarnings, + fetchModuleDefinition, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + }; }; export const [ diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_quality.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_quality.ts new file mode 100644 index 0000000000000..031479e66386f --- /dev/null +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_quality.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useMemo } from 'react'; + +import { JobModelSizeStats, JobSummary } from '../../../containers/logs/log_analysis'; +import { QualityWarning, CategoryQualityWarningReason } from './sections/notices/quality_warnings'; + +export const useLogEntryCategoriesQuality = ({ jobSummaries }: { jobSummaries: JobSummary[] }) => { + const categoryQualityWarnings: QualityWarning[] = useMemo( + () => + jobSummaries + .filter( + jobSummary => jobSummary.fullJob?.model_size_stats?.categorization_status === 'warn' + ) + .map(jobSummary => ({ + type: 'categoryQualityWarning', + jobId: jobSummary.id, + reasons: jobSummary.fullJob?.model_size_stats + ? getCategoryQualityWarningReasons(jobSummary.fullJob.model_size_stats) + : [], + })), + [jobSummaries] + ); + + return { + categoryQualityWarnings, + }; +}; + +const getCategoryQualityWarningReasons = ({ + categorized_doc_count: categorizedDocCount, + dead_category_count: deadCategoryCount, + frequent_category_count: frequentCategoryCount, + rare_category_count: rareCategoryCount, + total_category_count: totalCategoryCount, +}: JobModelSizeStats): CategoryQualityWarningReason[] => { + const rareCategoriesRatio = rareCategoryCount / totalCategoryCount; + const categoriesDocumentRatio = totalCategoryCount / categorizedDocCount; + const deadCategoriesRatio = deadCategoryCount / totalCategoryCount; + + return [ + ...(totalCategoryCount === 1 + ? [ + { + type: 'singleCategory' as const, + }, + ] + : []), + ...(rareCategoriesRatio >= 0.9 + ? [ + { + type: 'manyRareCategories' as const, + rareCategoriesRatio, + }, + ] + : []), + ...(categorizedDocCount > 100 && categoriesDocumentRatio >= 0.5 + ? [ + { + type: 'manyCategories' as const, + categoriesDocumentRatio, + }, + ] + : []), + ...(frequentCategoryCount === 0 + ? [ + { + type: 'noFrequentCategories' as const, + }, + ] + : []), + ...(deadCategoriesRatio >= 0.5 + ? [ + { + type: 'manyDeadCategories' as const, + deadCategoriesRatio, + }, + ] + : []), + ]; +}; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index fe12ca5455a75..2f34e62d8e611 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -37,14 +37,13 @@ export const LogEntryRatePageContent = () => { hasLogAnalysisSetupCapabilities, } = useLogAnalysisCapabilitiesContext(); - const { fetchJobStatus, fetchModuleDefinition, setupStatus } = useLogEntryRateModuleContext(); + const { fetchJobStatus, setupStatus } = useLogEntryRateModuleContext(); useEffect(() => { if (hasLogAnalysisReadCapabilities) { - fetchModuleDefinition(); fetchJobStatus(); } - }, [fetchJobStatus, fetchModuleDefinition, hasLogAnalysisReadCapabilities]); + }, [fetchJobStatus, hasLogAnalysisReadCapabilities]); if (isLoadingSource || isUninitialized) { return ; @@ -54,7 +53,7 @@ export const LogEntryRatePageContent = () => { return ; } else if (!hasLogAnalysisReadCapabilities) { return ; - } else if (setupStatus === 'initializing') { + } else if (setupStatus.type === 'initializing') { return ( { })} /> ); - } else if (setupStatus === 'unknown') { + } else if (setupStatus.type === 'unknown') { return ; } else if (isSetupStatusWithResults(setupStatus)) { return ; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index 50d58865e9746..156c9a919440e 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -11,21 +11,19 @@ import { EuiFlexItem, EuiPage, EuiPanel, - EuiSpacer, EuiSuperDatePicker, EuiText, } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; -import React, { useCallback, useMemo, useState, useEffect } from 'react'; - -import { euiStyled } from '../../../../../observability/public'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { euiStyled, useTrackPageview } from '../../../../../observability/public'; import { TimeRange } from '../../../../common/http_api/shared/time_range'; import { bucketSpan } from '../../../../common/log_analysis'; import { LoadingOverlayWrapper } from '../../../components/loading_overlay_wrapper'; +import { LogAnalysisJobProblemIndicator } from '../../../components/logging/log_analysis_job_status'; import { useInterval } from '../../../hooks/use_interval'; -import { useTrackPageview } from '../../../../../observability/public'; import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; import { AnomaliesResults } from './sections/anomalies'; import { LogRateResults } from './sections/log_rate'; @@ -35,7 +33,6 @@ import { StringTimeRange, useLogAnalysisResultsUrlState, } from './use_log_entry_rate_results_url_state'; -import { FirstUseCallout } from '../../../components/logging/log_analysis_results'; const JOB_STATUS_POLLING_INTERVAL = 30000; @@ -47,10 +44,13 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => { const { fetchJobStatus, - jobStatus, + fetchModuleDefinition, setupStatus, viewSetupForReconfiguration, viewSetupForUpdate, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, jobIds, sourceConfiguration: { sourceId }, } = useLogEntryRateModuleContext(); @@ -82,10 +82,6 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => { bucketDuration, }); - const hasResults = useMemo(() => (logEntryRate?.histogramBuckets?.length ?? 0) > 0, [ - logEntryRate, - ]); - const handleQueryTimeRangeChange = useCallback( ({ start: startTime, end: endTime }: { start: string; end: string }) => { setQueryTimeRange({ @@ -131,12 +127,23 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => { [setAutoRefresh] ); - const isFirstUse = useMemo(() => setupStatus === 'hiddenAfterSuccess', [setupStatus]); + const hasResults = useMemo(() => (logEntryRate?.histogramBuckets?.length ?? 0) > 0, [ + logEntryRate, + ]); + + const isFirstUse = useMemo( + () => setupStatus.type === 'skipped' && !!setupStatus.newlyCreated && !hasResults, + [hasResults, setupStatus] + ); useEffect(() => { getLogEntryRate(); }, [getLogEntryRate, queryTimeRange.lastChangedTime]); + useEffect(() => { + fetchModuleDefinition(); + }, [fetchModuleDefinition]); + useInterval(() => { fetchJobStatus(); }, JOB_STATUS_POLLING_INTERVAL); @@ -195,14 +202,18 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
+ + + - {isFirstUse && !hasResults ? ( - <> - - - - ) : null} { diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx index 2551170c44f4e..e216162d7a295 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx @@ -20,7 +20,7 @@ import React, { useMemo } from 'react'; import { euiStyled } from '../../../../../../../observability/public'; import { LogEntryRateResults } from '../../use_log_entry_rate_results'; import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; -import { formatAnomalyScore, JobStatus, SetupStatus } from '../../../../../../common/log_analysis'; +import { formatAnomalyScore } from '../../../../../../common/log_analysis'; import { getAnnotationsForAll, getLogEntryRateCombinedSeries, @@ -28,34 +28,18 @@ import { } from '../helpers/data_formatters'; import { AnomaliesChart } from './chart'; import { AnomaliesTable } from './table'; -import { - LogAnalysisJobProblemIndicator, - RecreateJobButton, -} from '../../../../../components/logging/log_analysis_job_status'; +import { RecreateJobButton } from '../../../../../components/logging/log_analysis_job_status'; import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results'; import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; export const AnomaliesResults: React.FunctionComponent<{ isLoading: boolean; - jobStatus: JobStatus; results: LogEntryRateResults | null; setTimeRange: (timeRange: TimeRange) => void; - setupStatus: SetupStatus; timeRange: TimeRange; viewSetupForReconfiguration: () => void; - viewSetupForUpdate: () => void; jobId: string; -}> = ({ - isLoading, - jobStatus, - results, - setTimeRange, - setupStatus, - timeRange, - viewSetupForReconfiguration, - viewSetupForUpdate, - jobId, -}) => { +}> = ({ isLoading, results, setTimeRange, timeRange, viewSetupForReconfiguration, jobId }) => { const hasAnomalies = useMemo(() => { return results && results.histogramBuckets ? results.histogramBuckets.some(bucket => { @@ -100,20 +84,13 @@ export const AnomaliesResults: React.FunctionComponent<{ - + - - }> {!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? ( logAnalysisModule.jobSummaries.some(getIsJobConfigurationOutdated), + [getIsJobConfigurationOutdated, logAnalysisModule.jobSummaries] + ); + + const hasOutdatedJobDefinitions = useMemo( + () => logAnalysisModule.jobSummaries.some(getIsJobDefinitionOutdated), + [getIsJobDefinitionOutdated, logAnalysisModule.jobSummaries] + ); + + const hasStoppedJobs = useMemo( + () => + Object.values(logAnalysisModule.jobStatus).some( + currentJobStatus => currentJobStatus === 'stopped' + ), + [logAnalysisModule.jobStatus] + ); + + return { + ...logAnalysisModule, + fetchModuleDefinition, + hasOutdatedJobConfigurations, + hasOutdatedJobDefinitions, + hasStoppedJobs, + }; }; export const [LogEntryRateModuleProvider, useLogEntryRateModuleContext] = createContainer( diff --git a/x-pack/plugins/infra/public/routers/logs_router.tsx b/x-pack/plugins/infra/public/routers/logs_router.tsx index 6700ed1fc8479..8258f087b5872 100644 --- a/x-pack/plugins/infra/public/routers/logs_router.tsx +++ b/x-pack/plugins/infra/public/routers/logs_router.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { Route, Router, Switch } from 'react-router-dom'; import { NotFoundPage } from '../pages/404'; -import { LinkToPage } from '../pages/link_to'; +import { LinkToLogsPage } from '../pages/link_to'; import { LogsPage } from '../pages/logs'; import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; @@ -19,7 +19,7 @@ export const LogsRouter: AppRouter = ({ history }) => { return ( - + {uiCapabilities?.logs?.show && ( )} diff --git a/x-pack/plugins/infra/public/routers/metrics_router.tsx b/x-pack/plugins/infra/public/routers/metrics_router.tsx index 7c2ebed8463f1..7cb9de65e7291 100644 --- a/x-pack/plugins/infra/public/routers/metrics_router.tsx +++ b/x-pack/plugins/infra/public/routers/metrics_router.tsx @@ -9,7 +9,7 @@ import { Route, Router, Switch } from 'react-router-dom'; import { NotFoundPage } from '../pages/404'; import { InfrastructurePage } from '../pages/infrastructure'; -import { LinkToPage } from '../pages/link_to'; +import { LinkToMetricsPage } from '../pages/link_to'; import { MetricDetail } from '../pages/metrics'; import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; @@ -20,7 +20,7 @@ export const MetricsRouter: AppRouter = ({ history }) => { return ( - + {uiCapabilities?.infrastructure?.show && ( )} diff --git a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts index 3a5dff75f004e..b8513541be7ae 100644 --- a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts @@ -112,7 +112,7 @@ export class InfraKibanaLogEntriesAdapter implements LogEntriesAdapter { ); const hits = sortDirection === 'asc' ? esResult.hits.hits : esResult.hits.hits.reverse(); - return mapHitsToLogEntryDocuments(hits, sourceConfiguration.fields.timestamp, fields); + return mapHitsToLogEntryDocuments(hits, fields); } public async getContainedLogSummaryBuckets( @@ -226,11 +226,7 @@ export class InfraKibanaLogEntriesAdapter implements LogEntriesAdapter { } } -function mapHitsToLogEntryDocuments( - hits: SortedSearchHit[], - timestampField: string, - fields: string[] -): LogEntryDocument[] { +function mapHitsToLogEntryDocuments(hits: SortedSearchHit[], fields: string[]): LogEntryDocument[] { return hits.map(hit => { const logFields = fields.reduce<{ [fieldName: string]: JsonValue }>( (flattenedFields, field) => { @@ -243,10 +239,8 @@ function mapHitsToLogEntryDocuments( ); return { - gid: hit._id, - // timestamp: hit._source[timestampField], - // FIXME s/key/cursor/g - key: { time: hit.sort[0], tiebreaker: hit.sort[1] }, + id: hit._id, + cursor: { time: hit.sort[0], tiebreaker: hit.sort[1] }, fields: logFields, highlights: hit.highlight || {}, }; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index 778889ba0c7a5..bfe04b82b95fc 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -11,6 +11,10 @@ import { getAllCompositeData } from '../../../utils/get_all_composite_data'; import { networkTraffic } from '../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; import { MetricExpressionParams, Comparator, AlertStates } from './types'; import { AlertServices, AlertExecutorOptions } from '../../../../../alerting/server'; +import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; +import { getDateHistogramOffset } from '../../snapshot/query_helpers'; + +const TOTAL_BUCKETS = 5; interface Aggregation { aggregatedIntervals: { @@ -70,6 +74,12 @@ export const getElasticsearchMetricQuery = ( throw new Error('Can only aggregate without a metric if using the document count aggregator'); } const interval = `${timeSize}${timeUnit}`; + const to = Date.now(); + const intervalAsSeconds = getIntervalInSeconds(interval); + // We need enough data for 5 buckets worth of data. We also need + // to convert the intervalAsSeconds to milliseconds. + const from = to - intervalAsSeconds * 1000 * TOTAL_BUCKETS; + const offset = getDateHistogramOffset(from, interval); const aggregations = aggType === 'count' @@ -89,6 +99,11 @@ export const getElasticsearchMetricQuery = ( date_histogram: { field: '@timestamp', fixed_interval: interval, + offset, + extended_bounds: { + min: from, + max: to, + }, }, aggregations, }, @@ -118,7 +133,9 @@ export const getElasticsearchMetricQuery = ( { range: { '@timestamp': { - gte: `now-${interval}`, + gte: from, + lte: to, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index 9a2631e3c2f76..528b9a69327fa 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -7,7 +7,6 @@ import { sortBy } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; -import { TimeKey } from '../../../../common/time'; import { JsonObject } from '../../../../common/typed_json'; import { LogEntriesSummaryBucket, @@ -50,15 +49,15 @@ export interface LogEntriesAroundParams { export const LOG_ENTRIES_PAGE_SIZE = 200; +const FIELDS_FROM_CONTEXT = ['log.file.path', 'host.name', 'container.id'] as const; + export class InfraLogEntriesDomain { constructor( private readonly adapter: LogEntriesAdapter, private readonly libs: { sources: InfraSources } ) {} - /* Name is temporary until we can clean up the GraphQL implementation */ - /* eslint-disable-next-line @typescript-eslint/camelcase */ - public async getLogEntriesAround__new( + public async getLogEntriesAround( requestContext: RequestHandlerContext, sourceId: string, params: LogEntriesAroundParams @@ -133,14 +132,14 @@ export class InfraLogEntriesDomain { const entries = documents.map(doc => { return { - id: doc.gid, - cursor: doc.key, + id: doc.id, + cursor: doc.cursor, columns: configuration.logColumns.map( (column): LogColumn => { if ('timestampColumn' in column) { return { columnId: column.timestampColumn.id, - timestamp: doc.key.time, + timestamp: doc.cursor.time, }; } else if ('messageColumn' in column) { return { @@ -157,6 +156,14 @@ export class InfraLogEntriesDomain { } } ), + context: FIELDS_FROM_CONTEXT.reduce((ctx, field) => { + // Users might have different types here in their mappings. + const value = doc.fields[field]; + if (typeof value === 'string') { + ctx[field] = value; + } + return ctx; + }, {}), }; }); @@ -292,17 +299,17 @@ export interface LogEntriesAdapter { export type LogEntryQuery = JsonObject; export interface LogEntryDocument { + id: string; fields: Fields; - gid: string; highlights: Highlights; - key: TimeKey; + cursor: LogEntriesCursor; } export interface LogSummaryBucket { entriesCount: number; start: number; end: number; - topEntryKeys: TimeKey[]; + topEntryKeys: LogEntriesCursor[]; } const logSummaryBucketHasEntries = (bucket: LogSummaryBucket) => @@ -332,7 +339,9 @@ const getRequiredFields = ( ); const fieldsFromFormattingRules = messageFormattingRules.requiredFields; - return Array.from(new Set([...fieldsFromCustomColumns, ...fieldsFromFormattingRules])); + return Array.from( + new Set([...fieldsFromCustomColumns, ...fieldsFromFormattingRules, ...FIELDS_FROM_CONTEXT]) + ); }; const createHighlightQueryDsl = (phrase: string, fields: string[]) => ({ diff --git a/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts b/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts index 383dc9a773abe..82a393079745f 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/query_helpers.ts @@ -87,8 +87,7 @@ export const getMetricsAggregations = (options: InfraSnapshotRequestOptions): Sn return aggregation; }; -export const getDateHistogramOffset = (options: InfraSnapshotRequestOptions): string => { - const { from, interval } = options.timerange; +export const getDateHistogramOffset = (from: number, interval: string): string => { const fromInSeconds = Math.floor(from / 1000); const bucketSizeInSeconds = getIntervalInSeconds(interval); diff --git a/x-pack/plugins/infra/server/lib/snapshot/snapshot.ts b/x-pack/plugins/infra/server/lib/snapshot/snapshot.ts index 8e5f8e6716f3c..07abfa5fd474a 100644 --- a/x-pack/plugins/infra/server/lib/snapshot/snapshot.ts +++ b/x-pack/plugins/infra/server/lib/snapshot/snapshot.ts @@ -159,7 +159,7 @@ const requestNodeMetrics = async ( date_histogram: { field: options.sourceConfiguration.fields.timestamp, interval: options.timerange.interval || '1m', - offset: getDateHistogramOffset(options), + offset: getDateHistogramOffset(options.timerange.from, options.timerange.interval), extended_bounds: { min: options.timerange.from, max: options.timerange.to, diff --git a/x-pack/plugins/infra/server/routes/log_entries/entries.ts b/x-pack/plugins/infra/server/routes/log_entries/entries.ts index f33dfa71fedcd..2cd889d9c5568 100644 --- a/x-pack/plugins/infra/server/routes/log_entries/entries.ts +++ b/x-pack/plugins/infra/server/routes/log_entries/entries.ts @@ -48,7 +48,7 @@ export const initLogEntriesRoute = ({ framework, logEntries }: InfraBackendLibs) let entries; if ('center' in payload) { - entries = await logEntries.getLogEntriesAround__new(requestContext, sourceId, { + entries = await logEntries.getLogEntriesAround(requestContext, sourceId, { startTimestamp, endTimestamp, query: parseFilterQuery(query), diff --git a/x-pack/plugins/infra/server/routes/log_entries/highlights.ts b/x-pack/plugins/infra/server/routes/log_entries/highlights.ts index 2e581d96cab9c..9a61c8fa5aa9b 100644 --- a/x-pack/plugins/infra/server/routes/log_entries/highlights.ts +++ b/x-pack/plugins/infra/server/routes/log_entries/highlights.ts @@ -45,7 +45,7 @@ export const initLogEntriesHighlightsRoute = ({ framework, logEntries }: InfraBa if ('center' in payload) { entriesPerHighlightTerm = await Promise.all( highlightTerms.map(highlightTerm => - logEntries.getLogEntriesAround__new(requestContext, sourceId, { + logEntries.getLogEntriesAround(requestContext, sourceId, { startTimestamp, endTimestamp, query: parseFilterQuery(query), diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx index 57031a3d72abe..79f85b0eecdf6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/yaml/index.tsx @@ -32,7 +32,7 @@ export const ConfigYamlView = memo<{ config: AgentConfig }>(({ config }) => { const fullConfigRequest = useGetOneAgentConfigFull(config.id); const apiKeysRequest = useGetEnrollmentAPIKeys(); - const apiKeyRequest = useGetOneEnrollmentAPIKey(apiKeysRequest.data?.list?.[0].id as string); + const apiKeyRequest = useGetOneEnrollmentAPIKey(apiKeysRequest.data?.list?.[0]?.id as string); if (fullConfigRequest.isLoading && !fullConfigRequest.data) { return ; @@ -49,30 +49,30 @@ export const ConfigYamlView = memo<{ config: AgentConfig }>(({ config }) => { })} - - -

+ {apiKeyRequest.data && ( + + +

+ +

+
+ + -

-
- - - - - - {apiKeyRequest.data && ( +
+ - )} - + + )} ); }); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx index 2e321e8bfc36f..c164138e35740 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/markdown_renderers.tsx @@ -28,9 +28,7 @@ export const markdownRenderers = { {children} ), table: ({ children }: { children: React.ReactNode[] }) => ( - - {children} -
+ {children}
), tableRow: ({ children }: { children: React.ReactNode[] }) => ( {children} diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index 99dcebd9bfba1..d7be1c1f1fe6e 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -32,7 +32,9 @@ export interface IngestManagerStartDeps { data: DataPublicPluginStart; } -export class IngestManagerPlugin implements Plugin { +export class IngestManagerPlugin + implements + Plugin { private config: IngestManagerConfigType; constructor(private readonly initializerContext: PluginInitializerContext) { @@ -50,7 +52,8 @@ export class IngestManagerPlugin implements Plugin { async mount(params: AppMountParameters) { const [coreStart, startDeps] = (await core.getStartServices()) as [ CoreStart, - IngestManagerStartDeps + IngestManagerStartDeps, + IngestManagerStart ]; const { renderApp } = await import('./applications/ingest_manager'); return renderApp(coreStart, params, deps, startDeps, config); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts index ba4b3135aac1d..7c315f7616e1f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts @@ -6,6 +6,7 @@ import { Response } from 'node-fetch'; import { URL } from 'url'; +import { sortBy } from 'lodash'; import { AssetParts, AssetsGroupedByServiceByType, @@ -50,7 +51,11 @@ export async function fetchFindLatestPackage( const res = await fetchUrl(url.toString()); const searchResults = JSON.parse(res); if (searchResults.length) { - return searchResults[0]; + // sort by version, then get the last (most recent) + const latestPackage = sortBy(searchResults, ['version'])[ + searchResults.length - 1 + ]; + return latestPackage; } else { throw new Error('package not found'); } diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 867a7454f0448..6abdaad7903be 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -4,5 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": false, - "optionalPlugins": ["usageCollection", "taskManager"] + "optionalPlugins": ["usageCollection", "taskManager"], + "configPath": ["xpack", "lens"] } diff --git a/x-pack/plugins/lens/server/plugin.tsx b/x-pack/plugins/lens/server/plugin.tsx index e805f9f7e0a92..3611658fbbcd9 100644 --- a/x-pack/plugins/lens/server/plugin.tsx +++ b/x-pack/plugins/lens/server/plugin.tsx @@ -14,6 +14,7 @@ import { initializeLensTelemetry, scheduleLensTelemetry, } from './usage'; +import { setupSavedObjects } from './saved_objects'; export interface PluginSetupContract { usageCollection?: UsageCollectionSetup; @@ -33,6 +34,7 @@ export class LensServerPlugin implements Plugin<{}, {}, {}, {}> { this.telemetryLogger = initializerContext.logger.get('telemetry'); } setup(core: CoreSetup, plugins: PluginSetupContract) { + setupSavedObjects(core); setupRoutes(core); if (plugins.usageCollection && plugins.taskManager) { registerLensUsageCollector( diff --git a/x-pack/plugins/lens/server/saved_objects.ts b/x-pack/plugins/lens/server/saved_objects.ts new file mode 100644 index 0000000000000..42dc750878f45 --- /dev/null +++ b/x-pack/plugins/lens/server/saved_objects.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { CoreSetup } from 'kibana/server'; +import { getEditPath } from '../common'; + +export function setupSavedObjects(core: CoreSetup) { + core.savedObjects.registerType({ + name: 'lens', + hidden: false, + namespaceAgnostic: false, + management: { + icon: 'lensApp', + defaultSearchField: 'title', + importableAndExportable: true, + getTitle: (obj: { attributes: { title: string } }) => obj.attributes.title, + getInAppUrl: (obj: { id: string }) => ({ + path: getEditPath(obj.id), + uiCapabilitiesPath: 'visualize.show', + }), + }, + mappings: { + properties: { + title: { + type: 'text', + }, + visualizationType: { + type: 'keyword', + }, + state: { + type: 'flattened', + }, + expression: { + index: false, + type: 'keyword', + }, + }, + }, + }); + + core.savedObjects.registerType({ + name: 'lens-ui-telemetry', + hidden: false, + namespaceAgnostic: false, + mappings: { + properties: { + name: { + type: 'keyword', + }, + type: { + type: 'keyword', + }, + date: { + type: 'date', + }, + count: { + type: 'integer', + }, + }, + }, + }); +} diff --git a/x-pack/plugins/license_management/public/index.ts b/x-pack/plugins/license_management/public/index.ts index 3c76549ebdc16..99f715f9718f6 100644 --- a/x-pack/plugins/license_management/public/index.ts +++ b/x-pack/plugins/license_management/public/index.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { PluginInitializerContext } from 'src/core/public'; - import { LicenseManagementUIPlugin } from './plugin'; import './application/index.scss'; +export { LicenseManagementUIPluginSetup, LicenseManagementUIPluginStart } from './plugin'; export const plugin = (ctx: PluginInitializerContext) => new LicenseManagementUIPlugin(ctx); diff --git a/x-pack/plugins/license_management/public/plugin.ts b/x-pack/plugins/license_management/public/plugin.ts index 00d353bc97e04..1d309f229cb8b 100644 --- a/x-pack/plugins/license_management/public/plugin.ts +++ b/x-pack/plugins/license_management/public/plugin.ts @@ -20,17 +20,25 @@ interface PluginsDependencies { telemetry?: TelemetryPluginSetup; } -export class LicenseManagementUIPlugin implements Plugin { +export interface LicenseManagementUIPluginSetup { + enabled: boolean; +} +export type LicenseManagementUIPluginStart = void; + +export class LicenseManagementUIPlugin + implements Plugin { private breadcrumbService = new BreadcrumbService(); constructor(private readonly initializerContext: PluginInitializerContext) {} - setup(coreSetup: CoreSetup, plugins: PluginsDependencies) { + setup(coreSetup: CoreSetup, plugins: PluginsDependencies): LicenseManagementUIPluginSetup { const config = this.initializerContext.config.get(); if (!config.ui.enabled) { // No need to go any further - return; + return { + enabled: false, + }; } const { getStartServices } = coreSetup; @@ -76,8 +84,12 @@ export class LicenseManagementUIPlugin implements Plugin { return renderApp(element, appDependencies); }, }); + + return { + enabled: true, + }; } - start() {} + start(): LicenseManagementUIPluginStart {} stop() {} } diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 12b03f0386304..814825483d0dd 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -188,7 +188,7 @@ export enum LABEL_BORDER_SIZES { LARGE = 'LARGE', } -export const DEFAULT_ICON = 'airfield'; +export const DEFAULT_ICON = 'marker'; export enum VECTOR_STYLES { SYMBOLIZE_AS = 'symbolizeAs', diff --git a/x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts similarity index 100% rename from x-pack/legacy/plugins/maps/common/data_request_descriptor_types.d.ts rename to x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts similarity index 99% rename from x-pack/legacy/plugins/maps/common/descriptor_types.d.ts rename to x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts index cfbcb65255ab2..fb49e1aaebe1c 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts @@ -5,7 +5,7 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER, SCALING_TYPES } from './constants'; +import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER, SCALING_TYPES } from '../constants'; import { VectorStyleDescriptor } from './style_property_descriptor_types'; import { DataRequestDescriptor } from './data_request_descriptor_types'; diff --git a/x-pack/plugins/advanced_ui_actions/public/util/index.ts b/x-pack/plugins/maps/common/descriptor_types/index.ts similarity index 58% rename from x-pack/plugins/advanced_ui_actions/public/util/index.ts rename to x-pack/plugins/maps/common/descriptor_types/index.ts index fd3ab89973348..af0f4487f471b 100644 --- a/x-pack/plugins/advanced_ui_actions/public/util/index.ts +++ b/x-pack/plugins/maps/common/descriptor_types/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { - UiActionsConfigurable as Configurable, - UiActionsCollectConfigProps as CollectConfigProps, -} from '../../../../../src/plugins/ui_actions/public'; +export * from './data_request_descriptor_types'; +export * from './descriptor_types'; +export * from './map_descriptor'; +export * from './style_property_descriptor_types'; diff --git a/x-pack/legacy/plugins/maps/common/map_descriptor.ts b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts similarity index 100% rename from x-pack/legacy/plugins/maps/common/map_descriptor.ts rename to x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts diff --git a/x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.d.ts similarity index 99% rename from x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts rename to x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.d.ts index 2fce56339e106..47e56ff96d623 100644 --- a/x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.d.ts @@ -12,7 +12,7 @@ import { VECTOR_STYLES, STYLE_TYPE, LAYER_STYLE_TYPE, -} from './constants'; +} from '../constants'; // Non-static/dynamic options export type SymbolizeAsOptions = { diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index c465700a4f9c5..e3feb47691877 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -10,3 +10,5 @@ import { MapsPlugin, MapsPluginSetup, MapsPluginStart } from './plugin'; export const plugin: PluginInitializer = () => { return new MapsPlugin(); }; + +export { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; diff --git a/x-pack/plugins/maps/public/reducers/non_serializable_instances.d.ts b/x-pack/plugins/maps/public/reducers/non_serializable_instances.d.ts new file mode 100644 index 0000000000000..6d216eb60c45d --- /dev/null +++ b/x-pack/plugins/maps/public/reducers/non_serializable_instances.d.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Adapters } from 'src/plugins/inspector/public'; +import { AnyAction } from 'redux'; + +interface EventHandlers { + /** + * Take action on data load. + */ + onDataLoad: (layerId: string, dataId: string) => void; + /** + * Take action on data load end. + */ + onDataLoadEnd: (layerId: string, dataId: string, resultMeta: object) => void; + /** + * Take action on data load error. + */ + onDataLoadError: (layerId: string, dataId: string, errorMessage: string) => void; +} + +export function setEventHandlers(eventHandlers?: EventHandlers): AnyAction; + +export function getInspectorAdapters(args: unknown): Adapters | undefined; diff --git a/x-pack/plugins/dashboard_enhanced/server/index.ts b/x-pack/plugins/maps/public/reducers/store.d.ts similarity index 69% rename from x-pack/plugins/dashboard_enhanced/server/index.ts rename to x-pack/plugins/maps/public/reducers/store.d.ts index e361b9fb075ed..ebed396e20399 100644 --- a/x-pack/plugins/dashboard_enhanced/server/index.ts +++ b/x-pack/plugins/maps/public/reducers/store.d.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export { config } from './config'; +import { Store } from 'redux'; -export const plugin = () => ({ - setup() {}, - start() {}, -}); +export type MapStore = Store; + +export function createMapStore(): MapStore; diff --git a/x-pack/plugins/ml/common/constants/search.ts b/x-pack/plugins/ml/common/constants/search.ts index e17f6b3098421..da65748668a4f 100644 --- a/x-pack/plugins/ml/common/constants/search.ts +++ b/x-pack/plugins/ml/common/constants/search.ts @@ -11,3 +11,8 @@ export enum SEARCH_QUERY_LANGUAGE { KUERY = 'kuery', LUCENE = 'lucene', } + +export interface ErrorMessage { + query: string; + message: string; +} diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index b6db289f4be6d..038f61b3a33b7 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -18,7 +18,8 @@ "optionalPlugins": [ "security", "spaces", - "management" + "management", + "licenseManagement" ], "server": true, "ui": true diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 8c3e0c066f411..e9796fcbb0fe4 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -37,6 +37,7 @@ const App: FC = ({ coreStart, deps }) => { appName: 'ML', data: deps.data, security: deps.security, + licenseManagement: deps.licenseManagement, storage: localStorage, ...coreStart, }; diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/influencers_cell.js b/x-pack/plugins/ml/public/application/components/anomalies_table/influencers_cell.js index 7d00c9818a1e2..f4b16dab5ef52 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/influencers_cell.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/influencers_cell.js @@ -56,7 +56,7 @@ export class InfluencersCell extends Component { } > influencerFilter( @@ -83,7 +83,7 @@ export class InfluencersCell extends Component { } > influencerFilter( diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js index 7da49a378ec96..2a34f12330a75 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -21,7 +21,7 @@ import { checkPermission } from '../../privilege/check_privilege'; import { SEARCH_QUERY_LANGUAGE } from '../../../../common/constants/search'; import { isRuleSupported } from '../../../../common/util/anomaly_utils'; import { parseInterval } from '../../../../common/util/parse_interval'; -import { escapeDoubleQuotes } from '../kql_filter_bar/utils'; +import { escapeDoubleQuotes } from '../../explorer/explorer_utils'; import { getFieldTypeFromMapping } from '../../services/mapping_service'; import { ml } from '../../services/ml_api_service'; import { mlJobService } from '../../services/job_service'; diff --git a/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.js b/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.js index 259e0d335c40f..02a9e569f28a4 100644 --- a/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.js +++ b/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.js @@ -22,7 +22,7 @@ function getAddFilter({ entityName, entityValue, filter }) { } > filter(entityName, entityValue, '+')} iconType="plusInCircle" @@ -45,7 +45,7 @@ function getRemoveFilter({ entityName, entityValue, filter }) { } > filter(entityName, entityValue, '-')} iconType="minusInCircle" diff --git a/x-pack/plugins/ml/public/application/components/influencers_list/influencers_list.js b/x-pack/plugins/ml/public/application/components/influencers_list/influencers_list.js index 5a31dcef51676..1044caa83e2ad 100644 --- a/x-pack/plugins/ml/public/application/components/influencers_list/influencers_list.js +++ b/x-pack/plugins/ml/public/application/components/influencers_list/influencers_list.js @@ -57,7 +57,7 @@ function Influencer({ influencerFieldName, influencerFilter, valueData }) { return (
-
+
{influencerFieldName !== 'mlcategory' ? ( - - -`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/__tests__/utils.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/__tests__/utils.js deleted file mode 100644 index 6029799ffe8b8..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/__tests__/utils.js +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { removeFilterFromQueryString, getQueryPattern, escapeRegExp } from '../utils'; - -describe('ML - KqlFilterBar utils', () => { - const fieldName = 'http.response.status_code'; - const fieldValue = '200'; - const speciaCharFieldName = 'normal(brackets)name'; - const speciaCharFieldValue = '<>:;[})'; - - describe('removeFilterFromQueryString', () => { - it('removes selected fieldName/fieldValue from query string with one value', () => { - const currentQueryString = 'http.response.status_code : "200"'; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it('removes selected fieldName/fieldValue of type number from existing query string with one value', () => { - const currentQueryString = 'http.response.status_code : 200'; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it('removes selected fieldName/fieldValue from query string with multiple values', () => { - const currentQueryString = 'test_field : test_value or http.response.status_code : "200"'; - const expectedOutput = 'test_field : test_value'; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it('removes selected fieldName/fieldValue of type number from existing query string with multiple values', () => { - const currentQueryString = 'http.response.status_code : 200 or test_field : test_value'; - const expectedOutput = 'test_field : test_value'; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it("removes 'and' from end of the query to ensure kuery syntax is valid", () => { - const currentQueryString = 'http.response.status_code : "200" and'; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it("removes 'or' from end of the query to ensure kuery syntax is valid", () => { - const currentQueryString = 'http.response.status_code : "200" or'; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it("removes 'and' from start of the query to ensure kuery syntax is valid", () => { - const currentQueryString = ' and http.response.status_code : "200"'; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it("removes 'or' from start of the query to ensure kuery syntax is valid", () => { - const currentQueryString = ' or http.response.status_code : "200" '; - const expectedOutput = ''; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it('removes selected fieldName/fieldValue correctly from AND query string when it is the middle value', () => { - const currentQueryString = `http.response.status_code : "400" and http.response.status_code : "200" - and http.response.status_code : "300"`; - const expectedOutput = - 'http.response.status_code : "400" and http.response.status_code : "300"'; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - - it('removes selected fieldName/fieldValue correctly from OR query string when it is the middle value', () => { - const currentQueryString = `http.response.status_code : "400" or http.response.status_code : "200" - or http.response.status_code : "300"`; - const expectedOutput = - 'http.response.status_code : "400" or http.response.status_code : "300"'; - const result = removeFilterFromQueryString(currentQueryString, fieldName, fieldValue); - expect(result).to.be(expectedOutput); - }); - }); - - describe('getQueryPattern', () => { - it('creates a regular expression pattern for given fieldName/fieldValue', () => { - // The source property returns a String containing the source text of the regexp object - // and it doesn't contain the two forward slashes on both sides and any flags. - const expectedOutput = /(http\.response\.status_code)\s?:\s?(")?(200)(")?/i.source; - const result = getQueryPattern(fieldName, fieldValue).source; - expect(result).to.be(expectedOutput); - }); - - it('creates a regular expression pattern for given fieldName/fieldValue containing special characters', () => { - // The source property returns a String containing the source text of the regexp object - // and it doesn't contain the two forward slashes on both sides and any flags. - const expectedOutput = /(normal\(brackets\)name)\s?:\s?(")?(<>:;\[\}\))(")?/i.source; - const result = getQueryPattern(speciaCharFieldName, speciaCharFieldValue).source; - expect(result).to.be(expectedOutput); - }); - }); - - describe('escapeRegExp', () => { - it('escapes regex special characters for given fieldName/fieldValue', () => { - // The source property returns a String containing the source text of the regexp object - // and it doesn't contain the two forward slashes on both sides and any flags. - const expectedFieldName = 'normal\\(brackets\\)name'; - const expectedFieldValue = '<>:;\\[\\}\\)'; - const resultFieldName = escapeRegExp(speciaCharFieldName); - const resultFieldValue = escapeRegExp(speciaCharFieldValue); - - expect(resultFieldName).to.be(expectedFieldName); - expect(resultFieldValue).to.be(expectedFieldValue); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/__snapshots__/click_outside.test.js.snap b/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/__snapshots__/click_outside.test.js.snap deleted file mode 100644 index eb3e5e6005dee..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/__snapshots__/click_outside.test.js.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ClickOutside snapshot 1`] = `
`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.js deleted file mode 100644 index 02d6750dca965..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/click_outside.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -export class ClickOutside extends Component { - componentDidMount() { - document.addEventListener('mousedown', this.onClick); - } - - componentWillUnmount() { - document.removeEventListener('mousedown', this.onClick); - } - - setNodeRef = node => { - this.nodeRef = node; - }; - - onClick = event => { - if (this.nodeRef && !this.nodeRef.contains(event.target)) { - this.props.onClickOutside(); - } - }; - - render() { - const { style, children } = this.props; - - return ( -
- {children} -
- ); - } -} - -ClickOutside.propTypes = { - onClickOutside: PropTypes.func.isRequired, -}; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/index.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/index.js deleted file mode 100644 index 884481f9848dd..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/click_outside/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { ClickOutside } from './click_outside'; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap b/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap deleted file mode 100644 index f3c825a66ee2f..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap +++ /dev/null @@ -1,133 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`FilterBar snapshot suggestions not shown 1`] = ` - -
- -
- Test description for fieldValueOne

", - "end": 1, - "start": 0, - "text": "fieldValueOne", - "type": "field", - }, - Object { - "description": "

Test description for fieldValueTwo

", - "end": 1, - "start": 0, - "text": "fieldValueTwo", - "type": "field", - }, - ] - } - /> -
-`; - -exports[`FilterBar snapshot suggestions shown 1`] = ` - -
- -
- Test description for fieldValueOne

", - "end": 1, - "start": 0, - "text": "fieldValueOne", - "type": "field", - }, - Object { - "description": "

Test description for fieldValueTwo

", - "end": 1, - "start": 0, - "text": "fieldValueTwo", - "type": "field", - }, - ] - } - /> -
-`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.js deleted file mode 100644 index 0c1796a6e01ca..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { Suggestions } from '../suggestions'; -import { ClickOutside } from '../click_outside'; -import { EuiFieldSearch, EuiProgress, keyCodes } from '@elastic/eui'; - -export class FilterBar extends Component { - state = { - isSuggestionsVisible: false, - index: null, - value: '', - inputIsPristine: true, - }; - - static getDerivedStateFromProps(props, state) { - if (state.inputIsPristine && props.initialValue) { - return { - value: props.initialValue, - }; - } - - return null; - } - - // Set value to filter created via filter table - componentDidUpdate(oldProps) { - const newProps = this.props; - if (oldProps.valueExternal !== newProps.valueExternal) { - this.setState({ value: newProps.valueExternal, index: null }); - } - } - - incrementIndex = currentIndex => { - let nextIndex = currentIndex + 1; - if (currentIndex === null || nextIndex >= this.props.suggestions.length) { - nextIndex = 0; - } - this.setState({ index: nextIndex }); - }; - - decrementIndex = currentIndex => { - let previousIndex = currentIndex - 1; - if (previousIndex < 0) { - previousIndex = null; - } - this.setState({ index: previousIndex }); - }; - - onKeyUp = event => { - const { selectionStart } = event.target; - const { value } = this.state; - switch (event.keyCode) { - case keyCodes.LEFT: - case keyCodes.RIGHT: - this.setState({ isSuggestionsVisible: true }); - this.props.onChange(value, selectionStart); - break; - } - }; - - onKeyDown = event => { - const { isSuggestionsVisible, index, value } = this.state; - switch (event.keyCode) { - case keyCodes.DOWN: - event.preventDefault(); - if (isSuggestionsVisible) { - this.incrementIndex(index); - } else { - this.setState({ isSuggestionsVisible: true, index: 0 }); - } - break; - case keyCodes.UP: - event.preventDefault(); - if (isSuggestionsVisible) { - this.decrementIndex(index); - } - break; - case keyCodes.ENTER: - event.preventDefault(); - if (isSuggestionsVisible && this.props.suggestions[index]) { - this.selectSuggestion(this.props.suggestions[index]); - } else { - this.setState({ isSuggestionsVisible: false }); - this.props.onSubmit(value); - } - break; - case keyCodes.ESC: - event.preventDefault(); - this.setState({ isSuggestionsVisible: false }); - break; - case keyCodes.TAB: - this.setState({ isSuggestionsVisible: false }); - break; - } - }; - - selectSuggestion = suggestion => { - const nextInputValue = - this.state.value.substr(0, suggestion.start) + - suggestion.text + - this.state.value.substr(suggestion.end); - - this.setState({ value: nextInputValue, index: null }); - this.props.onChange(nextInputValue, nextInputValue.length); - }; - - onClickOutside = () => { - this.setState({ isSuggestionsVisible: false }); - }; - - onChangeInputValue = event => { - const { value, selectionStart } = event.target; - const hasValue = Boolean(value.trim()); - this.setState({ - value, - inputIsPristine: false, - isSuggestionsVisible: hasValue, - index: null, - }); - - if (!hasValue) { - this.props.onSubmit(value); - } - this.props.onChange(value, selectionStart); - }; - - onClickInput = event => { - const { selectionStart } = event.target; - this.props.onChange(this.state.value, selectionStart); - }; - - onClickSuggestion = suggestion => { - this.selectSuggestion(suggestion); - this.inputRef.focus(); - }; - - onMouseEnterSuggestion = index => { - this.setState({ index }); - }; - - onSubmit = () => { - this.props.onSubmit(this.state.value); - this.setState({ isSuggestionsVisible: false }); - }; - - render() { - const { disabled } = this.props; - const { value } = this.state; - - return ( - -
- { - if (node) { - this.inputRef = node; - } - }} - disabled={disabled} - value={value} - onKeyDown={this.onKeyDown} - onKeyUp={this.onKeyUp} - onChange={this.onChangeInputValue} - onClick={this.onClickInput} - autoComplete="off" - spellCheck={false} - data-test-subj={this.props.testSubj} - /> - - {this.props.isLoading && ( - - )} -
- - -
- ); - } -} - -FilterBar.propTypes = { - initialValue: PropTypes.string, - isLoading: PropTypes.bool, - disabled: PropTypes.bool, - onChange: PropTypes.func.isRequired, - placeholder: PropTypes.string, - onSubmit: PropTypes.func.isRequired, - valueExternal: PropTypes.string, - suggestions: PropTypes.array.isRequired, - testSubj: PropTypes.string, -}; - -FilterBar.defaultProps = { - isLoading: false, - disabled: false, - placeholder: 'tag : engineering OR tag : marketing', - suggestions: [], - testSubj: undefined, -}; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.test.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.test.js deleted file mode 100644 index 287803f9eb40a..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/filter_bar.test.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { keyCodes } from '@elastic/eui'; -import { FilterBar } from './filter_bar'; - -const defaultProps = { - disabled: false, - initialValue: '', - placeholder: 'Test placeholder', - isLoading: false, - onChange: () => {}, - onSubmit: () => {}, - suggestions: [ - { - description: '

Test description for fieldValueOne

', - end: 1, - start: 0, - text: 'fieldValueOne', - type: 'field', - }, - { - description: '

Test description for fieldValueTwo

', - end: 1, - start: 0, - text: 'fieldValueTwo', - type: 'field', - }, - ], -}; - -describe('FilterBar', () => { - test('snapshot suggestions not shown', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - test('snapshot suggestions shown', () => { - const wrapper = shallow(); - wrapper.setState({ isSuggestionsVisible: true }); - expect(wrapper).toMatchSnapshot(); - }); - - test('index updated in state when suggestion is navigated to via mouse', () => { - const wrapper = mount(); - wrapper.setState({ isSuggestionsVisible: true }); - - expect(wrapper.state('index')).toEqual(null); - - const firstSuggestion = wrapper.find('li').first(); - firstSuggestion.simulate('mouseenter'); - expect(wrapper.state('index')).toEqual(0); - }); - - test('index updated and suggestions set to visible when input added', () => { - const wrapper = shallow(); - // default values - expect(wrapper.state('index')).toEqual(null); - expect(wrapper.state('isSuggestionsVisible')).toBe(false); - - const searchBar = wrapper.find('EuiFieldSearch'); - searchBar.simulate('keydown', { preventDefault: () => {}, keyCode: keyCodes.DOWN }); - wrapper.update(); - // updated values - expect(wrapper.state('index')).toEqual(0); - expect(wrapper.state('isSuggestionsVisible')).toBe(true); - }); - - test('index updated in state when suggestion is navigated to via keyboard', () => { - const wrapper = shallow(); - wrapper.setState({ isSuggestionsVisible: true, value: 'f', index: 0 }); - const searchBar = wrapper.find('EuiFieldSearch'); - searchBar.simulate('keydown', { preventDefault: () => {}, keyCode: keyCodes.DOWN }); - wrapper.update(); - - expect(wrapper.state('index')).toEqual(1); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/index.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/index.js deleted file mode 100644 index e8153037e0c10..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/filter_bar/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { FilterBar } from './filter_bar'; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/index.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/index.js deleted file mode 100644 index d229943f6afe7..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { KqlFilterBar } from './kql_filter_bar'; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.js deleted file mode 100644 index 0f3c6d25fe641..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.js +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { uniqueId } from 'lodash'; -import { FilterBar } from './filter_bar'; -import { EuiCallOut, EuiLink, EuiText } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { getSuggestions, getKqlQueryValues } from './utils'; -import { getDocLinks } from '../../util/dependency_cache'; - -function getErrorWithLink(errorMessage) { - const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = getDocLinks(); - return ( - - {`${errorMessage} Input must be valid `} - - {'Kibana Query Language'} - - {' (KQL) syntax.'} - - ); -} - -export class KqlFilterBar extends Component { - state = { - error: null, - suggestions: [], - isLoadingSuggestions: false, - isLoadingIndexPattern: true, - }; - - onChange = async (inputValue, selectionStart) => { - const { indexPattern } = this.props; - - this.setState({ error: null, suggestions: [], isLoadingSuggestions: true }); - - const currentRequest = uniqueId(); - this.currentRequest = currentRequest; - const boolFilter = []; - - try { - const suggestions = - (await getSuggestions(inputValue, selectionStart, indexPattern, boolFilter)) || []; - - if (currentRequest !== this.currentRequest) { - return; - } - - this.setState({ suggestions, isLoadingSuggestions: false }); - } catch (e) { - console.error('Error while fetching suggestions', e); - const errorMessage = i18n.translate('xpack.ml.explorer.fetchingSuggestionsErrorMessage', { - defaultMessage: 'Error while fetching suggestions', - }); - this.setState({ isLoadingSuggestions: false, error: e.message ? e.message : errorMessage }); - } - }; - - onSubmit = inputValue => { - const { indexPattern } = this.props; - const { onSubmit } = this.props; - - try { - // returns object with properties: { influencersFilterQuery, filteredFields, queryString, isAndOperator } - const kqlQueryValues = getKqlQueryValues(inputValue, indexPattern); - onSubmit(kqlQueryValues); - } catch (e) { - console.log('Invalid kuery syntax', e); // eslint-disable-line no-console - const errorWithLink = getErrorWithLink(e.message); - const errorMessage = i18n.translate('xpack.ml.explorer.invalidKuerySyntaxErrorMessage', { - defaultMessage: 'Invalid kuery syntax', - }); - this.setState({ error: e.message ? errorWithLink : errorMessage }); - } - }; - - render() { - const { error } = this.state; - const { initialValue, placeholder, valueExternal, testSubj } = this.props; - - return ( - - - {error && {error}} - - ); - } -} - -KqlFilterBar.propTypes = { - indexPattern: PropTypes.object.isRequired, - initialValue: PropTypes.string, - onSubmit: PropTypes.func.isRequired, - placeholder: PropTypes.string, - valueExternal: PropTypes.string, - testSubj: PropTypes.string, -}; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.test.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.test.js deleted file mode 100644 index 610d924651406..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/kql_filter_bar.test.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import { KqlFilterBar } from './kql_filter_bar'; - -const defaultProps = { - indexPattern: { - title: '.ml-anomalies-*', - fields: [ - { - name: 'nginx.access.geoip.country_iso_code', - type: 'string', - aggregatable: true, - searchable: true, - }, - { - name: 'nginx.access.url', - type: 'string', - aggregatable: true, - searchable: true, - }, - ], - }, - initialValue: '', - onSubmit: () => {}, - placeholder: undefined, -}; - -jest.mock('../../util/dependency_cache', () => ({ - getAutocomplete: () => ({ - getQuerySuggestions: () => {}, - }), -})); - -describe('KqlFilterBar', () => { - test('snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - test('error message callout when error is present', () => { - const wrapper = shallow(); - wrapper.setState({ error: 'Invalid syntax' }); - wrapper.update(); - const callout = wrapper.find('EuiCallOut'); - - expect(callout.contains('Invalid syntax')).toBe(true); - }); - - test('suggestions loading when typing into search bar', () => { - const wrapper = shallow(); - expect(wrapper.state('isLoadingSuggestions')).toBe(false); - // Simulate typing in by triggering change with inputValue and selectionStart - const filterBar = wrapper.find('FilterBar'); - filterBar.simulate('change', 'n', 1); - expect(wrapper.state('isLoadingSuggestions')).toBe(true); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap deleted file mode 100644 index 4eb236f50be05..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/__snapshots__/suggestion.test.js.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Suggestion snapshot 1`] = ` - - - - - - fieldValue - - - <p>Test description for fieldValue</p> - - -`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/index.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/index.js deleted file mode 100644 index 98aedf068a987..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { Suggestion } from './suggestion'; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.js deleted file mode 100644 index 121082a776c80..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import PropTypes from 'prop-types'; -import styled from 'styled-components'; -import { EuiIcon } from '@elastic/eui'; -import { tint } from 'polished'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; - -function getIconColor(type) { - switch (type) { - case 'field': - return theme.euiColorVis7; - case 'value': - return theme.euiColorVis0; - case 'operator': - return theme.euiColorVis1; - case 'conjunction': - return theme.euiColorVis3; - case 'recentSearch': - return theme.euiColorMediumShade; - } -} - -const Description = styled.div` - color: ${theme.euiColorDarkShade}; - - p { - display: inline; - - span { - font-family: ${theme.euiFontFamily}; - color: ${theme.euiColorFullShade}; - padding: 0 ${theme.euiSizeXS}; - display: inline-block; - } - } -`; - -const ListItem = styled.li` - font-size: ${theme.euiFontSizeXS}; - height: ${theme.euiSizeXL}; - align-items: center; - display: flex; - background: ${props => (props.selected ? theme.euiColorLightestShade : 'initial')}; - cursor: pointer; - border-radius: ${theme.euiSizeXS}; - - ${Description} { - p span { - background: ${props => - props.selected ? theme.euiColorEmptyShade : theme.euiColorLightestShade}; - } - } -`; - -const Icon = styled.div` - flex: 0 0 ${theme.euiSizeXL}; - background: ${props => tint(0.1, getIconColor(props.type))}; - color: ${props => getIconColor(props.type)}; - width: 100%; - height: 100%; - text-align: center; - line-height: ${theme.euiSizeXL}; -`; - -const TextValue = styled.div` - flex: 0 0 ${theme.euiSize * 16}px; - color: ${theme.euiColorDarkestShade}; - padding: 0 ${theme.euiSizeS}; -`; - -function getEuiIconType(type) { - switch (type) { - case 'field': - return 'kqlField'; - case 'value': - return 'kqlValue'; - case 'recentSearch': - return 'search'; - case 'conjunction': - return 'kqlSelector'; - case 'operator': - return 'kqlOperand'; - default: - throw new Error('Unknown type', type); - } -} - -export const Suggestion = props => { - return ( - props.onClick(props.suggestion)} - onMouseEnter={props.onMouseEnter} - > - - - - {props.suggestion.text} - {props.suggestion.description} - - ); -}; - -Suggestion.propTypes = { - onClick: PropTypes.func.isRequired, - onMouseEnter: PropTypes.func.isRequired, - selected: PropTypes.bool, - suggestion: PropTypes.object.isRequired, - innerRef: PropTypes.func.isRequired, -}; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.test.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.test.js deleted file mode 100644 index d60f2004db445..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestion/suggestion.test.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import { Suggestion } from './suggestion'; - -const defaultProps = { - innerRef: () => {}, - onClick: () => {}, - onMouseEnter: () => {}, - selected: true, - suggestion: { - description: '

Test description for fieldValue

', - end: 1, - start: 0, - text: 'fieldValue', - type: 'field', - }, -}; - -describe('Suggestion', () => { - test('snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap deleted file mode 100644 index 869e321d4a7af..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/__snapshots__/suggestions.test.js.snap +++ /dev/null @@ -1,40 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Suggestions snapshot 1`] = ` - - Test description for fieldValueOne

", - "end": 1, - "start": 0, - "text": "fieldValueOne", - "type": "field", - } - } - /> - Test description for fieldValueTwo

", - "end": 1, - "start": 0, - "text": "fieldValueTwo", - "type": "field", - } - } - /> -
-`; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/index.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/index.js deleted file mode 100644 index 70fb46e06bfa0..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { Suggestions } from './suggestions'; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.js deleted file mode 100644 index 94960e1fcc865..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import styled from 'styled-components'; -import { Suggestion } from '../suggestion'; -import { rgba } from 'polished'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; - -const List = styled.ul` - width: 100%; - border: 1px solid ${theme.euiColorLightShade}; - border-radius: ${theme.euiSizeXS}; - box-shadow: 0px ${theme.euiSizeXS} ${theme.euiSizeXL} ${rgba(theme.euiTextColor, 0.1)}; - position: absolute; - background: #fff; - z-index: 10; - left: 0; - max-height: ${theme.euiSize * 20}px; - overflow: scroll; -`; - -export class Suggestions extends Component { - childNodes = []; - - scrollIntoView = () => { - const parent = this.parentNode; - const child = this.childNodes[this.props.index]; - - if (this.props.index == null || !parent || !child) { - return; - } - - const scrollTop = Math.max( - Math.min(parent.scrollTop, child.offsetTop), - child.offsetTop + child.offsetHeight - parent.offsetHeight - ); - - parent.scrollTop = scrollTop; - }; - - componentDidUpdate(prevProps) { - if (prevProps.index !== this.props.index) { - this.scrollIntoView(); - } - } - - render() { - if (!this.props.show || this.props.suggestions.length === 0) { - return null; - } - - const suggestions = this.props.suggestions.map((suggestion, index) => { - const key = `${suggestion}_${index}`; - return ( - (this.childNodes[index] = node)} - selected={index === this.props.index} - suggestion={suggestion} - onClick={this.props.onClick} - onMouseEnter={() => this.props.onMouseEnter(index)} - key={key} - /> - ); - }); - - return (this.parentNode = node)}>{suggestions}; - } -} - -Suggestions.propTypes = { - index: PropTypes.number, - onClick: PropTypes.func.isRequired, - onMouseEnter: PropTypes.func.isRequired, - show: PropTypes.bool, - suggestions: PropTypes.array.isRequired, -}; diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.test.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.test.js deleted file mode 100644 index 666bfa4cfa1fa..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/suggestions/suggestions.test.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow, mount } from 'enzyme'; -import { Suggestions } from './suggestions'; - -const defaultProps = { - index: 0, - onClick: () => {}, - onMouseEnter: () => {}, - show: true, - suggestions: [ - { - description: '

Test description for fieldValueOne

', - end: 1, - start: 0, - text: 'fieldValueOne', - type: 'field', - }, - { - description: '

Test description for fieldValueTwo

', - end: 1, - start: 0, - text: 'fieldValueTwo', - type: 'field', - }, - ], -}; - -describe('Suggestions', () => { - test('snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); - - test('is null when show is false', () => { - const noShowProps = { ...defaultProps, show: false }; - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toBeTruthy(); - }); - - test('is null when no suggestions are available', () => { - const noSuggestions = { ...defaultProps, suggestions: [] }; - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toBeTruthy(); - }); - - test('creates suggestion list item for each suggestion passed in via props', () => { - const wrapper = mount(); - const suggestions = wrapper.find('li'); - expect(suggestions.length).toEqual(2); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/kql_filter_bar/utils.js b/x-pack/plugins/ml/public/application/components/kql_filter_bar/utils.js deleted file mode 100644 index d632f4079e5b9..0000000000000 --- a/x-pack/plugins/ml/public/application/components/kql_filter_bar/utils.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { esKuery } from '../../../../../../../src/plugins/data/public'; -import { getAutocomplete } from '../../util/dependency_cache'; - -export function getSuggestions(query, selectionStart, indexPattern, boolFilter) { - const autocomplete = getAutocomplete(); - return autocomplete.getQuerySuggestions({ - language: 'kuery', - indexPatterns: [indexPattern], - boolFilter, - query, - selectionStart, - selectionEnd: selectionStart, - }); -} - -function convertKueryToEsQuery(kuery, indexPattern) { - const ast = esKuery.fromKueryExpression(kuery); - return esKuery.toElasticsearchQuery(ast, indexPattern); -} -// Recommended by MDN for escaping user input to be treated as a literal string within a regular expression -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions -export function escapeRegExp(string) { - return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string -} - -export function escapeParens(string) { - return string.replace(/[()]/g, '\\$&'); -} - -export function escapeDoubleQuotes(string) { - return string.replace(/\"/g, '\\$&'); -} - -export function getKqlQueryValues(inputValue, indexPattern) { - const ast = esKuery.fromKueryExpression(inputValue); - const isAndOperator = ast.function === 'and'; - const query = convertKueryToEsQuery(inputValue, indexPattern); - const filteredFields = []; - - if (!query) { - return; - } - - // if ast.type == 'function' then layout of ast.arguments: - // [{ arguments: [ { type: 'literal', value: 'AAL' } ] },{ arguments: [ { type: 'literal', value: 'AAL' } ] }] - if (ast && Array.isArray(ast.arguments)) { - ast.arguments.forEach(arg => { - if (arg.arguments !== undefined) { - arg.arguments.forEach(nestedArg => { - if (typeof nestedArg.value === 'string') { - filteredFields.push(nestedArg.value); - } - }); - } else if (typeof arg.value === 'string') { - filteredFields.push(arg.value); - } - }); - } - - return { - filterQuery: query, - filteredFields, - queryString: inputValue, - isAndOperator, - tableQueryString: inputValue, - }; -} - -export function getQueryPattern(fieldName, fieldValue) { - const sanitizedFieldName = escapeRegExp(fieldName); - const sanitizedFieldValue = escapeRegExp(fieldValue); - - return new RegExp(`(${sanitizedFieldName})\\s?:\\s?(")?(${sanitizedFieldValue})(")?`, 'i'); -} - -export function removeFilterFromQueryString(currentQueryString, fieldName, fieldValue) { - let newQueryString = ''; - // Remove the passed in fieldName and value from the existing filter - const queryPattern = getQueryPattern(fieldName, fieldValue); - newQueryString = currentQueryString.replace(queryPattern, ''); - // match 'and' or 'or' at the start/end of the string - const endPattern = /\s(and|or)\s*$/gi; - const startPattern = /^\s*(and|or)\s/gi; - // If string has a double operator (e.g. tag:thing or or tag:other) remove and replace with the first occurring operator - const invalidOperatorPattern = /\s+(and|or)\s+(and|or)\s+/gi; - newQueryString = newQueryString.replace(invalidOperatorPattern, ' $1 '); - // If string starts/ends with 'and' or 'or' remove that as that is illegal kuery syntax - newQueryString = newQueryString.replace(endPattern, ''); - newQueryString = newQueryString.replace(startPattern, ''); - - return newQueryString; -} diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index d2615e8174dd1..475e44af3669c 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -11,10 +11,12 @@ import { KibanaReactContextValue, } from '../../../../../../../src/plugins/kibana_react/public'; import { SecurityPluginSetup } from '../../../../../security/public'; +import { LicenseManagementUIPluginSetup } from '../../../../../license_management/public'; interface StartPlugins { data: DataPublicPluginStart; security: SecurityPluginSetup; + licenseManagement?: LicenseManagementUIPluginSetup; } export type StartServices = CoreStart & StartPlugins; // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss index 962d3f4c7bd54..83314a74331fd 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss @@ -1,4 +1,3 @@ -@import 'pages/analytics_exploration/components/exploration/index'; @import 'pages/analytics_exploration/components/regression_exploration/index'; @import 'pages/analytics_exploration/components/classification_exploration/index'; @import 'pages/analytics_management/components/analytics_list/index'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 9c239df357163..95a8dfbb308f8 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -56,6 +56,8 @@ export interface LoadExploreDataArg { direction: SortDirection; searchQuery: SavedSearchQuery; requiresKeyword?: boolean; + pageIndex?: number; + pageSize?: number; } export const SEARCH_SIZE = 1000; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/data_grid.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/data_grid.ts new file mode 100644 index 0000000000000..2b6d733837562 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/data_grid.ts @@ -0,0 +1,23 @@ +/* + * 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 { EuiDataGridStyle } from '@elastic/eui'; + +export const euiDataGridStyle: EuiDataGridStyle = { + border: 'all', + fontSize: 's', + cellPadding: 's', + stripes: false, + rowHover: 'none', + header: 'shade', +}; + +export const euiDataGridToolbarSettings = { + showColumnSelector: true, + showStyleSelector: false, + showSortSelector: true, + showFullScreenSelector: false, +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts index e8ebf2b1cfd56..fb1d4edb37af8 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts @@ -362,18 +362,16 @@ export const getDefaultSelectableFields = (docs: EsDoc[], resultsField: string): } const newDocFields = getFlattenedFields(docs[0]._source, resultsField); - return newDocFields - .filter(k => { - if (k === `${resultsField}.outlier_score`) { - return true; - } - if (k.split('.')[0] === resultsField) { - return false; - } + return newDocFields.filter(k => { + if (k === `${resultsField}.outlier_score`) { + return true; + } + if (k.split('.')[0] === resultsField) { + return false; + } - return docs.some(row => row._source[k] !== null); - }) - .slice(0, MAX_COLUMNS); + return docs.some(row => row._source[k] !== null); + }); }; export const toggleSelectedFieldSimple = ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts index 62ef73670d8f5..7b76faf613ce8 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/index.ts @@ -46,3 +46,5 @@ export { EsFieldName, MAX_COLUMNS, } from './fields'; + +export { euiDataGridStyle, euiDataGridToolbarSettings } from './data_grid'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/column_data.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/column_data.tsx index baf7fd32b0f60..14493ab024f34 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/column_data.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/column_data.tsx @@ -4,79 +4,115 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { ConfusionMatrix, PredictedClass } from '../../../../common/analytics'; +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonEmpty, + EuiButtonIcon, + EuiDataGridControlColumn, + EuiPopover, + EuiText, +} from '@elastic/eui'; +import { ConfusionMatrix } from '../../../../common/analytics'; interface ColumnData { actual_class: string; actual_class_doc_count: number; - predicted_class?: string; - count?: number; - error_count?: number; + [key: string]: string | number; } export const ACTUAL_CLASS_ID = 'actual_class'; +export const OTHER_CLASS_ID = 'other'; +export const MAX_COLUMNS = 6; export function getColumnData(confusionMatrixData: ConfusionMatrix[]) { const colData: Partial = []; + const columns: Array<{ id: string; display?: any }> = [ + { + id: ACTUAL_CLASS_ID, + display: , + }, + ]; - confusionMatrixData.forEach((classData: any) => { - const correctlyPredictedClass = classData.predicted_classes.find( - (pc: PredictedClass) => pc.predicted_class === classData.actual_class - ); - const incorrectlyPredictedClass = classData.predicted_classes.find( - (pc: PredictedClass) => pc.predicted_class !== classData.actual_class - ); + let showOther = false; - let accuracy; - if (correctlyPredictedClass !== undefined) { - accuracy = correctlyPredictedClass.count / classData.actual_class_doc_count; - // round to 2 decimal places without converting to string; - accuracy = Math.round(accuracy * 100) / 100; - } + confusionMatrixData.forEach(classData => { + const otherCount = classData.other_predicted_class_doc_count; - let error; - if (incorrectlyPredictedClass !== undefined) { - error = incorrectlyPredictedClass.count / classData.actual_class_doc_count; - error = Math.round(error * 100) / 100; + if (otherCount > 0) { + showOther = true; } - let col: any = { + const col: any = { actual_class: classData.actual_class, actual_class_doc_count: classData.actual_class_doc_count, + other: otherCount, }; - if (correctlyPredictedClass !== undefined) { - col = { - ...col, - predicted_class: correctlyPredictedClass.predicted_class, - [correctlyPredictedClass.predicted_class]: accuracy, - count: correctlyPredictedClass.count, - accuracy, - }; - } + const predictedClasses = classData.predicted_classes || []; - if (incorrectlyPredictedClass !== undefined) { - col = { - ...col, - [incorrectlyPredictedClass.predicted_class]: error, - error_count: incorrectlyPredictedClass.count, - }; + columns.push({ id: classData.actual_class }); + + for (let i = 0; i < predictedClasses.length; i++) { + const predictedClass = predictedClasses[i].predicted_class; + const predictedClassCount = predictedClasses[i].count; + col[predictedClass] = predictedClassCount; } colData.push(col); }); - const columns: any = [ + if (showOther) { + columns.push({ id: OTHER_CLASS_ID }); + } + + return { columns, columnData: colData }; +} + +export function getTrailingControlColumns( + numColumns: number, + setShowFullColumns: any +): EuiDataGridControlColumn[] { + return [ { - id: ACTUAL_CLASS_ID, - display: , + id: 'actions', + width: 60, + headerCellRender: () => {`${numColumns} more`}, + rowCellRender: function RowCellRender() { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + return ( + setIsPopoverOpen(!isPopoverOpen)} + /> + } + closePopover={() => setIsPopoverOpen(false)} + ownFocus={true} + > + setShowFullColumns(true)}> + + {i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.showAllColumns', + { + defaultMessage: 'Show all columns', + } + )} + + + + ); + }, }, ]; - - colData.forEach((data: any) => { - columns.push({ id: data.predicted_class }); - }); - - return { columns, columnData: colData }; } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx index 7bf55f4ecf392..1c5563bdb4f83 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx @@ -39,7 +39,12 @@ import { ANALYSIS_CONFIG_TYPE, } from '../../../../common/analytics'; import { LoadingPanel } from '../loading_panel'; -import { getColumnData, ACTUAL_CLASS_ID } from './column_data'; +import { + getColumnData, + ACTUAL_CLASS_ID, + MAX_COLUMNS, + getTrailingControlColumns, +} from './column_data'; const defaultPanelWidth = 500; @@ -57,6 +62,7 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) const [confusionMatrixData, setConfusionMatrixData] = useState([]); const [columns, setColumns] = useState([]); const [columnsData, setColumnsData] = useState([]); + const [showFullColumns, setShowFullColumns] = useState(false); const [popoverContents, setPopoverContents] = useState([]); const [docsCount, setDocsCount] = useState(null); const [error, setError] = useState(null); @@ -168,8 +174,9 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) const colId = children?.props?.columnId; const gridItem = columnData[rowIndex]; - if (gridItem !== undefined) { - const count = colId === gridItem.actual_class ? gridItem.count : gridItem.error_count; + if (gridItem !== undefined && colId !== ACTUAL_CLASS_ID) { + // @ts-ignore + const count = gridItem[colId]; return `${count} / ${gridItem.actual_class_doc_count} * 100 = ${cellContentsElement.textContent}`; } @@ -203,19 +210,26 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) setCellProps: any; }) => { const cellValue = columnsData[rowIndex][columnId]; + const actualCount = columnsData[rowIndex] && columnsData[rowIndex].actual_class_doc_count; + let accuracy: number | string = '0%'; + + if (columnId !== ACTUAL_CLASS_ID && actualCount) { + accuracy = cellValue / actualCount; + // round to 2 decimal places without converting to string; + accuracy = Math.round(accuracy * 100) / 100; + accuracy = `${Math.round(accuracy * 100)}%`; + } // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (columnId !== ACTUAL_CLASS_ID) { setCellProps({ style: { - backgroundColor: `rgba(0, 179, 164, ${cellValue})`, + backgroundColor: `rgba(0, 179, 164, ${accuracy})`, }, }); } }, [rowIndex, columnId, setCellProps]); - return ( - {typeof cellValue === 'number' ? `${Math.round(cellValue * 100)}%` : cellValue} - ); + return {columnId === ACTUAL_CLASS_ID ? cellValue : accuracy}; }; if (isLoading === true) { @@ -224,6 +238,15 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; + const showTrailingColumns = columnsData.length > MAX_COLUMNS; + const extraColumns = columnsData.length - MAX_COLUMNS; + const shownColumns = + showTrailingColumns === true && showFullColumns === false + ? columns.slice(0, MAX_COLUMNS + 1) + : columns; + const rowCount = + showTrailingColumns === true && showFullColumns === false ? MAX_COLUMNS : columnsData.length; + return ( = ({ jobConfig, jobStatus, searchQuery }) )} {/* BEGIN TABLE ELEMENTS */} - + = ({ jobConfig, jobStatus, searchQuery }) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx index 84abbda71643c..20d126f4ac6ca 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx @@ -44,6 +44,7 @@ import { BASIC_NUMERICAL_TYPES, EXTENDED_NUMERICAL_TYPES, isKeywordAndTextType, + sortRegressionResultsFields, } from '../../../../common/fields'; import { @@ -134,79 +135,81 @@ export const ResultsTable: FC = React.memo( tableItems, } = useExploreData(jobConfig, selectedFields, setSelectedFields, setDocFields, setDepVarType); - const columns: Array> = selectedFields.map(field => { - const { type } = field; - const isNumber = - type !== undefined && - (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type)); - - const column: ColumnType = { - field: field.name, - name: field.name, - sortable: true, - truncateText: true, - }; - - const render = (d: any, fullItem: EsDoc) => { - if (Array.isArray(d) && d.every(item => typeof item === 'string')) { - // If the cells data is an array of strings, return as a comma separated list. - // The list will get limited to 5 items with `…` at the end if there's more in the original array. - return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; - } else if (Array.isArray(d)) { - // If the cells data is an array of e.g. objects, display a 'array' badge with a - // tooltip that explains that this type of field is not supported in this table. - return ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent', + const columns: Array> = selectedFields + .sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig)) + .map(field => { + const { type } = field; + const isNumber = + type !== undefined && + (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type)); + + const column: ColumnType = { + field: field.name, + name: field.name, + sortable: true, + truncateText: true, + }; + + const render = (d: any, fullItem: EsDoc) => { + if (Array.isArray(d) && d.every(item => typeof item === 'string')) { + // If the cells data is an array of strings, return as a comma separated list. + // The list will get limited to 5 items with `…` at the end if there's more in the original array. + return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; + } else if (Array.isArray(d)) { + // If the cells data is an array of e.g. objects, display a 'array' badge with a + // tooltip that explains that this type of field is not supported in this table. + return ( + - - ); - } - - return d; - }; + > + + {i18n.translate( + 'xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent', + { + defaultMessage: 'array', + } + )} + + + ); + } - if (isNumber) { - column.dataType = 'number'; - column.render = render; - } else if (typeof type !== 'undefined') { - switch (type) { - case ES_FIELD_TYPES.BOOLEAN: - column.dataType = ES_FIELD_TYPES.BOOLEAN; - break; - case ES_FIELD_TYPES.DATE: - column.align = 'right'; - column.render = (d: any) => { - if (d !== undefined) { - return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); - } - return d; - }; - break; - default: - column.render = render; - break; + return d; + }; + + if (isNumber) { + column.dataType = 'number'; + column.render = render; + } else if (typeof type !== 'undefined') { + switch (type) { + case ES_FIELD_TYPES.BOOLEAN: + column.dataType = ES_FIELD_TYPES.BOOLEAN; + break; + case ES_FIELD_TYPES.DATE: + column.align = 'right'; + column.render = (d: any) => { + if (d !== undefined) { + return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); + } + return d; + }; + break; + default: + column.render = render; + break; + } + } else { + column.render = render; } - } else { - column.render = render; - } - return column; - }); + return column; + }); const docFieldsCount = docFields.length; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_exploration.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_exploration.scss deleted file mode 100644 index b5b90347cf0b8..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_exploration.scss +++ /dev/null @@ -1,19 +0,0 @@ -.mlDataFrameAnalyticsExploration { - /* Overwrite to give table cells a more grid-like appearance */ - .euiTableHeaderCell { - padding: 0 4px; - } - .euiTableCellContent { - padding: 0; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - line-height: 2; - } -} - -.mlColoredTableCell { - width: 100%; - height: 100%; - padding: 0 4px; -} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_index.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_index.scss deleted file mode 100644 index ca27eec1d5a4d..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'exploration'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx deleted file mode 100644 index 70c29051c8215..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { FC, useEffect, useState } from 'react'; -import moment from 'moment-timezone'; - -import { i18n } from '@kbn/i18n'; - -import { - EuiBadge, - EuiButtonIcon, - EuiCallOut, - EuiCheckbox, - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiPopover, - EuiPopoverTitle, - EuiProgress, - EuiSpacer, - EuiText, - EuiTitle, - EuiToolTip, - Query, -} from '@elastic/eui'; - -import { - useColorRange, - ColorRangeLegend, - COLOR_RANGE, - COLOR_RANGE_SCALE, -} from '../../../../../components/color_range_legend'; -import { - ColumnType, - mlInMemoryTableBasicFactory, - OnTableChangeArg, - SortingPropType, - SORT_DIRECTION, -} from '../../../../../components/ml_in_memory_table'; - -import { formatHumanReadableDateTimeSeconds } from '../../../../../util/date_utils'; -import { ml } from '../../../../../services/ml_api_service'; - -import { - sortColumns, - toggleSelectedFieldSimple, - DataFrameAnalyticsConfig, - EsFieldName, - EsDoc, - MAX_COLUMNS, - INDEX_STATUS, - SEARCH_SIZE, - defaultSearchQuery, -} from '../../../../common'; -import { isKeywordAndTextType } from '../../../../common/fields'; - -import { getOutlierScoreFieldName } from './common'; -import { useExploreData, TableItem } from './use_explore_data'; -import { - DATA_FRAME_TASK_STATE, - Query as QueryType, -} from '../../../analytics_management/components/analytics_list/common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; -import { SavedSearchQuery } from '../../../../../contexts/ml'; -import { getIndexPatternIdFromName } from '../../../../../util/index_utils'; -import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/common/index_patterns'; -import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; -import { useMlContext } from '../../../../../contexts/ml'; - -const FEATURE_INFLUENCE = 'feature_influence'; - -const PAGE_SIZE_OPTIONS = [5, 10, 25, 50]; - -const ExplorationTitle: React.FC<{ jobId: string }> = ({ jobId }) => ( - - - {i18n.translate('xpack.ml.dataframe.analytics.exploration.jobIdTitle', { - defaultMessage: 'Outlier detection job ID {jobId}', - values: { jobId }, - })} - - -); - -interface Props { - jobId: string; - jobStatus: DATA_FRAME_TASK_STATE; -} - -const getFeatureCount = (jobConfig?: DataFrameAnalyticsConfig, tableItems: TableItem[] = []) => { - if (jobConfig === undefined || tableItems.length === 0) { - return 0; - } - - return Object.keys(tableItems[0]).filter(key => - key.includes(`${jobConfig.dest.results_field}.${FEATURE_INFLUENCE}.`) - ).length; -}; - -export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { - const [jobConfig, setJobConfig] = useState(undefined); - - const [pageIndex, setPageIndex] = useState(0); - const [pageSize, setPageSize] = useState(25); - - const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); - const [searchError, setSearchError] = useState(undefined); - const [searchString, setSearchString] = useState(undefined); - - const mlContext = useMlContext(); - - const initializeJobCapsService = async () => { - if (jobConfig !== undefined) { - const sourceIndex = jobConfig.source.index[0]; - const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; - const indexPattern: IIndexPattern = await mlContext.indexPatterns.get(indexPatternId); - if (indexPattern !== undefined) { - await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false); - } - } - }; - - useEffect(() => { - (async function() { - const analyticsConfigs = await ml.dataFrameAnalytics.getDataFrameAnalytics(jobId); - if ( - Array.isArray(analyticsConfigs.data_frame_analytics) && - analyticsConfigs.data_frame_analytics.length > 0 - ) { - setJobConfig(analyticsConfigs.data_frame_analytics[0]); - } - })(); - }, []); - - useEffect(() => { - initializeJobCapsService(); - }, [jobConfig && jobConfig.id]); - - const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]); - const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false); - - function toggleColumnsPopover() { - setColumnsPopoverVisible(!isColumnsPopoverVisible); - } - - function closeColumnsPopover() { - setColumnsPopoverVisible(false); - } - - function toggleColumn(column: EsFieldName) { - if (tableItems.length > 0 && jobConfig !== undefined) { - // spread to a new array otherwise the component wouldn't re-render - setSelectedFields([...toggleSelectedFieldSimple(selectedFields, column)]); - } - } - - const { - errorMessage, - loadExploreData, - sortField, - sortDirection, - status, - tableItems, - } = useExploreData(jobConfig, selectedFields, setSelectedFields); - - let docFields: EsFieldName[] = []; - let docFieldsCount = 0; - if (tableItems.length > 0) { - docFields = Object.keys(tableItems[0]); - docFields.sort(); - docFieldsCount = docFields.length; - } - - const columns: Array> = []; - - const cellBgColor = useColorRange( - COLOR_RANGE.BLUE, - COLOR_RANGE_SCALE.INFLUENCER, - getFeatureCount(jobConfig, tableItems) - ); - - if (jobConfig !== undefined && selectedFields.length > 0 && tableItems.length > 0) { - columns.push( - ...selectedFields.sort(sortColumns(tableItems[0], jobConfig.dest.results_field)).map(k => { - const column: ColumnType = { - field: k, - name: k, - sortable: true, - truncateText: true, - }; - - const render = (d: any, fullItem: EsDoc) => { - if (Array.isArray(d) && d.every(item => typeof item === 'string')) { - // If the cells data is an array of strings, return as a comma separated list. - // The list will get limited to 5 items with `…` at the end if there's more in the original array. - return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; - } else if (Array.isArray(d)) { - // If the cells data is an array of e.g. objects, display a 'array' badge with a - // tooltip that explains that this type of field is not supported in this table. - return ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.exploration.indexArrayBadgeContent', - { - defaultMessage: 'array', - } - )} - - - ); - } else if (typeof d === 'object' && d !== null) { - // If the cells data is an object, display a 'object' badge with a - // tooltip that explains that this type of field is not supported in this table. - return ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.exploration.indexObjectBadgeContent', - { - defaultMessage: 'object', - } - )} - - - ); - } - - const split = k.split('.'); - let backgroundColor; - const color = undefined; - const resultsField = jobConfig.dest.results_field; - - if (fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${k}`] !== undefined) { - backgroundColor = cellBgColor(fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${k}`]); - } - - if (split.length > 2 && split[0] === resultsField && split[1] === FEATURE_INFLUENCE) { - backgroundColor = cellBgColor(d); - } - - return ( -
- {d} -
- ); - }; - - let columnType; - - if (tableItems.length > 0) { - columnType = typeof tableItems[0][k]; - } - - if (typeof columnType !== 'undefined') { - switch (columnType) { - case 'boolean': - column.dataType = 'boolean'; - break; - case 'Date': - column.align = 'right'; - column.render = (d: any) => - formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); - break; - case 'number': - column.dataType = 'number'; - column.render = render; - break; - default: - column.render = render; - break; - } - } else { - column.render = render; - } - - return column; - }) - ); - } - - useEffect(() => { - if (jobConfig !== undefined) { - const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); - const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName); - let requiresKeyword = false; - - const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0]; - const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC; - - if (outlierScoreFieldSelected === false) { - requiresKeyword = isKeywordAndTextType(field); - } - - loadExploreData({ field, direction, searchQuery, requiresKeyword }); - } - }, [JSON.stringify(searchQuery)]); - - useEffect(() => { - // by default set the sorting to descending on the `outlier_score` field. - // if that's not available sort ascending on the first column. - // also check if the current sorting field is still available. - if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) { - const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); - const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName); - let requiresKeyword = false; - - const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0]; - const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC; - - if (outlierScoreFieldSelected === false) { - requiresKeyword = isKeywordAndTextType(field); - } - - loadExploreData({ field, direction, searchQuery, requiresKeyword }); - return; - } - }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]); - - let sorting: SortingPropType = false; - let onTableChange; - - if (columns.length > 0 && sortField !== '') { - sorting = { - sort: { - field: sortField, - direction: sortDirection, - }, - }; - - onTableChange = ({ - page = { index: 0, size: 10 }, - sort = { field: sortField, direction: sortDirection }, - }: OnTableChangeArg) => { - const { index, size } = page; - setPageIndex(index); - setPageSize(size); - - if ( - (sort.field !== sortField || sort.direction !== sortDirection) && - jobConfig !== undefined - ) { - const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); - let requiresKeyword = false; - - if (outlierScoreFieldName !== sort.field) { - requiresKeyword = isKeywordAndTextType(sort.field); - } - loadExploreData({ ...sort, searchQuery, requiresKeyword }); - } - }; - } - - const pagination = { - initialPageIndex: pageIndex, - initialPageSize: pageSize, - totalItemCount: tableItems.length, - pageSizeOptions: PAGE_SIZE_OPTIONS, - hidePerPageOptions: false, - }; - - const onQueryChange = ({ query, error }: { query: QueryType; error: any }) => { - if (error) { - setSearchError(error.message); - } else { - try { - const esQueryDsl = Query.toESQuery(query); - setSearchQuery(esQueryDsl); - setSearchString(query.text); - setSearchError(undefined); - } catch (e) { - setSearchError(e.toString()); - } - } - }; - - const search = { - onChange: onQueryChange, - defaultQuery: searchString, - box: { - incremental: false, - placeholder: i18n.translate('xpack.ml.dataframe.analytics.exploration.searchBoxPlaceholder', { - defaultMessage: 'E.g. avg>0.5', - }), - }, - }; - - if (jobConfig === undefined) { - return null; - } - // if it's a searchBar syntax error leave the table visible so they can try again - if (status === INDEX_STATUS.ERROR && !errorMessage.includes('parsing_exception')) { - return ( - - - -

{errorMessage}

-
-
- ); - } - - let tableError = - status === INDEX_STATUS.ERROR && errorMessage.includes('parsing_exception') - ? errorMessage - : searchError; - - if (status === INDEX_STATUS.LOADED && tableItems.length === 0 && tableError === undefined) { - tableError = i18n.translate('xpack.ml.dataframe.analytics.exploration.noDataCalloutBody', { - defaultMessage: - 'The query for the index returned no results. Please make sure the index contains documents and your query is not too restrictive.', - }); - } - - const MlInMemoryTableBasic = mlInMemoryTableBasicFactory(); - - return ( - - - - - - - - - {getTaskStateBadge(jobStatus)} - - - - - - - {docFieldsCount > MAX_COLUMNS && ( - - {i18n.translate('xpack.ml.dataframe.analytics.exploration.fieldSelection', { - defaultMessage: - '{selectedFieldsLength, number} of {docFieldsCount, number} {docFieldsCount, plural, one {field} other {fields}} selected', - values: { selectedFieldsLength: selectedFields.length, docFieldsCount }, - })} - - )} - - - - - } - isOpen={isColumnsPopoverVisible} - closePopover={closeColumnsPopover} - ownFocus - > - - {i18n.translate( - 'xpack.ml.dataframe.analytics.exploration.selectFieldsPopoverTitle', - { - defaultMessage: 'Select fields', - } - )} - -
- {docFields.map(d => ( - toggleColumn(d)} - disabled={selectedFields.includes(d) && selectedFields.length === 1} - /> - ))} -
-
-
-
-
-
-
- {status === INDEX_STATUS.LOADING && } - {status !== INDEX_STATUS.LOADING && ( - - )} - {(columns.length > 0 || searchQuery !== defaultSearchQuery) && sortField !== '' && ( - <> - - - - {tableItems.length === SEARCH_SIZE && ( - - {i18n.translate( - 'xpack.ml.dataframe.analytics.exploration.documentsShownHelpText', - { - defaultMessage: 'Showing first {searchSize} documents', - values: { searchSize: SEARCH_SIZE }, - } - )} - - )} - - - - - - - - )} -
- ); -}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/index.ts deleted file mode 100644 index 6f15c278158dc..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { Exploration } from './exploration'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts deleted file mode 100644 index 24cc8d000de7e..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useEffect, useState } from 'react'; - -import { SearchResponse } from 'elasticsearch'; - -import { SortDirection, SORT_DIRECTION } from '../../../../../components/ml_in_memory_table'; - -import { ml } from '../../../../../services/ml_api_service'; -import { getNestedProperty } from '../../../../../util/object_utils'; - -import { - getDefaultSelectableFields, - getFlattenedFields, - DataFrameAnalyticsConfig, - EsFieldName, - INDEX_STATUS, - SEARCH_SIZE, - defaultSearchQuery, - SearchQuery, -} from '../../../../common'; -import { LoadExploreDataArg } from '../../../../common/analytics'; - -import { getOutlierScoreFieldName } from './common'; - -export type TableItem = Record; - -export interface UseExploreDataReturnType { - errorMessage: string; - loadExploreData: (arg: LoadExploreDataArg) => void; - sortField: EsFieldName; - sortDirection: SortDirection; - status: INDEX_STATUS; - tableItems: TableItem[]; -} - -export const useExploreData = ( - jobConfig: DataFrameAnalyticsConfig | undefined, - selectedFields: EsFieldName[], - setSelectedFields: React.Dispatch> -): UseExploreDataReturnType => { - const [errorMessage, setErrorMessage] = useState(''); - const [status, setStatus] = useState(INDEX_STATUS.UNUSED); - const [tableItems, setTableItems] = useState([]); - const [sortField, setSortField] = useState(''); - const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC); - - const loadExploreData = async ({ - field, - direction, - searchQuery, - requiresKeyword, - }: LoadExploreDataArg) => { - if (jobConfig !== undefined) { - setErrorMessage(''); - setStatus(INDEX_STATUS.LOADING); - - try { - const resultsField = jobConfig.dest.results_field; - - const body: SearchQuery = { - query: searchQuery, - }; - - if (field !== undefined) { - body.sort = [ - { - [`${field}${requiresKeyword ? '.keyword' : ''}`]: { - order: direction, - }, - }, - ]; - } - - const resp: SearchResponse = await ml.esSearch({ - index: jobConfig.dest.index, - size: SEARCH_SIZE, - body, - }); - - setSortField(field); - setSortDirection(direction); - - const docs = resp.hits.hits; - - if (docs.length === 0) { - setTableItems([]); - setStatus(INDEX_STATUS.LOADED); - return; - } - - if (selectedFields.length === 0) { - const newSelectedFields = getDefaultSelectableFields(docs, resultsField); - setSelectedFields(newSelectedFields); - } - - // Create a version of the doc's source with flattened field names. - // This avoids confusion later on if a field name has dots in its name - // or is a nested fields when displaying it via EuiInMemoryTable. - const flattenedFields = getFlattenedFields(docs[0]._source, resultsField); - const transformedTableItems = docs.map(doc => { - const item: TableItem = {}; - flattenedFields.forEach(ff => { - item[ff] = getNestedProperty(doc._source, ff); - if (item[ff] === undefined) { - // If the attribute is undefined, it means it was not a nested property - // but had dots in its actual name. This selects the property by its - // full name and assigns it to `item[ff]`. - item[ff] = doc._source[`"${ff}"`]; - } - if (item[ff] === undefined) { - const parts = ff.split('.'); - if (parts[0] === resultsField && parts.length >= 2) { - parts.shift(); - if (doc._source[resultsField] !== undefined) { - item[ff] = doc._source[resultsField][parts.join('.')]; - } - } - } - }); - return item; - }); - - setTableItems(transformedTableItems); - setStatus(INDEX_STATUS.LOADED); - } catch (e) { - if (e.message !== undefined) { - setErrorMessage(e.message); - } else { - setErrorMessage(JSON.stringify(e)); - } - setTableItems([]); - setStatus(INDEX_STATUS.ERROR); - } - } - }; - - useEffect(() => { - if (jobConfig !== undefined) { - loadExploreData({ - field: getOutlierScoreFieldName(jobConfig), - direction: SORT_DIRECTION.DESC, - searchQuery: defaultSearchQuery, - }); - } - }, [jobConfig && jobConfig.id]); - - return { errorMessage, loadExploreData, sortField, sortDirection, status, tableItems }; -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/exploration_data_grid.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/exploration_data_grid.tsx new file mode 100644 index 0000000000000..2df0f70a56722 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/exploration_data_grid.tsx @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Dispatch, FC, SetStateAction, useCallback, useMemo } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { EuiDataGrid, EuiDataGridPaginationProps, EuiDataGridSorting } from '@elastic/eui'; + +import { euiDataGridStyle, euiDataGridToolbarSettings } from '../../../../common'; + +const FEATURE_INFLUENCE = 'feature_influence'; +const PAGE_SIZE_OPTIONS = [5, 10, 25, 50]; + +type Pagination = Pick; +type TableItem = Record; + +interface ExplorationDataGridProps { + colorRange: (d: number) => string; + columns: any[]; + pagination: Pagination; + resultsField: string; + rowCount: number; + selectedFields: string[]; + setPagination: Dispatch>; + setSelectedFields: Dispatch>; + setSortingColumns: Dispatch>; + sortingColumns: EuiDataGridSorting['columns']; + tableItems: TableItem[]; +} + +export const ExplorationDataGrid: FC = ({ + colorRange, + columns, + pagination, + resultsField, + rowCount, + selectedFields, + setPagination, + setSelectedFields, + setSortingColumns, + sortingColumns, + tableItems, +}) => { + const renderCellValue = useMemo(() => { + return ({ + rowIndex, + columnId, + setCellProps, + }: { + rowIndex: number; + columnId: string; + setCellProps: any; + }) => { + const adjustedRowIndex = rowIndex - pagination.pageIndex * pagination.pageSize; + + const fullItem = tableItems[adjustedRowIndex]; + + if (fullItem === undefined) { + return null; + } + + const cellValue = + fullItem.hasOwnProperty(columnId) && fullItem[columnId] !== undefined + ? fullItem[columnId] + : null; + + const split = columnId.split('.'); + let backgroundColor; + + // column with feature values get color coded by its corresponding influencer value + if (fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${columnId}`] !== undefined) { + backgroundColor = colorRange(fullItem[`${resultsField}.${FEATURE_INFLUENCE}.${columnId}`]); + } + + // column with influencer values get color coded by its own value + if (split.length > 2 && split[0] === resultsField && split[1] === FEATURE_INFLUENCE) { + backgroundColor = colorRange(cellValue); + } + + if (backgroundColor !== undefined) { + setCellProps({ + style: { backgroundColor }, + }); + } + + if (typeof cellValue === 'string' || cellValue === null) { + return cellValue; + } + + if (typeof cellValue === 'boolean') { + return cellValue ? 'true' : 'false'; + } + + if (typeof cellValue === 'object' && cellValue !== null) { + return JSON.stringify(cellValue); + } + + return cellValue; + }; + }, [resultsField, rowCount, tableItems, pagination.pageIndex, pagination.pageSize]); + + const onChangeItemsPerPage = useCallback( + pageSize => { + setPagination(p => { + const pageIndex = Math.floor((p.pageSize * p.pageIndex) / pageSize); + return { pageIndex, pageSize }; + }); + }, + [setPagination] + ); + + const onChangePage = useCallback(pageIndex => setPagination(p => ({ ...p, pageIndex })), [ + setPagination, + ]); + + const onSort = useCallback(sc => setSortingColumns(sc), [setSortingColumns]); + + return ( + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/index.ts new file mode 100644 index 0000000000000..ea89e91de5046 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_data_grid/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ExplorationDataGrid } from './exploration_data_grid'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx new file mode 100644 index 0000000000000..f95e6a93058ba --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Dispatch, FC, SetStateAction, useState } from 'react'; + +import { EuiCode, EuiInputPopover } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/common/index_patterns'; +import { + esKuery, + esQuery, + Query, + QueryStringInput, +} from '../../../../../../../../../../src/plugins/data/public'; + +import { SEARCH_QUERY_LANGUAGE } from '../../../../../../../common/constants/search'; + +import { SavedSearchQuery } from '../../../../../contexts/ml'; + +interface ErrorMessage { + query: string; + message: string; +} + +interface ExplorationQueryBarProps { + indexPattern: IIndexPattern; + setSearchQuery: Dispatch>; +} + +export const ExplorationQueryBar: FC = ({ + indexPattern, + setSearchQuery, +}) => { + // The internal state of the input query bar updated on every key stroke. + const [searchInput, setSearchInput] = useState({ + query: '', + language: SEARCH_QUERY_LANGUAGE.KUERY, + }); + + const [errorMessage, setErrorMessage] = useState(undefined); + + const searchChangeHandler = (query: Query) => setSearchInput(query); + const searchSubmitHandler = (query: Query) => { + try { + switch (query.language) { + case SEARCH_QUERY_LANGUAGE.KUERY: + setSearchQuery( + esKuery.toElasticsearchQuery( + esKuery.fromKueryExpression(query.query as string), + indexPattern + ) + ); + return; + case SEARCH_QUERY_LANGUAGE.LUCENE: + setSearchQuery(esQuery.luceneStringToDsl(query.query as string)); + return; + } + } catch (e) { + setErrorMessage({ query: query.query as string, message: e.message }); + } + }; + + return ( + setErrorMessage(undefined)} + input={ + + } + isOpen={errorMessage?.query === searchInput.query && errorMessage?.message !== ''} + > + + {i18n.translate('xpack.ml.stepDefineForm.invalidQuery', { + defaultMessage: 'Invalid Query', + })} + {': '} + {errorMessage?.message.split('\n')[0]} + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/index.ts new file mode 100644 index 0000000000000..bebf4f65db04e --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ExplorationQueryBar } from './exploration_query_bar'; diff --git a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/index.ts similarity index 80% rename from x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/index.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/index.ts index b9a64a3cc17e6..de49556f9cc98 100644 --- a/x-pack/plugins/dashboard_enhanced/public/components/dashboard_drilldown_config/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './dashboard_drilldown_config'; +export { OutlierExploration } from './outlier_exploration'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.test.tsx similarity index 88% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.test.tsx index ca8fd68079f7e..030447873f6a5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.test.tsx @@ -10,7 +10,7 @@ import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/ import { MlContext } from '../../../../../contexts/ml'; import { kibanaContextValueMock } from '../../../../../contexts/ml/__mocks__/kibana_context_value'; -import { Exploration } from './exploration'; +import { OutlierExploration } from './outlier_exploration'; // workaround to make React.memo() work with enzyme jest.mock('react', () => { @@ -22,7 +22,7 @@ describe('Data Frame Analytics: ', () => { test('Minimal initialization', () => { const wrapper = shallow( - + ); // Without the jobConfig being loaded, the component will just return empty. diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx new file mode 100644 index 0000000000000..214bc01c6a2ef --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -0,0 +1,220 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; + +import { + useColorRange, + ColorRangeLegend, + COLOR_RANGE, + COLOR_RANGE_SCALE, +} from '../../../../../components/color_range_legend'; + +import { sortColumns, INDEX_STATUS, defaultSearchQuery } from '../../../../common'; + +import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; +import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; + +import { useExploreData, TableItem } from '../../hooks/use_explore_data'; + +import { ExplorationDataGrid } from '../exploration_data_grid'; +import { ExplorationQueryBar } from '../exploration_query_bar'; + +const FEATURE_INFLUENCE = 'feature_influence'; + +const ExplorationTitle: FC<{ jobId: string }> = ({ jobId }) => ( + + + {i18n.translate('xpack.ml.dataframe.analytics.exploration.jobIdTitle', { + defaultMessage: 'Outlier detection job ID {jobId}', + values: { jobId }, + })} + + +); + +interface ExplorationProps { + jobId: string; + jobStatus: DATA_FRAME_TASK_STATE; +} + +const getFeatureCount = (resultsField: string, tableItems: TableItem[] = []) => { + if (tableItems.length === 0) { + return 0; + } + + return Object.keys(tableItems[0]).filter(key => + key.includes(`${resultsField}.${FEATURE_INFLUENCE}.`) + ).length; +}; + +export const OutlierExploration: FC = React.memo(({ jobId, jobStatus }) => { + const { + errorMessage, + indexPattern, + jobConfig, + pagination, + searchQuery, + selectedFields, + setPagination, + setSearchQuery, + setSelectedFields, + setSortingColumns, + sortingColumns, + rowCount, + status, + tableFields, + tableItems, + } = useExploreData(jobId); + + const columns = []; + + if ( + jobConfig !== undefined && + indexPattern !== undefined && + selectedFields.length > 0 && + tableItems.length > 0 + ) { + const resultsField = jobConfig.dest.results_field; + const removePrefix = new RegExp(`^${resultsField}\.${FEATURE_INFLUENCE}\.`, 'g'); + columns.push( + ...tableFields.sort(sortColumns(tableItems[0], resultsField)).map(id => { + const idWithoutPrefix = id.replace(removePrefix, ''); + const field = indexPattern.fields.getByName(idWithoutPrefix); + + // Built-in values are ['boolean', 'currency', 'datetime', 'numeric', 'json'] + // To fall back to the default string schema it needs to be undefined. + let schema; + + switch (field?.type) { + case 'date': + schema = 'datetime'; + break; + case 'geo_point': + schema = 'json'; + break; + case 'number': + schema = 'numeric'; + break; + } + + if (id === `${resultsField}.outlier_score`) { + schema = 'numeric'; + } + + return { id, schema }; + }) + ); + } + + const colorRange = useColorRange( + COLOR_RANGE.BLUE, + COLOR_RANGE_SCALE.INFLUENCER, + jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1 + ); + + if (jobConfig === undefined || indexPattern === undefined) { + return null; + } + + // if it's a searchBar syntax error leave the table visible so they can try again + if (status === INDEX_STATUS.ERROR && !errorMessage.includes('parsing_exception')) { + return ( + + + +

{errorMessage}

+
+
+ ); + } + + let tableError = + status === INDEX_STATUS.ERROR && errorMessage.includes('parsing_exception') + ? errorMessage + : undefined; + + if (status === INDEX_STATUS.LOADED && tableItems.length === 0 && tableError === undefined) { + tableError = i18n.translate('xpack.ml.dataframe.analytics.exploration.noDataCalloutBody', { + defaultMessage: + 'The query for the index returned no results. Please make sure the index contains documents and your query is not too restrictive.', + }); + } + + return ( + + + + + + + {getTaskStateBadge(jobStatus)} + + + + {(columns.length > 0 || searchQuery !== defaultSearchQuery) && ( + <> + + + + + + + + + + + {columns.length > 0 && tableItems.length > 0 && ( + + )} + + )} + + ); +}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx index 4e9571ca4a34d..7a6b2b23ba7a3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/results_table.tsx @@ -45,6 +45,7 @@ import { EXTENDED_NUMERICAL_TYPES, toggleSelectedField, isKeywordAndTextType, + sortRegressionResultsFields, } from '../../../../common/fields'; import { @@ -134,79 +135,81 @@ export const ResultsTable: FC = React.memo( tableItems, } = useExploreData(jobConfig, selectedFields, setSelectedFields, setDocFields, setDepVarType); - const columns: Array> = selectedFields.map(field => { - const { type } = field; - const isNumber = - type !== undefined && - (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type)); - - const column: ColumnType = { - field: field.name, - name: field.name, - sortable: true, - truncateText: true, - }; - - const render = (d: any, fullItem: EsDoc) => { - if (Array.isArray(d) && d.every(item => typeof item === 'string')) { - // If the cells data is an array of strings, return as a comma separated list. - // The list will get limited to 5 items with `…` at the end if there's more in the original array. - return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; - } else if (Array.isArray(d)) { - // If the cells data is an array of e.g. objects, display a 'array' badge with a - // tooltip that explains that this type of field is not supported in this table. - return ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.indexArrayBadgeContent', + const columns: Array> = selectedFields + .sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig)) + .map(field => { + const { type } = field; + const isNumber = + type !== undefined && + (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type)); + + const column: ColumnType = { + field: field.name, + name: field.name, + sortable: true, + truncateText: true, + }; + + const render = (d: any, fullItem: EsDoc) => { + if (Array.isArray(d) && d.every(item => typeof item === 'string')) { + // If the cells data is an array of strings, return as a comma separated list. + // The list will get limited to 5 items with `…` at the end if there's more in the original array. + return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; + } else if (Array.isArray(d)) { + // If the cells data is an array of e.g. objects, display a 'array' badge with a + // tooltip that explains that this type of field is not supported in this table. + return ( + - - ); - } - - return d; - }; + > + + {i18n.translate( + 'xpack.ml.dataframe.analytics.regressionExploration.indexArrayBadgeContent', + { + defaultMessage: 'array', + } + )} + + + ); + } - if (isNumber) { - column.dataType = 'number'; - column.render = render; - } else if (typeof type !== 'undefined') { - switch (type) { - case ES_FIELD_TYPES.BOOLEAN: - column.dataType = ES_FIELD_TYPES.BOOLEAN; - break; - case ES_FIELD_TYPES.DATE: - column.align = 'right'; - column.render = (d: any) => { - if (d !== undefined) { - return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); - } - return d; - }; - break; - default: - column.render = render; - break; + return d; + }; + + if (isNumber) { + column.dataType = 'number'; + column.render = render; + } else if (typeof type !== 'undefined') { + switch (type) { + case ES_FIELD_TYPES.BOOLEAN: + column.dataType = ES_FIELD_TYPES.BOOLEAN; + break; + case ES_FIELD_TYPES.DATE: + column.align = 'right'; + column.render = (d: any) => { + if (d !== undefined) { + return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); + } + return d; + }; + break; + default: + column.render = render; + break; + } + } else { + column.render = render; } - } else { - column.render = render; - } - return column; - }); + return column; + }); const docFieldsCount = docFields.length; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/common.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/common.test.ts similarity index 100% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/common.test.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/common.test.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/common.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/common.ts similarity index 100% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/common.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/common.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/index.ts new file mode 100644 index 0000000000000..dd896ca02f7f7 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { useExploreData, TableItem } from './use_explore_data'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/use_explore_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/use_explore_data.ts new file mode 100644 index 0000000000000..6ad0a1822e490 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/hooks/use_explore_data/use_explore_data.ts @@ -0,0 +1,232 @@ +/* + * 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 { useEffect, useState, Dispatch, SetStateAction } from 'react'; +import { SearchResponse } from 'elasticsearch'; + +import { EuiDataGridPaginationProps, EuiDataGridSorting } from '@elastic/eui'; + +import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; + +import { Dictionary } from '../../../../../../../common/types/common'; + +import { SavedSearchQuery } from '../../../../../contexts/ml'; +import { ml } from '../../../../../services/ml_api_service'; +import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; +import { getIndexPatternIdFromName } from '../../../../../util/index_utils'; +import { getNestedProperty } from '../../../../../util/object_utils'; +import { useMlContext } from '../../../../../contexts/ml'; + +import { + getDefaultSelectableFields, + getFlattenedFields, + DataFrameAnalyticsConfig, + EsFieldName, + INDEX_STATUS, + defaultSearchQuery, +} from '../../../../common'; +import { isKeywordAndTextType } from '../../../../common/fields'; + +import { getOutlierScoreFieldName } from './common'; + +export type TableItem = Record; + +type Pagination = Pick; + +interface UseExploreDataReturnType { + errorMessage: string; + indexPattern: IndexPattern | undefined; + jobConfig: DataFrameAnalyticsConfig | undefined; + pagination: Pagination; + searchQuery: SavedSearchQuery; + selectedFields: EsFieldName[]; + setJobConfig: Dispatch>; + setPagination: Dispatch>; + setSearchQuery: Dispatch>; + setSelectedFields: Dispatch>; + setSortingColumns: Dispatch>; + rowCount: number; + sortingColumns: EuiDataGridSorting['columns']; + status: INDEX_STATUS; + tableFields: string[]; + tableItems: TableItem[]; +} + +type EsSorting = Dictionary<{ + order: 'asc' | 'desc'; +}>; + +// The types specified in `@types/elasticsearch` are out of date and still have `total: number`. +interface SearchResponse7 extends SearchResponse { + hits: SearchResponse['hits'] & { + total: { + value: number; + relation: string; + }; + }; +} + +export const useExploreData = (jobId: string): UseExploreDataReturnType => { + const mlContext = useMlContext(); + + const [indexPattern, setIndexPattern] = useState(undefined); + const [jobConfig, setJobConfig] = useState(undefined); + const [errorMessage, setErrorMessage] = useState(''); + const [status, setStatus] = useState(INDEX_STATUS.UNUSED); + + const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]); + const [tableFields, setTableFields] = useState([]); + const [tableItems, setTableItems] = useState([]); + const [rowCount, setRowCount] = useState(0); + + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 25 }); + const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); + const [sortingColumns, setSortingColumns] = useState([]); + + // get analytics configuration + useEffect(() => { + (async function() { + const analyticsConfigs = await ml.dataFrameAnalytics.getDataFrameAnalytics(jobId); + if ( + Array.isArray(analyticsConfigs.data_frame_analytics) && + analyticsConfigs.data_frame_analytics.length > 0 + ) { + setJobConfig(analyticsConfigs.data_frame_analytics[0]); + } + })(); + }, []); + + // get index pattern and field caps + useEffect(() => { + (async () => { + if (jobConfig !== undefined) { + const sourceIndex = jobConfig.source.index[0]; + const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; + const jobCapsIndexPattern: IndexPattern = await mlContext.indexPatterns.get(indexPatternId); + if (jobCapsIndexPattern !== undefined) { + setIndexPattern(jobCapsIndexPattern); + await newJobCapsService.initializeFromIndexPattern(jobCapsIndexPattern, false, false); + } + } + })(); + }, [jobConfig && jobConfig.id]); + + // initialize sorting: reverse sort on outlier score column + useEffect(() => { + if (jobConfig !== undefined) { + setSortingColumns([{ id: getOutlierScoreFieldName(jobConfig), direction: 'desc' }]); + } + }, [jobConfig && jobConfig.id]); + + // update data grid data + useEffect(() => { + (async () => { + if (jobConfig !== undefined) { + setErrorMessage(''); + setStatus(INDEX_STATUS.LOADING); + + try { + const resultsField = jobConfig.dest.results_field; + + const sort: EsSorting = sortingColumns + .map(column => { + const { id } = column; + column.id = isKeywordAndTextType(id) ? `${id}.keyword` : id; + return column; + }) + .reduce((s, column) => { + s[column.id] = { order: column.direction }; + return s; + }, {} as EsSorting); + + const { pageIndex, pageSize } = pagination; + const resp: SearchResponse7 = await ml.esSearch({ + index: jobConfig.dest.index, + body: { + query: searchQuery, + from: pageIndex * pageSize, + size: pageSize, + ...(Object.keys(sort).length > 0 ? { sort } : {}), + }, + }); + + setRowCount(resp.hits.total.value); + + const docs = resp.hits.hits; + + if (docs.length === 0) { + setTableItems([]); + setStatus(INDEX_STATUS.LOADED); + return; + } + + if (selectedFields.length === 0) { + const newSelectedFields = getDefaultSelectableFields(docs, resultsField); + setSelectedFields(newSelectedFields); + } + + // Create a version of the doc's source with flattened field names. + // This avoids confusion later on if a field name has dots in its name + // or is a nested fields when displaying it via EuiInMemoryTable. + const flattenedFields = getFlattenedFields(docs[0]._source, resultsField); + const transformedTableItems = docs.map(doc => { + const item: TableItem = {}; + flattenedFields.forEach(ff => { + item[ff] = getNestedProperty(doc._source, ff); + if (item[ff] === undefined) { + // If the attribute is undefined, it means it was not a nested property + // but had dots in its actual name. This selects the property by its + // full name and assigns it to `item[ff]`. + item[ff] = doc._source[`"${ff}"`]; + } + if (item[ff] === undefined) { + const parts = ff.split('.'); + if (parts[0] === resultsField && parts.length >= 2) { + parts.shift(); + if (doc._source[resultsField] !== undefined) { + item[ff] = doc._source[resultsField][parts.join('.')]; + } + } + } + }); + return item; + }); + + setTableFields(flattenedFields); + setTableItems(transformedTableItems); + setStatus(INDEX_STATUS.LOADED); + } catch (e) { + if (e.message !== undefined) { + setErrorMessage(e.message); + } else { + setErrorMessage(JSON.stringify(e)); + } + setTableItems([]); + setStatus(INDEX_STATUS.ERROR); + } + } + })(); + }, [jobConfig && jobConfig.id, pagination, searchQuery, selectedFields, sortingColumns]); + + return { + errorMessage, + indexPattern, + jobConfig, + pagination, + rowCount, + searchQuery, + selectedFields, + setJobConfig, + setPagination, + setSearchQuery, + setSelectedFields, + setSortingColumns, + sortingColumns, + status, + tableFields, + tableItems, + }; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx index b00a38e2b5f65..efbebc1564bf9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/page.tsx @@ -22,7 +22,7 @@ import { import { NavigationMenu } from '../../../components/navigation_menu'; -import { Exploration } from './components/exploration'; +import { OutlierExploration } from './components/outlier_exploration'; import { RegressionExploration } from './components/regression_exploration'; import { ClassificationExploration } from './components/classification_exploration'; @@ -37,7 +37,7 @@ export const Page: FC<{ - + @@ -65,10 +65,10 @@ export const Page: FC<{ - + {analysisType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION && ( - + )} {analysisType === ANALYSIS_CONFIG_TYPE.REGRESSION && ( diff --git a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index 254788c52a7a8..a8bb5a0a8fe10 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { isFullLicense } from '../license'; -import { useTimefilter } from '../contexts/kibana'; +import { useTimefilter, useMlKibana } from '../contexts/kibana'; import { NavigationMenu } from '../components/navigation_menu'; @@ -50,8 +50,14 @@ function startTrialDescription() { export const DatavisualizerSelector: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const { + services: { licenseManagement }, + } = useMlKibana(); - const startTrialVisible = isFullLicense() === false; + const startTrialVisible = + licenseManagement !== undefined && + licenseManagement.enabled === true && + isFullLicense() === false; return ( diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/search_panel/search_panel.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/search_panel/search_panel.tsx index ef13fec3589fb..16004475eb44f 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/search_panel/search_panel.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/search_panel/search_panel.tsx @@ -6,14 +6,22 @@ import React, { FC, useState } from 'react'; -import { EuiFlexItem, EuiFlexGroup, EuiIconTip, EuiSuperSelect, EuiText } from '@elastic/eui'; +import { + EuiCode, + EuiFlexItem, + EuiFlexGroup, + EuiIconTip, + EuiInputPopover, + EuiSuperSelect, + EuiText, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; -import { SEARCH_QUERY_LANGUAGE } from '../../../../../../common/constants/search'; +import { SEARCH_QUERY_LANGUAGE, ErrorMessage } from '../../../../../../common/constants/search'; import { esKuery, @@ -22,8 +30,6 @@ import { QueryStringInput, } from '../../../../../../../../../src/plugins/data/public'; -import { getToastNotifications } from '../../../../util/dependency_cache'; - interface Props { indexPattern: IndexPattern; searchString: Query['query']; @@ -73,6 +79,7 @@ export const SearchPanel: FC = ({ query: searchString || '', language: searchQueryLanguage, }); + const [errorMessage, setErrorMessage] = useState(undefined); const searchHandler = (query: Query) => { let filterQuery; @@ -93,13 +100,7 @@ export const SearchPanel: FC = ({ setSearchQueryLanguage(query.language); } catch (e) { console.log('Invalid syntax', JSON.stringify(e, null, 2)); // eslint-disable-line no-console - const toastNotifications = getToastNotifications(); - toastNotifications.addError(e, { - title: i18n.translate('xpack.ml.datavisualizer.invalidSyntaxErrorMessage', { - defaultMessage: 'Invalid syntax in search bar', - }), - toastMessage: e.message ? e.message : e, - }); + setErrorMessage({ query: query.query as string, message: e.message }); } }; const searchChangeHandler = (query: Query) => setSearchInput(query); @@ -107,22 +108,40 @@ export const SearchPanel: FC = ({ return ( - + setErrorMessage(undefined)} + input={ + + } + isOpen={errorMessage?.query === searchInput.query && errorMessage?.message !== ''} + > + + {i18n.translate( + 'xpack.ml.datavisualizer.searchPanel.invalidKuerySyntaxErrorMessageQueryBar', + { + defaultMessage: 'Invalid query', + } + )} + {': '} + {errorMessage?.message.split('\n')[0]} + + diff --git a/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx new file mode 100644 index 0000000000000..0263ad08b03cf --- /dev/null +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx @@ -0,0 +1,179 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC, useState, useEffect } from 'react'; +import { EuiCode, EuiInputPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { + Query, + esKuery, + esQuery, + QueryStringInput, +} from '../../../../../../../../src/plugins/data/public'; +import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns'; +import { SEARCH_QUERY_LANGUAGE, ErrorMessage } from '../../../../../common/constants/search'; +import { explorerService } from '../../explorer_dashboard_service'; + +export const DEFAULT_QUERY_LANG = SEARCH_QUERY_LANGUAGE.KUERY; + +export function getKqlQueryValues({ + inputString, + queryLanguage, + indexPattern, +}: { + inputString: string | { [key: string]: any }; + queryLanguage: string; + indexPattern: IIndexPattern; +}): { clearSettings: boolean; settings: any } { + let influencersFilterQuery: any = {}; + const filteredFields: string[] = []; + const ast = esKuery.fromKueryExpression(inputString); + const isAndOperator = ast && ast.function === 'and'; + // if ast.type == 'function' then layout of ast.arguments: + // [{ arguments: [ { type: 'literal', value: 'AAL' } ] },{ arguments: [ { type: 'literal', value: 'AAL' } ] }] + if (ast && Array.isArray(ast.arguments)) { + ast.arguments.forEach(arg => { + if (arg.arguments !== undefined) { + arg.arguments.forEach((nestedArg: { type: string; value: string }) => { + if (typeof nestedArg.value === 'string') { + filteredFields.push(nestedArg.value); + } + }); + } else if (typeof arg.value === 'string') { + filteredFields.push(arg.value); + } + }); + } + if (queryLanguage === SEARCH_QUERY_LANGUAGE.KUERY) { + influencersFilterQuery = esKuery.toElasticsearchQuery( + esKuery.fromKueryExpression(inputString), + indexPattern + ); + } else if (queryLanguage === SEARCH_QUERY_LANGUAGE.LUCENE) { + influencersFilterQuery = esQuery.luceneStringToDsl(inputString); + } + + const clearSettings = + influencersFilterQuery?.match_all && Object.keys(influencersFilterQuery.match_all).length === 0; + + return { + clearSettings, + settings: { + filterQuery: influencersFilterQuery, + queryString: inputString, + tableQueryString: inputString, + isAndOperator, + filteredFields, + }, + }; +} + +function getInitSearchInputState({ + filterActive, + queryString, +}: { + filterActive: boolean; + queryString?: string; +}) { + if (queryString !== undefined && filterActive === true) { + return { + language: SEARCH_QUERY_LANGUAGE.KUERY, + query: queryString, + }; + } else { + return { + query: '', + language: DEFAULT_QUERY_LANG, + }; + } +} + +interface ExplorerQueryBarProps { + filterActive: boolean; + filterIconTriggeredQuery: string; + filterPlaceHolder: string; + indexPattern: IIndexPattern; + queryString?: string; + updateLanguage: (language: string) => void; +} + +export const ExplorerQueryBar: FC = ({ + filterActive, + filterIconTriggeredQuery, + filterPlaceHolder, + indexPattern, + queryString, + updateLanguage, +}) => { + // The internal state of the input query bar updated on every key stroke. + const [searchInput, setSearchInput] = useState( + getInitSearchInputState({ filterActive, queryString }) + ); + const [errorMessage, setErrorMessage] = useState(undefined); + + useEffect(() => { + if (filterIconTriggeredQuery !== undefined) { + setSearchInput({ + language: searchInput.language, + query: filterIconTriggeredQuery, + }); + } + }, [filterIconTriggeredQuery]); + + const searchChangeHandler = (query: Query) => { + if (searchInput.language !== query.language) { + updateLanguage(query.language); + } + setSearchInput(query); + }; + const applyInfluencersFilterQuery = (query: Query) => { + try { + const { clearSettings, settings } = getKqlQueryValues({ + inputString: query.query, + queryLanguage: query.language, + indexPattern, + }); + + if (clearSettings === true) { + explorerService.clearInfluencerFilterSettings(); + } else { + explorerService.setInfluencerFilterSettings(settings); + } + } catch (e) { + console.log('Invalid query syntax in search bar', e); // eslint-disable-line no-console + setErrorMessage({ query: query.query as string, message: e.message }); + } + }; + + return ( + setErrorMessage(undefined)} + input={ + + } + isOpen={errorMessage?.query === searchInput.query && errorMessage?.message !== ''} + > + + {i18n.translate('xpack.ml.explorer.invalidKuerySyntaxErrorMessageQueryBar', { + defaultMessage: 'Invalid query', + })} + {': '} + {errorMessage?.message.split('\n')[0]} + + + ); +}; diff --git a/x-pack/plugins/dashboard_enhanced/public/components/index.ts b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/index.ts similarity index 81% rename from x-pack/plugins/dashboard_enhanced/public/components/index.ts rename to x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/index.ts index b9a64a3cc17e6..3c1d653249889 100644 --- a/x-pack/plugins/dashboard_enhanced/public/components/index.ts +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './dashboard_drilldown_config'; +export { ExplorerQueryBar } from './explorer_query_bar'; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.js b/x-pack/plugins/ml/public/application/explorer/explorer.js index cf01ef1e44c85..d61d56d07b644 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer.js @@ -38,7 +38,6 @@ import { } from './components'; import { ChartTooltip } from '../components/chart_tooltip'; import { ExplorerSwimlane } from './explorer_swimlane'; -import { KqlFilterBar } from '../components/kql_filter_bar'; import { TimeBuckets } from '../util/time_buckets'; import { InfluencersList } from '../components/influencers_list'; import { @@ -54,14 +53,17 @@ import { SelectInterval } from '../components/controls/select_interval/select_in import { SelectLimit, limit$ } from './select_limit/select_limit'; import { SelectSeverity } from '../components/controls/select_severity/select_severity'; import { + ExplorerQueryBar, getKqlQueryValues, + DEFAULT_QUERY_LANG, +} from './components/explorer_query_bar/explorer_query_bar'; +import { + getDateFormatTz, removeFilterFromQueryString, getQueryPattern, escapeParens, escapeDoubleQuotes, -} from '../components/kql_filter_bar/utils'; - -import { getDateFormatTz } from './explorer_utils'; +} from './explorer_utils'; import { getSwimlaneContainerWidth } from './legacy_utils'; import { @@ -86,7 +88,6 @@ function mapSwimlaneOptionsToEuiOptions(options) { text: option, })); } - const ExplorerPage = ({ children, jobSelectorProps, resizeRef }) => (
@@ -112,6 +113,8 @@ export class Explorer extends React.Component { showCharts: PropTypes.bool.isRequired, }; + state = { filterIconTriggeredQuery: undefined, language: DEFAULT_QUERY_LANG }; + _unsubscribeAll = new Subject(); // make sure dragSelect is only available if the mouse pointer is actually over a swimlane disableDragSelectOnMouseLeave = true; @@ -221,7 +224,6 @@ export class Explorer extends React.Component { // and will cause a syntax error when called with getKqlQueryValues applyFilter = (fieldName, fieldValue, action) => { const { filterActive, indexPattern, queryString } = this.props.explorerState; - let newQueryString = ''; const operator = 'and '; const sanitizedFieldName = escapeParens(fieldName); @@ -248,11 +250,22 @@ export class Explorer extends React.Component { } } + this.setState({ filterIconTriggeredQuery: `${newQueryString}` }); + try { - const queryValues = getKqlQueryValues(`${newQueryString}`, indexPattern); - this.applyInfluencersFilterQuery(queryValues); + const { clearSettings, settings } = getKqlQueryValues({ + inputString: `${newQueryString}`, + queryLanguage: this.state.language, + indexPattern, + }); + + if (clearSettings === true) { + explorerService.clearInfluencerFilterSettings(); + } else { + explorerService.setInfluencerFilterSettings(settings); + } } catch (e) { - console.log('Invalid kuery syntax', e); // eslint-disable-line no-console + console.log('Invalid query syntax from table', e); // eslint-disable-line no-console const toastNotifications = getToastNotifications(); toastNotifications.addDanger( @@ -264,18 +277,7 @@ export class Explorer extends React.Component { } }; - applyInfluencersFilterQuery = payload => { - const { filterQuery: influencersFilterQuery } = payload; - - if ( - influencersFilterQuery.match_all && - Object.keys(influencersFilterQuery.match_all).length === 0 - ) { - explorerService.clearInfluencerFilterSettings(); - } else { - explorerService.setInfluencerFilterSettings(payload); - } - }; + updateLanguage = language => this.setState({ language }); render() { const { showCharts, severity } = this.props; @@ -296,7 +298,6 @@ export class Explorer extends React.Component { selectedJobs, swimlaneContainerWidth, tableData, - tableQueryString, viewByLoadedForTimeFormatted, viewBySwimlaneData, viewBySwimlaneDataLoading, @@ -362,12 +363,13 @@ export class Explorer extends React.Component { {noInfluencersConfigured === false && influencers !== undefined && (
-
)} diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_index.scss b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_index.scss index dfa03861e32f3..4b3bf40b7b368 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_index.scss +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_index.scss @@ -1,4 +1,3 @@ @import 'components/explorer_chart_label/index'; @import 'explorer_chart'; -@import 'explorer_chart_tooltip'; -@import 'explorer_charts_container'; \ No newline at end of file +@import 'explorer_charts_container'; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/components/explorer_chart_label/explorer_chart_label.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/components/explorer_chart_label/explorer_chart_label.js index ea8bb3159202f..a9bff36461292 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/components/explorer_chart_label/explorer_chart_label.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/components/explorer_chart_label/explorer_chart_label.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import './_explorer_chart_label.scss'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_info_tooltip.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_info_tooltip.js index 5cf8245cd4739..0ee1eac19f64d 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_info_tooltip.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_info_tooltip.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import './_explorer_chart_tooltip.scss'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_swimlane.js b/x-pack/plugins/ml/public/application/explorer/explorer_swimlane.js index a229537ba3ca1..e8cb8377a656d 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_swimlane.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_swimlane.js @@ -387,9 +387,17 @@ export class ExplorerSwimlane extends React.Component { .each(function() { if (swimlaneData.fieldName !== undefined) { d3.select(this) - .on('mouseover', label => { + .on('mouseover', value => { mlChartTooltipService.show( - [{ skipHeader: true }, { name: swimlaneData.fieldName, value: label }], + [ + { skipHeader: true }, + { + label: swimlaneData.fieldName, + value, + seriesIdentifier: { key: value }, + valueAccessor: 'fieldName', + }, + ], this, { x: laneLabelWidth, @@ -400,7 +408,7 @@ export class ExplorerSwimlane extends React.Component { .on('mouseout', () => { mlChartTooltipService.hide(); }) - .attr('aria-label', label => `${mlEscape(swimlaneData.fieldName)}: ${mlEscape(label)}`); + .attr('aria-label', value => `${mlEscape(swimlaneData.fieldName)}: ${mlEscape(value)}`); } }); diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js index 0b41f789bb571..852b16ec581bb 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js @@ -883,3 +883,42 @@ export async function loadTopInfluencers( } }); } + +// Recommended by MDN for escaping user input to be treated as a literal string within a regular expression +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions +export function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +export function escapeParens(string) { + return string.replace(/[()]/g, '\\$&'); +} + +export function escapeDoubleQuotes(string) { + return string.replace(/\"/g, '\\$&'); +} + +export function getQueryPattern(fieldName, fieldValue) { + const sanitizedFieldName = escapeRegExp(fieldName); + const sanitizedFieldValue = escapeRegExp(fieldValue); + + return new RegExp(`(${sanitizedFieldName})\\s?:\\s?(")?(${sanitizedFieldValue})(")?`, 'i'); +} + +export function removeFilterFromQueryString(currentQueryString, fieldName, fieldValue) { + let newQueryString = ''; + // Remove the passed in fieldName and value from the existing filter + const queryPattern = getQueryPattern(fieldName, fieldValue); + newQueryString = currentQueryString.replace(queryPattern, ''); + // match 'and' or 'or' at the start/end of the string + const endPattern = /\s(and|or)\s*$/gi; + const startPattern = /^\s*(and|or)\s/gi; + // If string has a double operator (e.g. tag:thing or or tag:other) remove and replace with the first occurring operator + const invalidOperatorPattern = /\s+(and|or)\s+(and|or)\s+/gi; + newQueryString = newQueryString.replace(invalidOperatorPattern, ' $1 '); + // If string starts/ends with 'and' or 'or' remove that as that is illegal kuery syntax + newQueryString = newQueryString.replace(endPattern, ''); + newQueryString = newQueryString.replace(startPattern, ''); + + return newQueryString; +} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js index 2739f32aa1055..37b9fe5e1f2d0 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js @@ -38,7 +38,9 @@ export function isStartable(jobs) { } export function isStoppable(jobs) { - return jobs.some(j => j.datafeedState === DATAFEED_STATE.STARTED); + return jobs.some( + j => j.datafeedState === DATAFEED_STATE.STARTED || j.datafeedState === DATAFEED_STATE.STARTING + ); } export function isClosable(jobs) { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index 2800cd362d426..0b45209ca4f37 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -83,6 +83,10 @@ export class JobCreator { return this._type; } + public get indexPatternTitle(): string { + return this._indexPatternTitle; + } + protected _addDetector(detector: Detector, agg: Aggregation, field: Field) { this._detectors.push(detector); this._aggs.push(agg); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts index f115c203624eb..035af2d81adbc 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts @@ -14,12 +14,7 @@ import { } from '../../../../../../common/types/fields'; import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; -import { - JOB_TYPE, - CREATED_BY_LABEL, - DEFAULT_MODEL_MEMORY_LIMIT, -} from '../../../../../../common/constants/new_job'; -import { ml } from '../../../../services/ml_api_service'; +import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; @@ -27,7 +22,7 @@ export class MultiMetricJobCreator extends JobCreator { // a multi metric job has one optional overall partition field // which is the same for all detectors. private _splitField: SplitField = null; - private _lastEstimatedModelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; + protected _type: JOB_TYPE = JOB_TYPE.MULTI_METRIC; constructor( @@ -86,60 +81,6 @@ export class MultiMetricJobCreator extends JobCreator { this._removeDetector(index); } - // called externally to set the model memory limit based current detector configuration - public async calculateModelMemoryLimit() { - if (this.jobConfig.analysis_config.detectors.length === 0) { - this.modelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; - } else { - const { modelMemoryLimit } = await ml.calculateModelMemoryLimit({ - analysisConfig: this.jobConfig.analysis_config, - indexPattern: this._indexPatternTitle, - query: this._datafeed_config.query, - timeFieldName: this._job_config.data_description.time_field, - earliestMs: this._start, - latestMs: this._end, - }); - - try { - if (this.modelMemoryLimit === null) { - this.modelMemoryLimit = modelMemoryLimit; - } else { - // To avoid overwriting a possible custom set model memory limit, - // it only gets set to the estimation if the current limit is either - // the default value or the value of the previous estimation. - // That's our best guess if the value hasn't been customized. - // It doesn't get it if the user intentionally for whatever reason (re)set - // the value to either the default or pervious estimate. - // Because the string based limit could contain e.g. MB/Mb/mb - // all strings get lower cased for comparison. - const currentModelMemoryLimit = this.modelMemoryLimit.toLowerCase(); - const defaultModelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT.toLowerCase(); - if ( - currentModelMemoryLimit === defaultModelMemoryLimit || - currentModelMemoryLimit === this._lastEstimatedModelMemoryLimit - ) { - this.modelMemoryLimit = modelMemoryLimit; - } - } - this._lastEstimatedModelMemoryLimit = modelMemoryLimit.toLowerCase(); - } catch (error) { - if (this.modelMemoryLimit === null) { - this.modelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; - } else { - // To avoid overwriting a possible custom set model memory limit, - // the limit is reset to the default only if the current limit matches - // the previous estimated limit. - const currentModelMemoryLimit = this.modelMemoryLimit.toLowerCase(); - if (currentModelMemoryLimit === this._lastEstimatedModelMemoryLimit) { - this.modelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; - } - // eslint-disable-next-line no-console - console.error('Model memory limit could not be calculated', error); - } - } - } - } - public get aggFieldPairs(): AggFieldPair[] { return this.detectors.map((d, i) => ({ field: this._fields[i], diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.test.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.test.ts new file mode 100644 index 0000000000000..f85223db65399 --- /dev/null +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useFakeTimers, SinonFakeTimers } from 'sinon'; +import { CalculatePayload, modelMemoryEstimatorProvider } from './model_memory_estimator'; +import { JobValidator } from '../../job_validator'; +import { DEFAULT_MODEL_MEMORY_LIMIT } from '../../../../../../../common/constants/new_job'; +import { ml } from '../../../../../services/ml_api_service'; + +jest.mock('../../../../../services/ml_api_service', () => { + return { + ml: { + calculateModelMemoryLimit$: jest.fn(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { of } = require('rxjs'); + return of({ modelMemoryLimit: '15MB' }); + }), + }, + }; +}); + +describe('delay', () => { + let clock: SinonFakeTimers; + let modelMemoryEstimator: ReturnType; + let mockJobValidator: JobValidator; + + beforeEach(() => { + clock = useFakeTimers(); + mockJobValidator = { + isModelMemoryEstimationPayloadValid: true, + } as JobValidator; + modelMemoryEstimator = modelMemoryEstimatorProvider(mockJobValidator); + }); + afterEach(() => { + clock.restore(); + jest.clearAllMocks(); + }); + + test('should emit a default value first', () => { + const spy = jest.fn(); + modelMemoryEstimator.updates$.subscribe(spy); + expect(spy).toHaveBeenCalledWith(DEFAULT_MODEL_MEMORY_LIMIT); + }); + + test('should debounce it for 600 ms', () => { + const spy = jest.fn(); + + modelMemoryEstimator.updates$.subscribe(spy); + + modelMemoryEstimator.update({ analysisConfig: { detectors: [{}] } } as CalculatePayload); + + clock.tick(601); + expect(spy).toHaveBeenCalledWith('15MB'); + }); + + test('should not proceed further if the payload has not been changed', () => { + const spy = jest.fn(); + + modelMemoryEstimator.updates$.subscribe(spy); + + modelMemoryEstimator.update({ + analysisConfig: { detectors: [{ by_field_name: 'test' }] }, + } as CalculatePayload); + + clock.tick(601); + + modelMemoryEstimator.update({ + analysisConfig: { detectors: [{ by_field_name: 'test' }] }, + } as CalculatePayload); + + clock.tick(601); + + modelMemoryEstimator.update({ + analysisConfig: { detectors: [{ by_field_name: 'test' }] }, + } as CalculatePayload); + + clock.tick(601); + + expect(ml.calculateModelMemoryLimit$).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(2); + }); + + test('should call the endpoint only with a valid payload', () => { + const spy = jest.fn(); + + modelMemoryEstimator.updates$.subscribe(spy); + + modelMemoryEstimator.update(({ + analysisConfig: { detectors: [] }, + } as unknown) as CalculatePayload); + // @ts-ignore + mockJobValidator.isModelMemoryEstimationPayloadValid = false; + + clock.tick(601); + + expect(ml.calculateModelMemoryLimit$).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.ts new file mode 100644 index 0000000000000..501a63492da56 --- /dev/null +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/model_memory_estimator.ts @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { Observable, of, Subject, Subscription } from 'rxjs'; +import { isEqual, cloneDeep } from 'lodash'; +import { + catchError, + debounceTime, + distinctUntilChanged, + pluck, + startWith, + switchMap, + map, + pairwise, +} from 'rxjs/operators'; +import { useEffect, useState } from 'react'; +import { DEFAULT_MODEL_MEMORY_LIMIT } from '../../../../../../../common/constants/new_job'; +import { ml } from '../../../../../services/ml_api_service'; +import { JobValidator, VALIDATION_DELAY_MS } from '../../job_validator/job_validator'; +import { ErrorResponse } from '../../../../../../../common/types/errors'; +import { useMlKibana } from '../../../../../contexts/kibana'; +import { JobCreator } from '../job_creator'; + +export type CalculatePayload = Parameters[0]; + +export const modelMemoryEstimatorProvider = (jobValidator: JobValidator) => { + const modelMemoryCheck$ = new Subject(); + const error$ = new Subject(); + + return { + get error$(): Observable { + return error$.asObservable(); + }, + get updates$(): Observable { + return modelMemoryCheck$.pipe( + // delay the request, making sure the validation is completed + debounceTime(VALIDATION_DELAY_MS + 100), + // clone the object to compare payloads and proceed further only + // if the configuration has been changed + map(cloneDeep), + distinctUntilChanged(isEqual), + switchMap(payload => { + const isPayloadValid = jobValidator.isModelMemoryEstimationPayloadValid; + + return isPayloadValid + ? ml.calculateModelMemoryLimit$(payload).pipe( + pluck('modelMemoryLimit'), + catchError(error => { + // eslint-disable-next-line no-console + console.error('Model memory limit could not be calculated', error.body); + error$.next(error.body); + return of(DEFAULT_MODEL_MEMORY_LIMIT); + }) + ) + : of(DEFAULT_MODEL_MEMORY_LIMIT); + }), + startWith(DEFAULT_MODEL_MEMORY_LIMIT) + ); + }, + update(payload: CalculatePayload) { + modelMemoryCheck$.next(payload); + }, + }; +}; + +export const useModelMemoryEstimator = ( + jobCreator: JobCreator, + jobValidator: JobValidator, + jobCreatorUpdate: Function, + jobCreatorUpdated: number +) => { + const { + services: { notifications }, + } = useMlKibana(); + + // Initialize model memory estimator only once + const [modelMemoryEstimator] = useState(modelMemoryEstimatorProvider(jobValidator)); + + // Listen for estimation results and errors + useEffect(() => { + const subscription = new Subscription(); + + subscription.add( + modelMemoryEstimator.updates$ + .pipe(pairwise()) + .subscribe(([previousEstimation, currentEstimation]) => { + // to make sure we don't overwrite a manual input + if ( + jobCreator.modelMemoryLimit === null || + jobCreator.modelMemoryLimit === previousEstimation + ) { + jobCreator.modelMemoryLimit = currentEstimation; + // required in order to trigger changes on the input + jobCreatorUpdate(); + } + }) + ); + + subscription.add( + modelMemoryEstimator.error$.subscribe(error => { + notifications.toasts.addWarning({ + title: i18n.translate('xpack.ml.newJob.wizard.estimateModelMemoryError', { + defaultMessage: 'Model memory limit could not be calculated', + }), + text: error.message, + }); + }) + ); + + return () => { + subscription.unsubscribe(); + }; + }, []); + + // Update model memory estimation payload on the job creator updates + useEffect(() => { + modelMemoryEstimator.update({ + analysisConfig: jobCreator.jobConfig.analysis_config, + indexPattern: jobCreator.indexPatternTitle, + query: jobCreator.datafeedConfig.query, + timeFieldName: jobCreator.jobConfig.data_description.time_field, + earliestMs: jobCreator.start, + latestMs: jobCreator.end, + }); + }, [jobCreatorUpdated]); +}; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts index 82e5e15a24d5c..2650f89cf25ca 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_validator/job_validator.ts @@ -6,7 +6,7 @@ import { ReactElement } from 'react'; import { combineLatest, Observable, ReplaySubject, Subject } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { map, startWith, tap } from 'rxjs/operators'; import { basicJobValidation, basicDatafeedValidation, @@ -17,11 +17,12 @@ import { populateValidationMessages, checkForExistingJobAndGroupIds } from './ut import { ExistingJobsAndGroups } from '../../../../services/job_service'; import { cardinalityValidator, CardinalityValidatorResult } from './validators'; import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../common/constants/categorization_job'; +import { JOB_TYPE } from '../../../../../../common/constants/new_job'; // delay start of validation to allow the user to make changes // e.g. if they are typing in a new value, try not to validate // after every keystroke -const VALIDATION_DELAY_MS = 500; +export const VALIDATION_DELAY_MS = 500; type AsyncValidatorsResult = Partial; @@ -109,7 +110,8 @@ export class JobValidator { ...(curr ? curr : {}), }; }, {}); - }) + }), + startWith({}) ); this.validationResult$ = combineLatest([ @@ -270,4 +272,30 @@ export class JobValidator { public set categorizationField(valid: boolean) { this._advancedValidations.categorizationFieldValid.valid = valid; } + + /** + * Indicates if the Pick Fields step has a valid input + */ + public get isPickFieldsStepValid(): boolean { + return ( + this._jobCreator.detectors.length > 0 && + (this._jobCreator.type !== JOB_TYPE.ADVANCED || + (this._jobCreator.type === JOB_TYPE.ADVANCED && this.modelMemoryLimit.valid)) && + this.bucketSpan.valid && + this.duplicateDetectors.valid && + !this.validating && + (this._jobCreator.type !== JOB_TYPE.CATEGORIZATION || + (this._jobCreator.type === JOB_TYPE.CATEGORIZATION && this.categorizationField)) + ); + } + + public get isModelMemoryEstimationPayloadValid(): boolean { + return ( + this._jobCreator.detectors.length > 0 && + this.bucketSpan.valid && + this.duplicateDetectors.valid && + (this._jobCreator.type !== JOB_TYPE.CATEGORIZATION || + (this._jobCreator.type === JOB_TYPE.CATEGORIZATION && this.categorizationField)) + ); + } } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/influencers/influencers.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/influencers/influencers.tsx index 5c5ba38b1c5a1..c55bdeef4dde8 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/influencers/influencers.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/influencers/influencers.tsx @@ -25,9 +25,6 @@ export const Influencers: FC = () => { useEffect(() => { jobCreator.removeAllInfluencers(); influencers.forEach(i => jobCreator.addInfluencer(i)); - if (jobCreator instanceof MultiMetricJobCreator) { - jobCreator.calculateModelMemoryLimit(); - } jobCreatorUpdate(); }, [influencers.join()]); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx index ffa991388fbe2..cbd7c0ab72ffc 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx @@ -79,7 +79,6 @@ export const MultiMetricDetectors: FC = ({ setIsValid }) => { aggFieldPairList.forEach(pair => { jobCreator.addDetector(pair.agg, pair.field); }); - jobCreator.calculateModelMemoryLimit(); jobCreatorUpdate(); loadCharts(); setIsValid(aggFieldPairList.length > 0); @@ -115,7 +114,6 @@ export const MultiMetricDetectors: FC = ({ setIsValid }) => { } else { setFieldValues([]); } - jobCreator.calculateModelMemoryLimit(); }, [splitField]); // watch for changes in the split field values diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/pick_fields.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/pick_fields.tsx index bfec49678bc34..6f03b9a3c3321 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/pick_fields.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/pick_fields.tsx @@ -25,16 +25,7 @@ export const PickFieldsStep: FC = ({ setCurrentStep, isCurrentStep }) const jobType = jobCreator.type; useEffect(() => { - const active = - jobCreator.detectors.length > 0 && - (jobCreator.type !== JOB_TYPE.ADVANCED || - (jobCreator.type === JOB_TYPE.ADVANCED && jobValidator.modelMemoryLimit.valid)) && - jobValidator.bucketSpan.valid && - jobValidator.duplicateDetectors.valid && - jobValidator.validating === false && - (jobCreator.type !== JOB_TYPE.CATEGORIZATION || - (jobCreator.type === JOB_TYPE.CATEGORIZATION && jobValidator.categorizationField)); - setNextActive(active); + setNextActive(jobValidator.isPickFieldsStepValid); }, [jobValidatorUpdated]); return ( diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx index 6fe27457428b1..2ca0607f81a1e 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx @@ -5,6 +5,7 @@ */ import React, { FC, useReducer, useState, useEffect } from 'react'; +import { useModelMemoryEstimator } from '../../common/job_creator/util/model_memory_estimator'; import { WIZARD_STEPS } from '../components/step_types'; @@ -78,6 +79,8 @@ export const Wizard: FC = ({ stringifyConfigs(jobCreator.jobConfig, jobCreator.datafeedConfig) ); + useModelMemoryEstimator(jobCreator, jobValidator, jobCreatorUpdate, jobCreatorUpdated); + useEffect(() => { const subscription = jobValidator.validationResult$.subscribe(() => { setJobValidatorUpdate(jobValidatorUpdated); diff --git a/x-pack/plugins/ml/public/application/services/job_service.js b/x-pack/plugins/ml/public/application/services/job_service.js index e087740ec0e99..0454d40e78923 100644 --- a/x-pack/plugins/ml/public/application/services/job_service.js +++ b/x-pack/plugins/ml/public/application/services/job_service.js @@ -383,6 +383,7 @@ class JobService { delete tempJob.datafeed_config.state; delete tempJob.datafeed_config.node; delete tempJob.datafeed_config.timing_stats; + delete tempJob.datafeed_config.assignment_explanation; // remove query_delay if it's between 60s and 120s // the back-end produces a random value between 60 and 120 and so @@ -585,6 +586,7 @@ class JobService { const data = { index: job.datafeed_config.indices, body, + ...(job.datafeed_config.indices_options || {}), }; ml.esSearch(data) diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts index df59678452e2f..3be8679830423 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts @@ -535,7 +535,7 @@ export const ml = { }); }, - calculateModelMemoryLimit({ + calculateModelMemoryLimit$({ analysisConfig, indexPattern, query, @@ -559,7 +559,7 @@ export const ml = { latestMs, }); - return http<{ modelMemoryLimit: string }>({ + return http$<{ modelMemoryLimit: string }>({ path: `${basePath()}/validate/calculate_model_memory_limit`, method: 'POST', body, diff --git a/x-pack/plugins/ml/public/index.ts b/x-pack/plugins/ml/public/index.ts index f9f2be390e05f..8070f94a1264d 100755 --- a/x-pack/plugins/ml/public/index.ts +++ b/x-pack/plugins/ml/public/index.ts @@ -6,8 +6,19 @@ import { PluginInitializer } from 'kibana/public'; import './index.scss'; -import { MlPlugin, MlPluginSetup, MlPluginStart } from './plugin'; +import { + MlPlugin, + MlPluginSetup, + MlPluginStart, + MlSetupDependencies, + MlStartDependencies, +} from './plugin'; -export const plugin: PluginInitializer = () => new MlPlugin(); +export const plugin: PluginInitializer< + MlPluginSetup, + MlPluginStart, + MlSetupDependencies, + MlStartDependencies +> = () => new MlPlugin(); export { MlPluginSetup, MlPluginStart }; diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 30b7133f4147e..62b60f81b672f 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -14,6 +14,7 @@ import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SecurityPluginSetup } from '../../security/public'; import { LicensingPluginSetup } from '../../licensing/public'; import { initManagementSection } from './application/management'; +import { LicenseManagementUIPluginSetup } from '../../license_management/public'; import { setDependencyCache } from './application/util/dependency_cache'; import { PLUGIN_ID, PLUGIN_ICON } from '../common/constants/app'; @@ -26,10 +27,11 @@ export interface MlSetupDependencies { licensing: LicensingPluginSetup; management: ManagementSetup; usageCollection: UsageCollectionSetup; + licenseManagement?: LicenseManagementUIPluginSetup; } export class MlPlugin implements Plugin { - setup(core: CoreSetup, pluginsSetup: MlSetupDependencies) { + setup(core: CoreSetup, pluginsSetup: MlSetupDependencies) { core.application.register({ id: PLUGIN_ID, title: i18n.translate('xpack.ml.plugin.title', { @@ -50,6 +52,7 @@ export class MlPlugin implements Plugin { licensing: pluginsSetup.licensing, management: pluginsSetup.management, usageCollection: pluginsSetup.usageCollection, + licenseManagement: pluginsSetup.licenseManagement, }, { element: params.element, diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts index 30cf5a0d4e58f..bcdc58e61ad7c 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts @@ -8,8 +8,7 @@ import { APICaller, SavedObjectsClientContract } from 'kibana/server'; import { Module } from '../../../common/types/modules'; import { DataRecognizer } from '../data_recognizer'; -// FLAKY: https://github.com/elastic/kibana/issues/59541 -describe.skip('ML - data recognizer', () => { +describe('ML - data recognizer', () => { const dr = new DataRecognizer( jest.fn() as APICaller, ({ @@ -18,38 +17,6 @@ describe.skip('ML - data recognizer', () => { } as never) as SavedObjectsClientContract ); - const moduleIds = [ - 'apache_ecs', - 'apm_jsbase', - 'apm_nodejs', - 'apm_transaction', - 'auditbeat_process_docker_ecs', - 'auditbeat_process_hosts_ecs', - 'logs_ui_analysis', - 'logs_ui_categories', - 'metricbeat_system_ecs', - 'nginx_ecs', - 'sample_data_ecommerce', - 'sample_data_weblogs', - 'siem_auditbeat', - 'siem_auditbeat_auth', - 'siem_packetbeat', - 'siem_winlogbeat', - 'siem_winlogbeat_auth', - ]; - - // check all module IDs are the same as the list above - it('listModules - check all module IDs', async () => { - const modules = await dr.listModules(); - const ids = modules.map(m => m.id); - expect(ids.join()).toEqual(moduleIds.join()); - }); - - it('getModule - load a single module', async () => { - const module = await dr.getModule(moduleIds[0]); - expect(module.id).toEqual(moduleIds[0]); - }); - describe('jobOverrides', () => { it('should apply job overrides correctly', () => { // arrange diff --git a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts index 6002bb218c41b..22c3d94dfb29e 100644 --- a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts +++ b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts @@ -35,10 +35,13 @@ const customUrlSchema = { time_range: schema.maybe(schema.any()), }; -const customSettingsSchema = schema.object({ - created_by: schema.maybe(schema.string()), - custom_urls: schema.maybe(schema.arrayOf(schema.maybe(schema.object({ ...customUrlSchema })))), -}); +const customSettingsSchema = schema.object( + { + created_by: schema.maybe(schema.string()), + custom_urls: schema.maybe(schema.arrayOf(schema.maybe(schema.object({ ...customUrlSchema })))), + }, + { unknowns: 'allow' } // Create / Update job API allows other fields to be added to custom_settings. +); export const anomalyDetectionUpdateJobSchema = { description: schema.maybe(schema.string()), diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js index c09a08f61dc0a..b90a9aa7d139a 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js @@ -6,7 +6,10 @@ import { defaultsDeep, uniq, compact, get } from 'lodash'; -import { TELEMETRY_COLLECTION_INTERVAL } from '../../common/constants'; +import { + TELEMETRY_COLLECTION_INTERVAL, + KIBANA_STATS_TYPE_MONITORING, +} from '../../common/constants'; import { sendBulkPayload, monitoringBulk } from './lib'; import { hasMonitoringCluster } from '../es_client/instantiate_client'; @@ -188,11 +191,18 @@ export class BulkUploader { ); } - getKibanaStats() { - return { + getKibanaStats(type) { + const stats = { ...this.kibanaStats, status: this.kibanaStatusGetter(), }; + + if (type === KIBANA_STATS_TYPE_MONITORING) { + delete stats.port; + delete stats.locale; + } + + return stats; } /* @@ -252,7 +262,7 @@ export class BulkUploader { ...accum, { index: { _type: type } }, { - kibana: this.getKibanaStats(), + kibana: this.getKibanaStats(type), ...typesNested[type], }, ]; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.ts index 00197e98948bf..85357f786ddc1 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.ts +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.ts @@ -5,6 +5,7 @@ */ import { Observable } from 'rxjs'; +import { cloneDeep } from 'lodash'; import moment from 'moment'; import { OpsMetrics } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; @@ -22,7 +23,15 @@ export function getOpsStatsCollector( metrics$: Observable ) { let lastMetrics: MonitoringOpsMetrics | null = null; - metrics$.subscribe(metrics => { + metrics$.subscribe(_metrics => { + const metrics: any = cloneDeep(_metrics); + // Ensure we only include the same data that Metricbeat collection would get + delete metrics.process.pid; + metrics.response_times = { + average: metrics.response_times.avg_in_millis, + max: metrics.response_times.max_in_millis, + }; + delete metrics.requests.statusCodes; lastMetrics = { ...metrics, timestamp: moment.utc().toISOString(), diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts index 63e1dbc400787..c66adfcabd671 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.ts @@ -12,9 +12,6 @@ import { MonitoringConfig } from '../../config'; * If so, get email from kibana.yml */ export async function getDefaultAdminEmail(config: MonitoringConfig) { - if (!config.cluster_alerts.email_notifications.enabled) { - return null; - } return config.cluster_alerts.email_notifications.email_address || null; } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js index c248ad743e0ec..d431ec47adbcb 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js @@ -84,7 +84,7 @@ export async function getNodes(req, esIndexPattern, pageOfNodes, clusterStats, n by_date: { date_histogram: { field: 'timestamp', - min_doc_count: 1, + min_doc_count: 0, fixed_interval: bucketSize + 's', }, aggs: getMetricAggs(LISTING_METRICS_NAMES, bucketSize), diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_paginated_pipelines.js b/x-pack/plugins/monitoring/server/lib/logstash/get_paginated_pipelines.js index 5ceb9536be2ae..81eca5bbff9cb 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_paginated_pipelines.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_paginated_pipelines.js @@ -118,6 +118,9 @@ async function getPaginatedThroughputData(pipelines, req, lsIndexPattern, throug for (const pipeline of pipelines) { if (pipelineAggregationData.id === pipeline.id) { const dataSeries = get(pipelineAggregationData, `metrics.${throughputMetric}.data`, [[]]); + if (dataSeries.length === 0) { + continue; + } pipeline[throughputMetric] = dataSeries.pop()[1]; } } diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index b8216f037eabb..24d8bcaa4397c 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -51,7 +51,6 @@ import { InfraPluginSetup } from '../../infra/server'; export interface LegacyAPI { getServerStatus: () => string; - infra: any; } interface PluginsSetup { @@ -189,8 +188,9 @@ export class Plugin { name: serverInfo.name, index: get(legacyConfig, 'kibana.index'), host: serverInfo.host, - transport_address: `${serverInfo.host}:${serverInfo.port}`, + locale: i18n.getLocale(), port: serverInfo.port.toString(), + transport_address: `${serverInfo.host}:${serverInfo.port}`, version: this.initializerContext.env.packageInfo.version, snapshot: snapshotRegex.test(this.initializerContext.env.packageInfo.version), }, @@ -224,7 +224,7 @@ export class Plugin { this.monitoringCore = this.getLegacyShim( config, legacyConfig, - core.getStartServices as () => Promise<[CoreStart, PluginsStart]>, + core.getStartServices as () => Promise<[CoreStart, PluginsStart, {}]>, this.licenseService, this.cluster ); @@ -293,7 +293,7 @@ export class Plugin { getLegacyShim( config: MonitoringConfig, legacyConfig: any, - getCoreServices: () => Promise<[CoreStart, PluginsStart]>, + getCoreServices: () => Promise<[CoreStart, PluginsStart, {}]>, licenseService: MonitoringLicenseService, cluster: ICustomClusterClient ): MonitoringCore { diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json index 57063ea729ed6..438b9ddea4734 100644 --- a/x-pack/plugins/observability/kibana.json +++ b/x-pack/plugins/observability/kibana.json @@ -2,5 +2,6 @@ "id": "observability", "version": "8.0.0", "kibanaVersion": "kibana", + "configPath": ["xpack", "observability"], "ui": true } diff --git a/x-pack/plugins/oss_telemetry/kibana.json b/x-pack/plugins/oss_telemetry/kibana.json index d83894f7c44a3..0defee0881e0e 100644 --- a/x-pack/plugins/oss_telemetry/kibana.json +++ b/x-pack/plugins/oss_telemetry/kibana.json @@ -4,5 +4,6 @@ "version": "8.0.0", "kibanaVersion": "kibana", "requiredPlugins": ["usageCollection", "taskManager"], + "configPath": ["xpack", "oss_telemetry"], "ui": false } diff --git a/x-pack/plugins/painless_lab/public/application/components/main.tsx b/x-pack/plugins/painless_lab/public/application/components/main.tsx index 10907536e9cc2..5aed3f25a51b9 100644 --- a/x-pack/plugins/painless_lab/public/application/components/main.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/main.tsx @@ -55,7 +55,7 @@ export const Main: React.FunctionComponent = () => { return (
- +

{i18n.translate('xpack.painlessLab.title', { diff --git a/x-pack/plugins/painless_lab/public/styles/_index.scss b/x-pack/plugins/painless_lab/public/styles/_index.scss index f68dbe302511a..cad0d8229524b 100644 --- a/x-pack/plugins/painless_lab/public/styles/_index.scss +++ b/x-pack/plugins/painless_lab/public/styles/_index.scss @@ -5,12 +5,17 @@ * This is a very brittle way of preventing the editor and other content from disappearing * behind the bottom bar. */ -$bottomBarHeight: calc(#{$euiSize} * 3); +$bottomBarHeight: calc(#{$euiSize} * 3); .painlessLabBottomBarPlaceholder { height: $bottomBarHeight } +.painlessLabLeftPane { + padding-top: $euiSizeM; + background-color: $euiColorEmptyShade; +} + .painlessLabRightPane { border-right: none; border-top: none; @@ -25,7 +30,7 @@ $bottomBarHeight: calc(#{$euiSize} * 3); flex-direction: column; height: 100%; - [role="tabpanel"] { + [role='tabpanel'] { height: 100%; overflow-y: auto; } diff --git a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts index 10b3dbbd9b452..a204bd44901b7 100644 --- a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts +++ b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts @@ -127,6 +127,41 @@ describe('cluster_serialization', () => { }); }); + it('should deserialize a cluster that contains a deprecated proxy address and is in cloud', () => { + expect( + deserializeCluster( + 'test_cluster', + { + seeds: ['localhost:9300'], + connected: true, + num_nodes_connected: 1, + max_connections_per_cluster: 3, + initial_connect_timeout: '30s', + skip_unavailable: false, + transport: { + ping_schedule: '-1', + compress: false, + }, + }, + 'localhost:9300', + true + ) + ).toEqual({ + name: 'test_cluster', + proxyAddress: 'localhost:9300', + mode: 'proxy', + hasDeprecatedProxySetting: true, + isConnected: true, + connectedNodesCount: 1, + maxConnectionsPerCluster: 3, + initialConnectTimeout: '30s', + skipUnavailable: false, + transportPingSchedule: '-1', + transportCompress: false, + serverName: 'localhost', + }); + }); + it('should deserialize a cluster object with arbitrary missing properties', () => { expect( deserializeCluster('test_cluster', { @@ -155,6 +190,38 @@ describe('cluster_serialization', () => { expect(() => serializeCluster('foo')).toThrowError(); }); + it('should serialize a cluster that has a deprecated proxy setting', () => { + expect( + serializeCluster({ + name: 'test_cluster', + proxyAddress: 'localhost:9300', + mode: 'proxy', + isConnected: true, + skipUnavailable: false, + proxySocketConnections: 18, + serverName: 'localhost', + hasDeprecatedProxySetting: true, + }) + ).toEqual({ + persistent: { + cluster: { + remote: { + test_cluster: { + mode: 'proxy', + proxy_socket_connections: 18, + proxy_address: 'localhost:9300', + skip_unavailable: false, + server_name: 'localhost', + proxy: null, + seeds: null, + node_connections: null, + }, + }, + }, + }, + }); + }); + it('should serialize a complete cluster object to only dynamic properties', () => { expect( serializeCluster({ @@ -167,13 +234,14 @@ describe('cluster_serialization', () => { skipUnavailable: false, transportPingSchedule: '-1', transportCompress: false, + mode: 'sniff', }) ).toEqual({ persistent: { cluster: { remote: { test_cluster: { - mode: null, + mode: 'sniff', node_connections: null, proxy_address: null, proxy_socket_connections: null, diff --git a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts index fbea311cdeefa..07dbe8da28d8a 100644 --- a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts +++ b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts @@ -6,7 +6,8 @@ import { PROXY_MODE } from '../constants'; -export interface ClusterEs { +// Values returned from ES GET /_remote/info +export interface ClusterInfoEs { seeds?: string[]; mode?: 'proxy' | 'sniff'; connected?: boolean; @@ -42,19 +43,23 @@ export interface Cluster { connectedSocketsCount?: number; hasDeprecatedProxySetting?: boolean; } -export interface ClusterPayload { + +interface ClusterPayloadEs { + skip_unavailable?: boolean | null; + mode?: 'sniff' | 'proxy' | null; + proxy_address?: string | null; + proxy_socket_connections?: number | null; + server_name?: string | null; + seeds?: string[] | null; + node_connections?: number | null; + proxy?: null; +} +// Payload expected from ES PUT /_cluster/settings +export interface ClusterSettingsPayloadEs { persistent: { cluster: { remote: { - [key: string]: { - skip_unavailable?: boolean | null; - mode?: 'sniff' | 'proxy' | null; - proxy_address?: string | null; - proxy_socket_connections?: number | null; - server_name?: string | null; - seeds?: string[] | null; - node_connections?: number | null; - }; + [key: string]: ClusterPayloadEs; }; }; }; @@ -62,8 +67,9 @@ export interface ClusterPayload { export function deserializeCluster( name: string, - esClusterObject: ClusterEs, - deprecatedProxyAddress?: string | undefined + esClusterObject: ClusterInfoEs, + deprecatedProxyAddress?: string | undefined, + isCloudEnabled?: boolean | undefined ): Cluster { if (!name || !esClusterObject || typeof esClusterObject !== 'object') { throw new Error('Unable to deserialize cluster'); @@ -112,12 +118,16 @@ export function deserializeCluster( // If a user has a remote cluster with the deprecated proxy setting, // we transform the data to support the new implementation and also flag the deprecation if (deprecatedProxyAddress) { + // Cloud-specific logic: Create default server name, since field doesn't exist in deprecated implementation + const defaultServerName = deprecatedProxyAddress.split(':')[0]; + deserializedClusterObject = { ...deserializedClusterObject, proxyAddress: deprecatedProxyAddress, seeds: undefined, hasDeprecatedProxySetting: true, mode: PROXY_MODE, + serverName: isCloudEnabled ? defaultServerName : undefined, }; } @@ -131,7 +141,7 @@ export function deserializeCluster( return deserializedClusterObject; } -export function serializeCluster(deserializedClusterObject: Cluster): ClusterPayload { +export function serializeCluster(deserializedClusterObject: Cluster): ClusterSettingsPayloadEs { if (!deserializedClusterObject || typeof deserializedClusterObject !== 'object') { throw new Error('Unable to serialize cluster'); } @@ -145,22 +155,31 @@ export function serializeCluster(deserializedClusterObject: Cluster): ClusterPay proxyAddress, proxySocketConnections, serverName, + hasDeprecatedProxySetting, } = deserializedClusterObject; + const clusterData: ClusterPayloadEs = { + skip_unavailable: typeof skipUnavailable === 'boolean' ? skipUnavailable : null, + mode: mode || null, + proxy_address: proxyAddress || null, + proxy_socket_connections: proxySocketConnections || null, + server_name: serverName || null, + seeds: seeds || null, + node_connections: nodeConnections || null, + }; + + // This is only applicable in edit mode + // In order to "upgrade" an existing remote cluster to use the new proxy mode settings, we need to set the old proxy setting to null + if (hasDeprecatedProxySetting) { + clusterData.proxy = null; + } + return { // Background on why we only save as persistent settings detailed here: https://github.com/elastic/kibana/pull/26067#issuecomment-441848124 persistent: { cluster: { remote: { - [name]: { - skip_unavailable: skipUnavailable !== undefined ? skipUnavailable : null, - mode: mode ?? null, - proxy_address: proxyAddress ?? null, - proxy_socket_connections: proxySocketConnections ?? null, - server_name: serverName ?? null, - seeds: seeds ?? null, - node_connections: nodeConnections ?? null, - }, + [name]: clusterData, }, }, }, diff --git a/x-pack/plugins/remote_clusters/common/lib/index.ts b/x-pack/plugins/remote_clusters/common/lib/index.ts index 52a0536bfd55b..43cf004becff9 100644 --- a/x-pack/plugins/remote_clusters/common/lib/index.ts +++ b/x-pack/plugins/remote_clusters/common/lib/index.ts @@ -4,4 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export { deserializeCluster, serializeCluster, Cluster, ClusterEs } from './cluster_serialization'; +export { + deserializeCluster, + serializeCluster, + Cluster, + ClusterInfoEs, +} from './cluster_serialization'; diff --git a/x-pack/plugins/remote_clusters/kibana.json b/x-pack/plugins/remote_clusters/kibana.json index 8922bf621aa03..f1b9d20f762d3 100644 --- a/x-pack/plugins/remote_clusters/kibana.json +++ b/x-pack/plugins/remote_clusters/kibana.json @@ -11,7 +11,8 @@ "indexManagement" ], "optionalPlugins": [ - "usageCollection" + "usageCollection", + "cloud" ], "server": true, "ui": true diff --git a/x-pack/plugins/remote_clusters/public/application/app_context.tsx b/x-pack/plugins/remote_clusters/public/application/app_context.tsx new file mode 100644 index 0000000000000..86c0b401d416d --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/app_context.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { createContext } from 'react'; + +export interface Context { + isCloudEnabled: boolean; +} + +export const AppContext = createContext({} as any); + +export const AppContextProvider = ({ + children, + context, +}: { + children: React.ReactNode; + context: Context; +}) => { + return {children}; +}; diff --git a/x-pack/plugins/remote_clusters/public/application/index.d.ts b/x-pack/plugins/remote_clusters/public/application/index.d.ts index b5c5ad5522134..b021dca51bacd 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.d.ts +++ b/x-pack/plugins/remote_clusters/public/application/index.d.ts @@ -8,5 +8,8 @@ import { RegisterManagementAppArgs, I18nStart } from '../types'; export declare const renderApp: ( elem: HTMLElement | null, - I18nContext: I18nStart['Context'] + I18nContext: I18nStart['Context'], + appDependencies: { + isCloudEnabled?: boolean; + } ) => ReturnType; diff --git a/x-pack/plugins/remote_clusters/public/application/index.js b/x-pack/plugins/remote_clusters/public/application/index.js index 0b8b26ace5daa..f2d788c741342 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.js +++ b/x-pack/plugins/remote_clusters/public/application/index.js @@ -11,14 +11,17 @@ import { Provider } from 'react-redux'; import { App } from './app'; import { remoteClustersStore } from './store'; +import { AppContextProvider } from './app_context'; -export const renderApp = (elem, I18nContext) => { +export const renderApp = (elem, I18nContext, appDependencies) => { render( - - - + + + + + , elem diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap index 6ff8c538ca89c..4c109c557fdb0 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap @@ -5,7 +5,6 @@ exports[`RemoteClusterForm proxy mode renders correct connection settings when u disabledFields={Object {}} fields={ Object { - "mode": "sniff", "name": "", "nodeConnections": 3, "proxyAddress": "", @@ -805,6 +804,7 @@ exports[`RemoteClusterForm proxy mode renders correct connection settings when u data-test-subj="remoteClusterFormServerNameFormRow" describedByIds={Array []} display="row" + error={null} fullWidth={true} hasChildLabel={true} hasEmptyLabelSpace={false} @@ -827,10 +827,11 @@ exports[`RemoteClusterForm proxy mode renders correct connection settings when u } /> } + isInvalid={false} label={ } @@ -845,18 +846,21 @@ exports[`RemoteClusterForm proxy mode renders correct connection settings when u className="euiFormRow__labelWrapper" >