diff --git a/.backportrc.json b/.backportrc.json index af064451595c8..77456cf33f625 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -1,5 +1,5 @@ { "upstream": "elastic/kibana", - "branches": [{ "name": "7.x", "checked": true }, "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.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/.eslintignore b/.eslintignore index 90155ca9cb681..e5b17567b562c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,7 +9,7 @@ bower_components /built_assets /html_docs /src/plugins/data/common/es_query/kuery/ast/_generated_/** -/src/fixtures/vislib/mock_data +src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data /src/legacy/ui/public/angular-bootstrap /src/legacy/ui/public/flot-charts /test/fixtures/scenarios diff --git a/.eslintrc.js b/.eslintrc.js index a7bb204da4775..2c5804da053a6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -77,7 +77,7 @@ module.exports = { }, }, { - files: ['src/legacy/core_plugins/kbn_vislib_vis_types/**/*.{js,ts,tsx}'], + files: ['src/legacy/core_plugins/vis_type_vislib/**/*.{js,ts,tsx}'], rules: { 'react-hooks/exhaustive-deps': 'off', }, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index acfb7307f49c4..ed5721e8756e8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -117,21 +117,21 @@ /x-pack/test/api_integration/apis/security/ @elastic/kibana-security # Kibana Localization -/src/dev/i18n @elastic/kibana-localization +/src/dev/i18n/ @elastic/kibana-localization # Pulse /packages/kbn-analytics/ @elastic/pulse /src/legacy/core_plugins/ui_metric/ @elastic/pulse /src/plugins/usage_collection/ @elastic/pulse -/x-pack/legacy/plugins/telemetry @elastic/pulse +/x-pack/legacy/plugins/telemetry/ @elastic/pulse # Kibana Alerting Services -/x-pack/legacy/plugins/alerting @elastic/kibana-alerting-services -/x-pack/legacy/plugins/actions @elastic/kibana-alerting-services -/x-pack/legacy/plugins/task_manager @elastic/kibana-alerting-services -/x-pack/test/alerting_api_integration @elastic/kibana-alerting-services -/x-pack/test/plugin_api_integration/plugins/task_manager @elastic/kibana-alerting-services -/x-pack/test/plugin_api_integration/test_suites/task_manager @elastic/kibana-alerting-services +/x-pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services +/x-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services +/x-pack/plugins/task_manager/ @elastic/kibana-alerting-services +/x-pack/test/alerting_api_integration/ @elastic/kibana-alerting-services +/x-pack/test/plugin_api_integration/plugins/task_manager/ @elastic/kibana-alerting-services +/x-pack/test/plugin_api_integration/test_suites/task_manager/ @elastic/kibana-alerting-services /x-pack/legacy/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services diff --git a/.i18nrc.json b/.i18nrc.json index 4bc0f773ee8b5..6986d36e8e94f 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -21,7 +21,7 @@ "interpreter": "src/legacy/core_plugins/interpreter", "kbn": "src/legacy/core_plugins/kibana", "kbnDocViews": "src/legacy/core_plugins/kbn_doc_views", - "kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types", + "kbnVislibVisTypes": "src/legacy/core_plugins/vis_type_vislib", "management": ["src/legacy/core_plugins/management", "src/plugins/management"], "kibana_react": "src/legacy/core_plugins/kibana_react", "kibana-react": "src/plugins/kibana_react", diff --git a/.sass-lint.yml b/.sass-lint.yml index f6c0f5bb83fcb..fba2c003484f6 100644 --- a/.sass-lint.yml +++ b/.sass-lint.yml @@ -2,7 +2,7 @@ files: include: - 'src/legacy/core_plugins/metrics/**/*.s+(a|c)ss' - 'src/legacy/core_plugins/timelion/**/*.s+(a|c)ss' - - 'src/legacy/ui/public/vislib/**/*.s+(a|c)ss' + - 'src/legacy/core_plugins/vis_type_vislib/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/rollup/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss' diff --git a/docs/maps/images/gs_add_cloropeth_layer.png b/docs/maps/images/gs_add_cloropeth_layer.png index b2ee35f025b6f..2800a5a2d2584 100644 Binary files a/docs/maps/images/gs_add_cloropeth_layer.png and b/docs/maps/images/gs_add_cloropeth_layer.png differ diff --git a/docs/maps/images/gs_add_es_layer.png b/docs/maps/images/gs_add_es_layer.png deleted file mode 100644 index b80ddc47d7e5d..0000000000000 Binary files a/docs/maps/images/gs_add_es_layer.png and /dev/null differ diff --git a/docs/maps/images/sample_data_web_logs.png b/docs/maps/images/sample_data_web_logs.png index dda0926a07dfe..3b0c2ba3f12c0 100644 Binary files a/docs/maps/images/sample_data_web_logs.png and b/docs/maps/images/sample_data_web_logs.png differ diff --git a/docs/maps/maps-getting-started.asciidoc b/docs/maps/maps-getting-started.asciidoc index e6908ca773a2f..34ed79c736b2e 100644 --- a/docs/maps/maps-getting-started.asciidoc +++ b/docs/maps/maps-getting-started.asciidoc @@ -68,14 +68,16 @@ and lighter shades symbolize countries with less traffic. . Click the *EMS Boundaries* data source. . From the *Layer* dropdown menu, select *World Countries*. . Click the *Add layer* button. -. Set *Layer name* to `Total Requests by Country`. -. Set *Layer transparency* to 0.5. +. Set *Name* to `Total Requests by Country`. +. Set *Opacity* to 50%. +. Click *Add* under *Tooltip fields*. +. In the popover, select *ISO 3166-1 alpha-2 code* and *name* and click *Add*. ===== Join the vector layer with the sample web log index You now have a vector layer containing the world countries. To symbolize countries by web traffic, you'll need to augment the world country features with the count of Elasticsearch weblog documents originating from each country. -To do this, you'll create a <> to link the vector source *World Countries* to +To do this, you'll create a <> to link the vector source *World Countries* to the {es} index `kibana_sample_data_logs` on the shared key iso2 = geo.src. . Click plus image:maps/images/gs_plus_icon.png[] to the right of *Term Joins* label. @@ -83,15 +85,18 @@ the {es} index `kibana_sample_data_logs` on the shared key iso2 = geo.src. . Set *Left field* to *ISO 3166-1 alpha-2 code*. . Set *Right source* to *kibana_sample_data_logs*. . Set *Right field* to *geo.src*. +. Click *and use metric count*. +. Set *Custom label* to *web logs count*. ===== Set the layer style All of the world countries are still a single color because the layer is using <>. To shade the world countries based on which country is sending the most requests, you'll need to use <>. -. Click image:maps/images/gs_link_icon.png[] to the right of *Fill color*. +. Under *Fill color*, change the selected value from *Solid* to *By value*. +. In the field select input, select *web logs count*. . Select the grey color ramp. -. In the field select input, select *count of kibana_sample_data_logs:geo.src*. +. Under *Border color*, change the selected color to *white*. . Click *Save & close*. + Your map now looks like this: @@ -119,9 +124,11 @@ The layer is only visible when users zoom in the map past zoom level 9. . Click the *Documents* data source. . Set *Index pattern* to *kibana_sample_data_logs*. . Click the *Add layer* button. -. Set *Layer name* to `Actual Requests`. -. Set *Zoom range for layer visibility* to the range [9, 24]. -. Set *Layer transparency* to 1. +. Set *Name* to `Actual Requests`. +. Set *Visibilty* to the range [9, 24]. +. Set *Opacity* to 100%. +. Click *Add* under *Tooltip fields*. +. In the popover, select *clientip*, *timestamp*, *host*, *request*, *response*, *machine.os*, *agent*, and *bytes* and click *Add*. . Set *Fill color* to *#2200ff*. . Click *Save & close*. + @@ -152,28 +159,28 @@ image::maps/images/grid_metrics_both.png[] . Set *Index pattern* to *kibana_sample_data_logs*. . Set *Show as* to *points*. . Click the *Add layer* button. -. Set *Layer name* to `Total Requests and Bytes`. -. Set *Zoom range for layer visibility* to the range [0, 9]. -. Set *Layer transparency* to 1. +. Set *Name* to `Total Requests and Bytes`. +. Set *Visibility* to the range [0, 9]. +. Set *Opacity* to 100%. ===== Configure the aggregation metrics -. Click plus image:maps/images/gs_plus_icon.png[] to the right of *Metrics* label. +. Click *Add metric* under of *Metrics* label. . Select *Sum* in the aggregation select. . Select *bytes* in the field select. ===== Set the layer style . In *Layer style*, change *Symbol size*: - .. Set *Min size* to 1. + .. Set *Min size* to 7. .. Set *Max size* to 25. - .. In the field select, select *sum of bytes*. + .. Change the field select from *count* to *sum of bytes*. . Click *Save & close* button. + Your map now looks like this between zoom levels 0 and 9: + [role="screenshot"] -image::maps/images/gs_add_es_layer.png[] +image::maps/images/sample_data_web_logs.png[] [role="xpack"] [[maps-save]] diff --git a/docs/user/security/images/mutual-tls-role-mapping.png b/docs/user/security/images/mutual-tls-role-mapping.png new file mode 100644 index 0000000000000..d95ce41e130c2 Binary files /dev/null and b/docs/user/security/images/mutual-tls-role-mapping.png differ diff --git a/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc b/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc new file mode 100644 index 0000000000000..1c7e7080e676b --- /dev/null +++ b/docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc @@ -0,0 +1,120 @@ +[role="xpack"] +[[elasticsearch-mutual-tls]] +=== Mutual TLS authentication between {kib} and {es} +++++ +Mutual TLS with {es} +++++ + +In a standard Transport Layer Security (TLS/SSL) configuration, the server presents a signed certificate to authenticate itself to the +client. In a mutual TLS configuration, the client also presents a signed certificate to authenticate itself to the server. + +When {security} is enabled on your cluster, each request that {kib} makes to {es} must be authenticated. Most requests made through {kib} to +{es} are authenticated by using the credentials of the logged-in user. There are, however, a few internal requests that the {kib} server +needs to make to the {es} cluster. For this reason, you must configure credentials for the {kib} server to use for those requests. + +If {kib} has `elasticsearch.username` and `elasticsearch.password` configured, it will attempt to use these to authenticate to {es} via the +{ref}/native-realm.html[Native realm]. However, {kib} also supports mutual TLS authentication with {es} via a {ref}/pki-realm.html[Public +Key Infrastructure (PKI) realm]. To do so, {es} needs to verify the signature on the {kib} client certificate, and it also needs to map the +certificate's distinguished name (DN) to the appropriate `kibana_system` role. + +NOTE: Using a PKI realm is a gold feature. For a comparison of the Elastic license levels, see https://www.elastic.co/subscriptions[the +subscription page]. + +To configure {kib} and {es} to use mutual TLS authentication: + +. <> with a username and password. + +. <>. At a minimum, this requires a server certificate for {es}. + +. Create a client certificate and private key for {kib} to use when connecting to {es}. ++ +-- +NOTE: This is not the same as the <> that {kib} will present to web browsers. + +You may choose to generate a certificate and private key using {ref}/certutil.html[the {es} certutil tool]. At this point, you will have +already set up a certificate authority (CA) to sign the {es} server certificate. You may choose to use the same CA to sign the {kib} client +certificate. You would do this like so: + +[source,sh] +-------------------------------------------------------------------------------- +bin/elasticsearch-certutil cert -ca elastic-stack-ca.p12 -name kibana-client +-------------------------------------------------------------------------------- + +This will generate a certificate and private key in a PKCS #12 keystore named `kibana-client.p12`. The certificate has a Common Name (CN) of +"kibana-client". + +You will also need to use the CA certificate when setting up the PKI realm in {es}. While you could use the CA keystore in the above example +for this purpose, it is bad practice to expose the CA's private key in such a manner. Instead, you can extract the CA certificate (without +its private key) like so: + +[source,sh] +-------------------------------------------------------------------------------- +openssl pkcs12 -in kibana-client.p12 -cacerts -nokeys -out ca.crt +-------------------------------------------------------------------------------- +-- + +. Configure a PKI realm and a Native realm in your {es} cluster: ++ +-- +By default, {es} provides a Native realm. However, to support both a PKI realm (for {kib}) and a Native realm (for end users), you must +configure each realm in `elasticsearch.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +xpack.security.authc.realms.pki.realm1.order: 1 +xpack.security.authc.realms.pki.realm1.certificate_authorities: "/path/to/ca.crt" +xpack.security.authc.realms.native.realm2.order: 2 +-------------------------------------------------------------------------------- + +-- + +. Configure your {es} cluster to request client certificates: ++ +-- +By default, {es} will not request a client certificate when establishing a TLS connection. To change this, you must set up optional client +certificate authentication in `elasticsearch.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +xpack.security.http.ssl.client_authentication: "optional" +-------------------------------------------------------------------------------- +-- + +. Restart your {es} cluster. + +. Use {kib} to create a <> for your new client certificate: ++ +-- +This role mapping will assign the `kibana_system` role to any user that matches the included mapping rule, which is set to equal the client +certificate's DN attribute: + +[role="screenshot"] +image:user/security/images/mutual-tls-role-mapping.png["Role mapping for the {kib} client certificate"] +-- + +. Configure {kib} to use the client certificate: ++ +-- +Assuming you used the {es} certutil tool to generate a certificate and private key in a PKCS #12 keystore, add the following values to +`kibana.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +elasticsearch.ssl.keystore.path: "/path/to/kibana-client.p12" +elasticsearch.ssl.keystore.password: "decryption password" +-------------------------------------------------------------------------------- + +The decryption password should match what you entered when prompted by the {es} certutil tool. + +You must also remove the `elasticsearch.username` and `elasticsearch.password` values from the configuration file. Otherwise, {kib} will +attempt to use those to authenticate via the Native realm. + +TIP: Alternatively, {kib} also supports using a client certificate and private key in PEM format with the `elasticsearch.ssl.certificate` +and `elasticsearch.ssl.key` settings. For more information, see <>. +-- + +. Restart {kib}. + +NOTE: The steps above enable {kib} to authenticate to {es} using a certificate. However, end users will only be able to authenticate to +{kib} with a username and password. To allow end users to authenticate to {kib} using certificates, see <>. diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc index a68a2ee285ee3..2d07b57bfabe1 100644 --- a/docs/user/security/securing-kibana.asciidoc +++ b/docs/user/security/securing-kibana.asciidoc @@ -88,6 +88,8 @@ xpack.security.session.lifespan: "8h" . Optional: <>. +. Optional: <>. + . Restart {kib}. . [[kibana-roles]]Choose an authentication mechanism and grant users the privileges they need to @@ -141,4 +143,5 @@ NOTE: This must be a user who has been assigned < = ({ fetchStreaming }) => { + const isMounted = useMountedState(); + const [data, setData] = useState(5); + const [showingResults, setShowingResults] = useState(false); + const [results, { push: pushResult, clear: clearList }] = useList([]); + const [completed, setCompleted] = useState(false); + const [error, setError] = useState(null); + + const handleSubmit = () => { + setShowingResults(true); + const { stream } = fetchStreaming({ + url: '/bfetch_explorer/count', + body: JSON.stringify({ data }), + }); + stream.subscribe({ + next: (next: string) => { + if (!isMounted()) return; + pushResult(next); + }, + error: (nextError: any) => { + if (!isMounted()) return; + setError(nextError); + }, + complete: () => { + if (!isMounted()) return; + setCompleted(true); + }, + }); + }; + + const handleReset = () => { + setShowingResults(false); + clearList(); + setError(null); + setCompleted(false); + }; + + if (showingResults) { + return ( + +
{JSON.stringify(error || results, null, 4)}
+ + + Reset + +
+ ); + } + + return ( + + + setData(Number(e.target.value))} + /> + + + Start + + + ); +}; diff --git a/examples/bfetch_explorer/public/components/double_integers/index.tsx b/examples/bfetch_explorer/public/components/double_integers/index.tsx new file mode 100644 index 0000000000000..d8fbe33ec73be --- /dev/null +++ b/examples/bfetch_explorer/public/components/double_integers/index.tsx @@ -0,0 +1,105 @@ +/* + * 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, { useState } from 'react'; +import useMountedState from 'react-use/lib/useMountedState'; +import useList from 'react-use/lib/useList'; +import useCounter from 'react-use/lib/useCounter'; +import { EuiForm, EuiSpacer, EuiTextArea, EuiFormRow, EuiButton } from '@elastic/eui'; +import { ExplorerService } from '../../plugin'; + +interface ResultItem { + num: number; + result?: { + num: number; + }; + error?: any; +} + +const defaultNumbers = [2000, 300, -1, 1000].join('\n'); + +export interface Props { + double: ExplorerService['double']; +} + +export const DoubleIntegers: React.FC = ({ double }) => { + const isMounted = useMountedState(); + const [numbers, setNumbers] = useState(defaultNumbers); + const [showingResults, setShowingResults] = useState(false); + const [numberOfResultsAwaiting, counter] = useCounter(0); + const [results, { push: pushResult, clear: clearList }] = useList([]); + + const handleSubmit = () => { + setShowingResults(true); + const nums = numbers + .split('\n') + .map(num => num.trim()) + .filter(Boolean) + .map(Number); + counter.set(nums.length); + nums.forEach(num => { + double({ num }).then( + result => { + if (!isMounted()) return; + counter.dec(); + pushResult({ num, result }); + }, + error => { + if (!isMounted()) return; + counter.dec(); + pushResult({ num, error }); + } + ); + }); + }; + + const handleReset = () => { + setShowingResults(false); + counter.reset(); + clearList(); + }; + + if (showingResults) { + return ( + +
{JSON.stringify(results, null, 4)}
+ + + Reset + +
+ ); + } + + return ( + + + setNumbers(e.target.value)} + /> + + + Send + + + ); +}; diff --git a/examples/bfetch_explorer/public/components/page/index.tsx b/examples/bfetch_explorer/public/components/page/index.tsx new file mode 100644 index 0000000000000..0e7855178a884 --- /dev/null +++ b/examples/bfetch_explorer/public/components/page/index.tsx @@ -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 React from 'react'; +import { + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageHeader, + EuiPageHeaderSection, + EuiTitle, +} from '@elastic/eui'; + +export interface PageProps { + title?: React.ReactNode; +} + +export const Page: React.FC = ({ title = 'Untitled', children }) => { + return ( + + + + +

{title}

+
+
+
+ + + {children} + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/index.tsx b/examples/bfetch_explorer/public/containers/app/index.tsx new file mode 100644 index 0000000000000..a448c9e4f3a6a --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/index.tsx @@ -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 React from 'react'; +import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; +import { EuiPage } from '@elastic/eui'; +import { useDeps } from '../../hooks/use_deps'; +import { Sidebar } from './sidebar'; +import { routes } from '../../routes'; + +export const App: React.FC = () => { + const { appBasePath } = useDeps(); + + const routeElements: React.ReactElement[] = []; + for (const { items } of routes) { + for (const { id, component } of items) { + routeElements.push( component} />); + } + } + + return ( + + + + + {routeElements} + + + + + ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx b/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx new file mode 100644 index 0000000000000..7b4eac6eea44c --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx @@ -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. + */ + +import * as React from 'react'; +import { EuiPanel, EuiText } from '@elastic/eui'; +import { CountUntil } from '../../../../components/count_until'; +import { Page } from '../../../../components/page'; +import { useDeps } from '../../../../hooks/use_deps'; + +// eslint-disable-next-line +export interface Props {} + +export const PageCountUntil: React.FC = () => { + const { plugins } = useDeps(); + + return ( + + + This demo sends a single number N using fetchStreaming to the server. The + server will stream back N number of messages with 1 second delay each containing a number + from 1 to N, after which it will close the stream. + +
+ + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx b/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx new file mode 100644 index 0000000000000..7bd5feb836674 --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx @@ -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. + */ + +import * as React from 'react'; +import { EuiPanel, EuiText } from '@elastic/eui'; +import { DoubleIntegers } from '../../../../components/double_integers'; +import { Page } from '../../../../components/page'; +import { useDeps } from '../../../../hooks/use_deps'; + +// eslint-disable-next-line +export interface Props {} + +export const PageDoubleIntegers: React.FC = () => { + const { explorer } = useDeps(); + + return ( + + + Below is a list of numbers in milliseconds. They are sent as a batch to the server. For each + number server waits given number of milliseconds then doubles the number and streams it + back. + +
+ + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx new file mode 100644 index 0000000000000..cc50698e05908 --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx @@ -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 React from 'react'; +import { EuiPageSideBar, EuiSideNav } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; +import { routes } from '../../../routes'; + +// eslint-disable-next-line +interface SidebarProps {} + +export const Sidebar: React.FC = () => { + const history = useHistory(); + + return ( + + ({ + id, + name: title, + isSelected: true, + items: items.map(route => ({ + id: route.id, + name: route.title, + onClick: () => history.push(`/${route.id}`), + 'data-test-subj': route.id, + })), + })), + }, + ]} + /> + + ); +}; diff --git a/examples/bfetch_explorer/public/hooks/use_deps.ts b/examples/bfetch_explorer/public/hooks/use_deps.ts new file mode 100644 index 0000000000000..c68b4e759c21c --- /dev/null +++ b/examples/bfetch_explorer/public/hooks/use_deps.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useKibana } from '../../../../src/plugins/kibana_react/public'; +import { BfetchDeps } from '../mount'; + +export const useDeps = () => useKibana().services as BfetchDeps; diff --git a/src/legacy/core_plugins/interpreter/public/canvas/consts.ts b/examples/bfetch_explorer/public/index.ts similarity index 86% rename from src/legacy/core_plugins/interpreter/public/canvas/consts.ts rename to examples/bfetch_explorer/public/index.ts index 2600ada36afdc..76d0a1d1c6334 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/consts.ts +++ b/examples/bfetch_explorer/public/index.ts @@ -17,5 +17,6 @@ * under the License. */ -// The server endpoint for retrieiving and running Canvas functions. -export const FUNCTIONS_URL = '/api/interpreter/fns'; +import { BfetchExplorerPlugin } from './plugin'; + +export const plugin = () => new BfetchExplorerPlugin(); diff --git a/examples/bfetch_explorer/public/mount.tsx b/examples/bfetch_explorer/public/mount.tsx new file mode 100644 index 0000000000000..5ad53ef4a1988 --- /dev/null +++ b/examples/bfetch_explorer/public/mount.tsx @@ -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 * as React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { CoreSetup, CoreStart, AppMountParameters } from 'kibana/public'; +import { KibanaContextProvider } from '../../../src/plugins/kibana_react/public'; +import { BfetchExplorerStartPlugins, ExplorerService } from './plugin'; +import { App } from './containers/app'; + +export interface BfetchDeps { + appBasePath: string; + core: CoreStart; + plugins: BfetchExplorerStartPlugins; + explorer: ExplorerService; +} + +export const mount = ( + coreSetup: CoreSetup, + explorer: ExplorerService +) => async ({ appBasePath, element }: AppMountParameters) => { + const [core, plugins] = await coreSetup.getStartServices(); + const deps: BfetchDeps = { appBasePath, core, plugins, explorer }; + const reactElement = ( + + + + ); + render(reactElement, element); + return () => unmountComponentAtNode(element); +}; diff --git a/examples/bfetch_explorer/public/plugin.tsx b/examples/bfetch_explorer/public/plugin.tsx new file mode 100644 index 0000000000000..3155354c91fd4 --- /dev/null +++ b/examples/bfetch_explorer/public/plugin.tsx @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Plugin, CoreSetup } from 'kibana/public'; +import { BfetchPublicSetup, BfetchPublicStart } from '../../../src/plugins/bfetch/public'; +import { mount } from './mount'; + +export interface ExplorerService { + double: (number: { num: number }) => Promise<{ num: number }>; +} + +export interface BfetchExplorerSetupPlugins { + bfetch: BfetchPublicSetup; +} + +export interface BfetchExplorerStartPlugins { + bfetch: BfetchPublicStart; +} + +export class BfetchExplorerPlugin implements Plugin { + public setup(core: CoreSetup, plugins: BfetchExplorerSetupPlugins) { + const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ + url: '/bfetch_explorer/double', + }); + + const explorer: ExplorerService = { + double, + }; + + core.application.register({ + id: 'bfetch-explorer', + title: 'bfetch explorer', + mount: mount(core, explorer), + }); + } + + public start() {} + public stop() {} +} diff --git a/src/legacy/ui/public/vis/editors/default/schemas.d.ts b/examples/bfetch_explorer/public/routes.tsx similarity index 51% rename from src/legacy/ui/public/vis/editors/default/schemas.d.ts rename to examples/bfetch_explorer/public/routes.tsx index 236421f30fb09..2008811d75795 100644 --- a/src/legacy/ui/public/vis/editors/default/schemas.d.ts +++ b/examples/bfetch_explorer/public/routes.tsx @@ -17,21 +17,43 @@ * under the License. */ -import { AggParam } from '../../../agg_types'; -import { AggGroupNames } from './agg_groups'; -import { AggControlProps } from './controls/agg_control_props'; +import React from 'react'; +import { PageDoubleIntegers } from './containers/app/pages/page_double_integers'; +import { PageCountUntil } from './containers/app/pages/page_count_until'; -export interface Schema { - aggFilter: string | string[]; - editor: boolean | string; - group: AggGroupNames; - max: number; - min: number; - name: string; - params: AggParam[]; +interface RouteSectionDef { title: string; - defaults: unknown; - hideCustomLabel?: boolean; - mustBeFirst?: boolean; - editorComponent?: React.ComponentType; + id: string; + items: RouteDef[]; } + +interface RouteDef { + title: string; + id: string; + component: React.ReactNode; +} + +export const routes: RouteSectionDef[] = [ + { + title: 'fetchStreaming', + id: 'fetchStreaming', + items: [ + { + title: 'Count until', + id: 'count-until', + component: , + }, + ], + }, + { + title: 'batchedFunction', + id: 'batchedFunction', + items: [ + { + title: 'Double integers', + id: 'double-integers', + component: , + }, + ], + }, +]; diff --git a/src/legacy/core_plugins/interpreter/server/routes/index.ts b/examples/bfetch_explorer/server/index.ts similarity index 85% rename from src/legacy/core_plugins/interpreter/server/routes/index.ts rename to examples/bfetch_explorer/server/index.ts index 50385147dd38e..76d0a1d1c6334 100644 --- a/src/legacy/core_plugins/interpreter/server/routes/index.ts +++ b/examples/bfetch_explorer/server/index.ts @@ -17,8 +17,6 @@ * under the License. */ -import { registerServerFunctions } from './server_functions'; +import { BfetchExplorerPlugin } from './plugin'; -export function routes(server: any) { - registerServerFunctions(server); -} +export const plugin = () => new BfetchExplorerPlugin(); diff --git a/examples/bfetch_explorer/server/plugin.ts b/examples/bfetch_explorer/server/plugin.ts new file mode 100644 index 0000000000000..bf3b7f50ca6c8 --- /dev/null +++ b/examples/bfetch_explorer/server/plugin.ts @@ -0,0 +1,68 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subject } from 'rxjs'; +import { Plugin, CoreSetup, CoreStart } from '../../../src/core/server'; +import { BfetchServerSetup, BfetchServerStart } from '../../../src/plugins/bfetch/server'; + +export interface BfetchExplorerSetupPlugins { + bfetch: BfetchServerSetup; +} + +export interface BfetchExplorerStartPlugins { + bfetch: BfetchServerStart; +} + +export class BfetchExplorerPlugin implements Plugin { + public setup(core: CoreSetup, plugins: BfetchExplorerSetupPlugins) { + plugins.bfetch.addStreamingResponseRoute('/bfetch_explorer/count', () => ({ + getResponseStream: ({ data }: any) => { + const subject = new Subject(); + const countTo = Number(data); + for (let cnt = 1; cnt <= countTo; cnt++) { + setTimeout(() => { + subject.next(String(cnt)); + }, cnt * 1000); + } + setTimeout(() => { + subject.complete(); + }, countTo * 1000); + return subject; + }, + })); + + plugins.bfetch.addBatchProcessingRoute<{ num: number }, { num: number }>( + '/bfetch_explorer/double', + () => ({ + onBatchItem: async ({ num }) => { + // Validate inputs. + if (num < 0) throw new Error('Invalid number'); + // Wait number of specified milliseconds. + await new Promise(r => setTimeout(r, num)); + // Double the number and send it back. + return { num: 2 * num }; + }, + }) + ); + } + + public start(core: CoreStart, plugins: BfetchExplorerStartPlugins) {} + + public stop() {} +} diff --git a/examples/bfetch_explorer/tsconfig.json b/examples/bfetch_explorer/tsconfig.json new file mode 100644 index 0000000000000..d508076b33199 --- /dev/null +++ b/examples/bfetch_explorer/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../typings/**/*", + ], + "exclude": [] +} diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 12779efe7f869..e5493df0aecf7 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -120,7 +120,7 @@ export const TEMPORARILY_IGNORED_PATHS = [ 'src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/seriesList.js', '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/fixtures/vislib/mock_data/terms/_seriesMultiple.js', + 'src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_seriesMultiple.js', 'src/legacy/ui/public/angular-bootstrap/bindHtml/bindHtml.js', 'src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html', 'src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html', diff --git a/src/dev/register_git_hook/register_git_hook.js b/src/dev/register_git_hook/register_git_hook.js index 99ae351fe383e..8820327d3adc0 100644 --- a/src/dev/register_git_hook/register_git_hook.js +++ b/src/dev/register_git_hook/register_git_hook.js @@ -65,7 +65,7 @@ function getKbnPrecommitGitHookScript(rootPath, nodeHome, platform) { # The correct exit code on that situation # according the linux documentation project is 130 # https://www.tldp.org/LDP/abs/html/exitcodes.html - trap "exit 130" SIGINT + trap "exit 130" INT has_node() { command -v node >/dev/null 2>&1 diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 8213bdeeea2da..1dce53b6c2a84 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -18,6 +18,7 @@ */ export const storybookAliases = { + apm: 'x-pack/legacy/plugins/apm/scripts/storybook.js', canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js', embeddable: 'src/plugins/embeddable/scripts/storybook.js', infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js', diff --git a/src/legacy/core_plugins/interpreter/init.ts b/src/legacy/core_plugins/interpreter/init.ts index 768d76fbf744e..46da1539afadb 100644 --- a/src/legacy/core_plugins/interpreter/init.ts +++ b/src/legacy/core_plugins/interpreter/init.ts @@ -22,35 +22,10 @@ // @ts-ignore import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common'; -// @ts-ignore -import { routes } from './server/routes'; - -import { typeSpecs as types, Type } from '../../../plugins/expressions/common'; import { Legacy } from '../../../../kibana'; -export class TypesRegistry extends Registry { - wrapper(obj: any) { - return new (Type as any)(obj); - } -} - -export class FunctionsRegistry extends Registry { - wrapper(obj: any) { - return new Fn(obj); - } -} - -export const registries = { - types: new TypesRegistry(), - serverFunctions: new FunctionsRegistry(), -}; - export async function init(server: Legacy.Server /* options */) { server.injectUiAppVars('canvas', () => { - register(registries, { - types, - }); - const config = server.config(); const basePath = config.get('server.basePath'); const reportingBrowserType = (() => { @@ -63,7 +38,9 @@ export async function init(server: Legacy.Server /* options */) { return { kbnIndex: config.get('kibana.index'), - serverFunctions: registries.serverFunctions.toArray(), + serverFunctions: (server.newPlatform.setup.plugins.expressions as any).__LEGACY + .registries() + .serverFunctions.toArray(), basePath, reportingBrowserType, }; @@ -71,7 +48,5 @@ export async function init(server: Legacy.Server /* options */) { // Expose server.plugins.interpreter.register(specs) and // server.plugins.interpreter.registries() (a getter). - server.expose(registryFactory(registries)); - - routes(server); + server.expose((server.newPlatform.setup.plugins.expressions as any).__LEGACY); } diff --git a/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts b/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts index 2c2f79b3d6f51..fed157846a1a1 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts +++ b/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts @@ -28,62 +28,6 @@ * server side, it should be respective function's internal implementation detail. */ -import { get, identity } from 'lodash'; -// @ts-ignore -import { npSetup, npStart } from 'ui/new_platform'; -import { FUNCTIONS_URL } from './consts'; -import { batchedFetch } from './batched_fetch'; +import { npSetup } from 'ui/new_platform'; -export function getType(node: any) { - if (node == null) return 'null'; - if (typeof node === 'object') { - if (!node.type) throw new Error('Objects must have a type property'); - return node.type; - } - return typeof node; -} - -export function serializeProvider(types: any) { - return { - serialize: provider('serialize'), - deserialize: provider('deserialize'), - }; - - function provider(key: any) { - return (context: any) => { - const type = getType(context); - const typeDef = types[type]; - const fn: any = get(typeDef, key) || identity; - return fn(context); - }; - } -} - -let cached: Promise | null = null; - -export const loadLegacyServerFunctionWrappers = async () => { - if (!cached) { - cached = (async () => { - const serverFunctionList = await npSetup.core.http.get(FUNCTIONS_URL); - const types = npSetup.plugins.expressions.__LEGACY.types.toJS(); - const { serialize } = serializeProvider(types); - const batch = batchedFetch({ - fetchStreaming: npStart.plugins.bfetch.fetchStreaming, - serialize, - }); - - // For every sever-side function, register a client-side - // function that matches its definition, but which simply - // calls the server-side function endpoint. - Object.keys(serverFunctionList).forEach(functionName => { - const fn = () => ({ - ...serverFunctionList[functionName], - fn: (context: any, args: any) => batch({ functionName, args, context }), - }); - npSetup.plugins.expressions.registerFunction(fn); - }); - })(); - } - - return cached; -}; +export const { loadLegacyServerFunctionWrappers } = npSetup.plugins.expressions.__LEGACY; diff --git a/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts b/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts index 66c51167c7b59..0f37f33cc1b13 100644 --- a/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts +++ b/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts @@ -26,6 +26,7 @@ export const registries = { browserFunctions: functionsRegistry, renderers: renderersRegistry, types: typesRegistry, + loadLegacyServerFunctionWrappers: () => Promise.resolve(), }; const resetRegistry = (registry: any) => { diff --git a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts deleted file mode 100644 index 0088663080774..0000000000000 --- a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { createHandlers } from '../create_handlers'; - -const mockRequest = { - headers: 'i can haz headers', -}; - -const mockServer = { - plugins: { - elasticsearch: { - getCluster: () => ({ - callWithRequest: (...args: any) => Promise.resolve(args), - }), - }, - }, - config: () => ({ - has: () => false, - get: (val: any) => val, - }), - info: { - uri: 'serveruri', - }, -}; - -describe('server createHandlers', () => { - it('provides helper methods and properties', () => { - const handlers = createHandlers(mockRequest, mockServer); - - expect(handlers).to.have.property('environment', 'server'); - expect(handlers).to.have.property('serverUri'); - expect(handlers).to.have.property('elasticsearchClient'); - }); - - describe('elasticsearchClient', () => { - it('executes callWithRequest', async () => { - const handlers = createHandlers(mockRequest, mockServer); - const [request, endpoint, payload] = await handlers.elasticsearchClient( - 'endpoint', - 'payload' - ); - expect(request).to.equal(mockRequest); - expect(endpoint).to.equal('endpoint'); - expect(payload).to.equal('payload'); - }); - }); -}); diff --git a/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts b/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts deleted file mode 100644 index e03ad361b5555..0000000000000 --- a/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts +++ /dev/null @@ -1,166 +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 Boom from 'boom'; -import Joi from 'joi'; -import { serializeProvider } from '../../../../../plugins/expressions/common'; -import { createHandlers } from '../lib/create_handlers'; - -const API_ROUTE = '/api/interpreter'; - -/** - * Register the Canvas function endopints. - * - * @param {*} server - The Kibana server - */ -export function registerServerFunctions(server: any) { - getServerFunctions(server); - runServerFunctions(server); -} - -/** - * Register the endpoint that executes a batch of functions, and sends the result back as a single response. - * - * @param {*} server - The Kibana server - */ -function runServerFunctions(server: any) { - server.route({ - method: 'POST', - path: `${API_ROUTE}/fns`, - options: { - payload: { - allow: 'application/json', - maxBytes: 26214400, // 25MB payload limit - }, - validate: { - payload: Joi.object({ - functions: Joi.array() - .items( - Joi.object().keys({ - id: Joi.number().required(), - functionName: Joi.string().required(), - args: Joi.object().default({}), - context: Joi.any().default(null), - }) - ) - .required(), - }).required(), - }, - }, - async handler(req: any) { - const handlers = await createHandlers(req, server); - const { functions } = req.payload; - - // Grab the raw Node response object. - const res = req.raw.res; - - // Tell Hapi not to manage the response https://github.com/hapijs/hapi/issues/3884 - req._isReplied = true; - - // Send the initial headers. - res.writeHead(200, { - 'Content-Type': 'application/x-ndjson', - Connection: 'keep-alive', - 'Transfer-Encoding': 'chunked', - 'Cache-Control': 'no-cache', - }); - - // Write a length-delimited response - const streamResult = (result: any) => { - res.write(JSON.stringify(result) + '\n'); - }; - - // Tries to run an interpreter function, and ensures a consistent error payload on failure. - const tryFunction = async (id: any, fnCall: any) => { - try { - const result = await runFunction(server, handlers, fnCall); - - if (typeof result === 'undefined') { - return batchError(id, `Function ${fnCall.functionName} did not return anything.`); - } - - return { id, statusCode: 200, result }; - } catch (err) { - if (Boom.isBoom(err)) { - return batchError(id, err.output.payload, (err as any).statusCode); - } else if (err instanceof Error) { - return batchError(id, err.message); - } - - server.log(['interpreter', 'error'], err); - return batchError(id, 'See server logs for details.'); - } - }; - - // Process each function individually, and stream the responses back to the client - await Promise.all( - functions.map(({ id, ...fnCall }: any) => tryFunction(id, fnCall).then(streamResult)) - ); - - // All of the responses have been written, so we can close the response. - res.end(); - }, - }); -} - -/** - * A helper function for bundling up errors. - */ -function batchError(id: any, message: any, statusCode = 500) { - return { - id, - statusCode, - result: { statusCode, message }, - }; -} - -/** - * Register the endpoint that returns the list of server-only functions. - * @param {*} server - The Kibana server - */ -function getServerFunctions(server: any) { - server.route({ - method: 'GET', - path: `${API_ROUTE}/fns`, - handler() { - return server.plugins.interpreter.registries().serverFunctions.toJS(); - }, - }); -} - -/** - * Run a single Canvas function. - * - * @param {*} server - The Kibana server object - * @param {*} handlers - The Canvas handlers - * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` - */ -async function runFunction(server: any, handlers: any, fnCall: any) { - const registries = server.plugins.interpreter.registries(); - const { functionName, args, context } = fnCall; - const types = registries.types.toJS(); - const { deserialize } = serializeProvider(types); - const fnDef = registries.serverFunctions.toJS()[functionName]; - - if (!fnDef) { - throw Boom.notFound(`Function "${functionName}" could not be found.`); - } - - return fnDef.fn(deserialize(context), args, handlers); -} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/package.json b/src/legacy/core_plugins/kbn_vislib_vis_types/package.json deleted file mode 100644 index b6df6eb794de8..0000000000000 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "kbn_vislib_vis_types", - "version": "kibana" -} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controller.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/controller.js deleted file mode 100644 index 46f2376cb03eb..0000000000000 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/controller.js +++ /dev/null @@ -1,140 +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 'jquery'; -import React from 'react'; - -import { - CUSTOM_LEGEND_VIS_TYPES, - VisLegend, -} from '../../../ui/public/vis/vis_types/vislib_vis_legend'; -import { VislibVisProvider } from '../../../ui/public/vislib/vis'; -import chrome from '../../../ui/public/chrome'; -import { mountReactNode } from '../../../../core/public/utils'; - -const legendClassName = { - top: 'visLib--legend-top', - bottom: 'visLib--legend-bottom', - left: 'visLib--legend-left', - right: 'visLib--legend-right', -}; - -export class vislibVisController { - constructor(el, vis) { - this.el = el; - this.vis = vis; - this.unmount = null; - this.legendRef = React.createRef(); - - // vis mount point - this.container = document.createElement('div'); - this.container.className = 'visLib'; - this.el.appendChild(this.container); - - // chart mount point - this.chartEl = document.createElement('div'); - this.chartEl.className = 'visLib__chart'; - this.container.appendChild(this.chartEl); - // legend mount point - this.legendEl = document.createElement('div'); - this.legendEl.className = 'visLib__legend'; - this.container.appendChild(this.legendEl); - } - - render(esResponse, visParams) { - if (this.vislibVis) { - this.destroy(); - } - - return new Promise(async resolve => { - if (!this.vislib) { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private'); - this.Vislib = Private(VislibVisProvider); - } - - if (this.el.clientWidth === 0 || this.el.clientHeight === 0) { - return resolve(); - } - - this.vislibVis = new this.Vislib(this.chartEl, visParams); - this.vislibVis.on('brush', this.vis.API.events.brush); - this.vislibVis.on('click', this.vis.API.events.filter); - this.vislibVis.on('renderComplete', resolve); - - this.vislibVis.initVisConfig(esResponse, this.vis.getUiState()); - - if (visParams.addLegend) { - $(this.container) - .attr('class', (i, cls) => { - return cls.replace(/visLib--legend-\S+/g, ''); - }) - .addClass(legendClassName[visParams.legendPosition]); - - this.mountLegend(esResponse, visParams.legendPosition); - } - - this.vislibVis.render(esResponse, this.vis.getUiState()); - - // refreshing the legend after the chart is rendered. - // this is necessary because some visualizations - // provide data necessary for the legend only after a render cycle. - if ( - visParams.addLegend && - CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type) - ) { - this.unmountLegend(); - this.mountLegend(esResponse, visParams.legendPosition); - this.vislibVis.render(esResponse, this.vis.getUiState()); - } - }); - } - - mountLegend(visData, position) { - this.unmount = mountReactNode( - - )(this.legendEl); - } - - unmountLegend() { - if (this.unmount) { - this.unmount(); - } - } - - destroy() { - if (this.unmount) { - this.unmount(); - } - - if (this.vislibVis) { - this.vislibVis.off('brush', this.vis.API.events.brush); - this.vislibVis.off('click', this.vis.API.events.filter); - this.vislibVis.destroy(); - delete this.vislibVis; - } - } -} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.d.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.d.ts deleted file mode 100644 index ff8345e9a5b25..0000000000000 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.d.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 { RangeValues } from 'ui/vis/editors/default/controls/ranges'; -import { Alignments, GaugeTypes } from './utils/collections'; -import { ColorSchemaVislibParams, Labels, Style } from './types'; - -interface Gauge extends ColorSchemaVislibParams { - backStyle: 'Full'; - gaugeStyle: 'Full'; - orientation: 'vertical'; - type: 'meter'; - alignment: Alignments; - colorsRange: RangeValues[]; - extendRange: boolean; - gaugeType: GaugeTypes; - labels: Labels; - percentageMode: boolean; - outline?: boolean; - scale: { - show: boolean; - labels: false; - color: 'rgba(105,112,125,0.2)'; - }; - style: Style; -} - -export interface GaugeVisParams { - type: 'gauge'; - addTooltip: boolean; - addLegend: boolean; - isDisplayWarning: boolean; - gauge: Gauge; -} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.d.ts b/src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.d.ts deleted file mode 100644 index 13c676854ead2..0000000000000 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.d.ts +++ /dev/null @@ -1,36 +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 { ColorSchemas } from 'ui/vislib/components/color/colormaps'; -import { RangeValues } from 'ui/vis/editors/default/controls/ranges'; -import { TimeMarker } from 'ui/vislib/visualizations/time_marker'; -import { CommonVislibParams, ColorSchemaVislibParams, ValueAxis } from './types'; -import { Positions } from './utils/collections'; - -export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaVislibParams { - type: 'heatmap'; - addLegend: boolean; - enableHover: boolean; - colorsNumber: number | ''; - colorsRange: RangeValues[]; - valueAxes: ValueAxis[]; - setColorRange: boolean; - percentageMode: boolean; - times: TimeMarker[]; -} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js deleted file mode 100644 index c82073ff582b8..0000000000000 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/kbn_vislib_vis_types.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy'; - -import { histogramDefinition } from './histogram'; -import { lineDefinition } from './line'; -import { pieDefinition } from './pie'; -import { areaDefinition } from './area'; -import { heatmapDefinition } from './heatmap'; -import { horizontalBarDefinition } from './horizontal_bar'; -import { gaugeDefinition } from './gauge'; -import { goalDefinition } from './goal'; - -visualizations.types.createBaseVisualization(histogramDefinition); -visualizations.types.createBaseVisualization(lineDefinition); -visualizations.types.createBaseVisualization(pieDefinition); -visualizations.types.createBaseVisualization(areaDefinition); -visualizations.types.createBaseVisualization(heatmapDefinition); -visualizations.types.createBaseVisualization(horizontalBarDefinition); -visualizations.types.createBaseVisualization(gaugeDefinition); -visualizations.types.createBaseVisualization(goalDefinition); 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 78ac99567d10e..2927565e61dce 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 @@ -826,9 +826,14 @@ function discoverController( }; $scope.updateQueryAndFetch = function({ query, dateRange }) { + const oldDateRange = timefilter.getTime(); timefilter.setTime(dateRange); $state.query = query; - $scope.fetch(); + // storing the updated timerange in the state will trigger a fetch + // call automatically, so only trigger fetch in case this is a refresh call (no changes in parameters). + if (_.isEqual(oldDateRange, dateRange)) { + $scope.fetch(); + } }; function onResults(resp) { diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss index 9fc25b1fbe61e..324458c0814d9 100644 --- a/src/legacy/core_plugins/kibana/public/index.scss +++ b/src/legacy/core_plugins/kibana/public/index.scss @@ -7,6 +7,9 @@ // Public UI styles @import 'src/legacy/ui/public/index'; +// vis_type_vislib UI styles +@import 'src/legacy/core_plugins/vis_type_vislib/public/index'; + // Dev tools styles @import './dev_tools/index'; diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 334397c479a1d..4100ae7205869 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -52,7 +52,7 @@ import './visualize'; import './dashboard'; import './management'; import './dev_tools'; -import 'ui/vislib'; +import 'ui/color_maps'; import 'ui/agg_response'; import 'ui/agg_types'; import { showAppRedirectNotification } from 'ui/notify'; diff --git a/src/legacy/core_plugins/region_map/public/choropleth_layer.js b/src/legacy/core_plugins/region_map/public/choropleth_layer.js index f4c6bfd6bedf5..8132976fcbc69 100644 --- a/src/legacy/core_plugins/region_map/public/choropleth_layer.js +++ b/src/legacy/core_plugins/region_map/public/choropleth_layer.js @@ -23,7 +23,7 @@ import _ from 'lodash'; import d3 from 'd3'; import { i18n } from '@kbn/i18n'; import { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; -import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colormaps'; +import { truncatedColorMaps } from 'ui/color_maps'; import * as topojson from 'topojson-client'; import { toastNotifications } from 'ui/notify'; import * as colorUtil from 'ui/vis/map/color_util'; diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx index 8306b3274a914..73fe07ec60102 100644 --- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx +++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx @@ -28,7 +28,7 @@ import { NumberInputOption, SelectOption, SwitchOption, -} from '../../../kbn_vislib_vis_types/public/components'; +} from '../../../vis_type_vislib/public/components'; import { WmsOptions } from '../../../tile_map/public/components/wms_options'; import { RegionMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/region_map/public/region_map_type.js b/src/legacy/core_plugins/region_map/public/region_map_type.js index 6f83ae912e184..39353a379ce52 100644 --- a/src/legacy/core_plugins/region_map/public/region_map_type.js +++ b/src/legacy/core_plugins/region_map/public/region_map_type.js @@ -19,7 +19,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { colorSchemas } from 'ui/vislib/components/color/truncated_colormaps'; +import { truncatedColorSchemas as colorSchemas } from 'ui/color_maps'; import { mapToLayerWithId } from './util'; import { createRegionMapVisualization } from './region_map_visualization'; import { Status } from '../../visualizations/public'; diff --git a/src/legacy/core_plugins/region_map/public/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/region_map_visualization.js index b58de5d9c6ab7..f9a5793ca8137 100644 --- a/src/legacy/core_plugins/region_map/public/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/region_map_visualization.js @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import ChoroplethLayer from './choropleth_layer'; -import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colormaps'; +import { truncatedColorMaps } from 'ui/color_maps'; import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { toastNotifications } from 'ui/notify'; diff --git a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx index 15c92f4617497..e57cea8467d12 100644 --- a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx @@ -27,7 +27,7 @@ import { RangeOption, SelectOption, SwitchOption, -} from '../../../kbn_vislib_vis_types/public/components'; +} from '../../../vis_type_vislib/public/components'; import { WmsOptions } from './wms_options'; import { TileMapVisParams } from '../types'; import { MapTypes } from '../map_types'; diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx index f2cf69bb63ba4..2989f6ce7ebd5 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { EuiLink, EuiSpacer, EuiText, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TextInputOption } from '../../../kbn_vislib_vis_types/public/components'; +import { TextInputOption } from '../../../vis_type_vislib/public/components'; import { WMSOptions } from '../types'; interface WmsInternalOptions { 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 c5ccc3acba610..d9dca5afd7377 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 @@ -25,7 +25,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { TmsLayer } from 'ui/vis/map/service_settings'; import { Vis } from 'ui/vis'; import { RegionMapVisParams } from '../../../region_map/public/types'; -import { SelectOption, SwitchOption } from '../../../kbn_vislib_vis_types/public/components'; +import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public/components'; import { WmsInternalOptions } from './wms_internal_options'; import { WMSOptions, TileMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js index e9334ff91def9..fe29d9b6aad21 100644 --- a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js +++ b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js @@ -22,7 +22,7 @@ import _ from 'lodash'; import d3 from 'd3'; import $ from 'jquery'; import { EventEmitter } from 'events'; -import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colormaps'; +import { truncatedColorMaps } from 'ui/color_maps'; import * as colorUtil from 'ui/vis/map/color_util'; export class ScaledCirclesMarkers extends EventEmitter { diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_type.js b/src/legacy/core_plugins/tile_map/public/tile_map_type.js index f2e6469e768e7..c58c226f0aba0 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_type.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_type.js @@ -21,7 +21,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { Schemas } from 'ui/vis/editors/default/schemas'; -import { colorSchemas } from 'ui/vislib/components/color/truncated_colormaps'; +import { truncatedColorSchemas as colorSchemas } from 'ui/color_maps'; import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; import { createTileMapVisualization } from './tile_map_visualization'; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx index cce92a08f2c2b..125577815c207 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx @@ -22,7 +22,7 @@ import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { RangeOption, SwitchOption } from '../../kbn_vislib_vis_types/public/components'; +import { RangeOption, SwitchOption } from '../../vis_type_vislib/public/components'; import { MarkdownVisParams } from './types'; function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_controller.js b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_controller.js index ecaf6b5d70d36..17dad6a4cd8cb 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_controller.js @@ -20,7 +20,7 @@ import { last, findIndex, isNaN } from 'lodash'; import React, { Component } from 'react'; import { isColorDark } from '@elastic/eui'; -import { getHeatmapColors } from 'ui/vislib/components/color/heatmap_color'; +import { getHeatmapColors } from 'ui/color_maps'; import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; import { MetricVisValue } from './metric_vis_value'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx index 9649588976c0d..566618c527019 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx @@ -36,8 +36,8 @@ import { SwitchOption, RangeOption, SetColorSchemaOptionsValue, -} from '../../../kbn_vislib_vis_types/public/components'; -import { ColorModes } from '../../../kbn_vislib_vis_types/public/utils/collections'; +} from '../../../vis_type_vislib/public/components'; +import { ColorModes } from '../../../vis_type_vislib/public/utils/collections'; import { MetricVisParam, VisParams } from '../types'; function MetricVisOptions({ diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts index b64361f17c470..04bff5ccb4655 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; -import { vislibColorMaps, ColorSchemas } from 'ui/vislib/components/color/colormaps'; +import { vislibColorMaps, ColorSchemas } from 'ui/color_maps'; import { ExpressionFunction, KibanaDatatable, @@ -27,7 +27,7 @@ import { Render, Style, } from '../../../../plugins/expressions/public'; -import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections'; +import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; import { visType, DimensionsVisParam, VisParams } from './types'; type Context = KibanaDatatable; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts index ceab5dafe1f06..9b22423012b36 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts @@ -23,13 +23,13 @@ import { i18n } from '@kbn/i18n'; import { Schemas } from 'ui/vis/editors/default/schemas'; import { AggGroupNames } from 'ui/vis/editors/default'; -import { colorSchemas, ColorSchemas } from 'ui/vislib/components/color/colormaps'; +import { colorSchemas, ColorSchemas } from 'ui/color_maps'; // @ts-ignore import { MetricVisComponent } from './components/metric_vis_controller'; import { MetricVisOptions } from './components/metric_vis_options'; -import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections'; +import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; export const metricVisDefinition = { name: 'metric', 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 ce0e78140a86a..06ec509f8c4d3 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/types.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/types.ts @@ -17,11 +17,11 @@ * under the License. */ -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; +import { ColorSchemas } from 'ui/color_maps'; import { RangeValues } from 'ui/vis/editors/default/controls/ranges'; import { SchemaConfig } from '../../visualizations/public'; -import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections'; -import { Labels, Style } from '../../kbn_vislib_vis_types/public/types'; +import { ColorModes } from '../../vis_type_vislib/public/utils/collections'; +import { Labels, Style } from '../../vis_type_vislib/public/types'; export const visType = 'metric'; diff --git a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx index 4d69af59b0c99..be82b52dee0fc 100644 --- a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx @@ -28,7 +28,7 @@ import { NumberInputOption, SwitchOption, SelectOption, -} from '../../../kbn_vislib_vis_types/public/components/common'; +} from '../../../vis_type_vislib/public/components/common'; import { TableVisParams } from '../types'; import { totalAggregations, isAggConfigNumeric } from './utils'; diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index 9e6a2d1a24a85..c500b5d888b05 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { ValidatedDualRange } from 'ui/validated_range'; import { VisOptionsProps } from 'ui/vis/editors/default'; -import { SelectOption, SwitchOption } from '../../../kbn_vislib_vis_types/public/components'; +import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public/components'; import { TagCloudVisParams } from '../types'; function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json deleted file mode 100644 index 178704a36372d..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json +++ /dev/null @@ -1,984 +0,0 @@ -{ - "_shards": { - "failed": 0, - "successful": 5, - "total": 5 - }, - "aggregations": { - "c9b5f9c0-e403-11e6-be91-6f7688e9fac7": { - "doc_count": 128145, - "timeseries": { - "buckets": [ - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057 - }, - "doc_count": 368, - "key": 1485549090000, - "key_as_string": "2017-01-27T20:31:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.07466666666666667 - }, - "doc_count": 1106, - "key": 1485549120000, - "key_as_string": "2017-01-27T20:32:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.08033333333333335 - }, - "doc_count": 1107, - "key": 1485549150000, - "key_as_string": "2017-01-27T20:32:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.066 - }, - "doc_count": 1109, - "key": 1485549180000, - "key_as_string": "2017-01-27T20:33:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.05366666666666667 - }, - "doc_count": 1093, - "key": 1485549210000, - "key_as_string": "2017-01-27T20:33:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1086, - "key": 1485549240000, - "key_as_string": "2017-01-27T20:34:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1086, - "key": 1485549270000, - "key_as_string": "2017-01-27T20:34:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1090, - "key": 1485549300000, - "key_as_string": "2017-01-27T20:35:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1085, - "key": 1485549330000, - "key_as_string": "2017-01-27T20:35:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1082, - "key": 1485549360000, - "key_as_string": "2017-01-27T20:36:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1080, - "key": 1485549390000, - "key_as_string": "2017-01-27T20:36:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1082, - "key": 1485549420000, - "key_as_string": "2017-01-27T20:37:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1079, - "key": 1485549450000, - "key_as_string": "2017-01-27T20:37:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1080, - "key": 1485549480000, - "key_as_string": "2017-01-27T20:38:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1080, - "key": 1485549510000, - "key_as_string": "2017-01-27T20:38:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1082, - "key": 1485549540000, - "key_as_string": "2017-01-27T20:39:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.042666666666666665 - }, - "doc_count": 1079, - "key": 1485549570000, - "key_as_string": "2017-01-27T20:39:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485549600000, - "key_as_string": "2017-01-27T20:40:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1075, - "key": 1485549630000, - "key_as_string": "2017-01-27T20:40:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485549660000, - "key_as_string": "2017-01-27T20:41:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1076, - "key": 1485549690000, - "key_as_string": "2017-01-27T20:41:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485549720000, - "key_as_string": "2017-01-27T20:42:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485549750000, - "key_as_string": "2017-01-27T20:42:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1067, - "key": 1485549780000, - "key_as_string": "2017-01-27T20:43:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1065, - "key": 1485549810000, - "key_as_string": "2017-01-27T20:43:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1065, - "key": 1485549840000, - "key_as_string": "2017-01-27T20:44:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036333333333333336 - }, - "doc_count": 1062, - "key": 1485549870000, - "key_as_string": "2017-01-27T20:44:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1063, - "key": 1485549900000, - "key_as_string": "2017-01-27T20:45:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1065, - "key": 1485549930000, - "key_as_string": "2017-01-27T20:45:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1065, - "key": 1485549960000, - "key_as_string": "2017-01-27T20:46:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1069, - "key": 1485549990000, - "key_as_string": "2017-01-27T20:46:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550020000, - "key_as_string": "2017-01-27T20:47:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550050000, - "key_as_string": "2017-01-27T20:47:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550080000, - "key_as_string": "2017-01-27T20:48:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1074, - "key": 1485550110000, - "key_as_string": "2017-01-27T20:48:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1074, - "key": 1485550140000, - "key_as_string": "2017-01-27T20:49:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1074, - "key": 1485550170000, - "key_as_string": "2017-01-27T20:49:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485550200000, - "key_as_string": "2017-01-27T20:50:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485550230000, - "key_as_string": "2017-01-27T20:50:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1074, - "key": 1485550260000, - "key_as_string": "2017-01-27T20:51:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.031 - }, - "doc_count": 1074, - "key": 1485550290000, - "key_as_string": "2017-01-27T20:51:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485550320000, - "key_as_string": "2017-01-27T20:52:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1073, - "key": 1485550350000, - "key_as_string": "2017-01-27T20:52:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550380000, - "key_as_string": "2017-01-27T20:53:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485550410000, - "key_as_string": "2017-01-27T20:53:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1069, - "key": 1485550440000, - "key_as_string": "2017-01-27T20:54:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1069, - "key": 1485550470000, - "key_as_string": "2017-01-27T20:54:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1068, - "key": 1485550500000, - "key_as_string": "2017-01-27T20:55:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1067, - "key": 1485550530000, - "key_as_string": "2017-01-27T20:55:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1065, - "key": 1485550560000, - "key_as_string": "2017-01-27T20:56:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1069, - "key": 1485550590000, - "key_as_string": "2017-01-27T20:56:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1068, - "key": 1485550620000, - "key_as_string": "2017-01-27T20:57:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550650000, - "key_as_string": "2017-01-27T20:57:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1068, - "key": 1485550680000, - "key_as_string": "2017-01-27T20:58:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1071, - "key": 1485550710000, - "key_as_string": "2017-01-27T20:58:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1074, - "key": 1485550740000, - "key_as_string": "2017-01-27T20:59:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1074, - "key": 1485550770000, - "key_as_string": "2017-01-27T20:59:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1074, - "key": 1485550800000, - "key_as_string": "2017-01-27T21:00:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1076, - "key": 1485550830000, - "key_as_string": "2017-01-27T21:00:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1078, - "key": 1485550860000, - "key_as_string": "2017-01-27T21:01:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1077, - "key": 1485550890000, - "key_as_string": "2017-01-27T21:01:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550920000, - "key_as_string": "2017-01-27T21:02:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550950000, - "key_as_string": "2017-01-27T21:02:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1073, - "key": 1485550980000, - "key_as_string": "2017-01-27T21:03:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551010000, - "key_as_string": "2017-01-27T21:03:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1069, - "key": 1485551040000, - "key_as_string": "2017-01-27T21:04:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1068, - "key": 1485551070000, - "key_as_string": "2017-01-27T21:04:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1075, - "key": 1485551100000, - "key_as_string": "2017-01-27T21:05:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485551130000, - "key_as_string": "2017-01-27T21:05:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485551160000, - "key_as_string": "2017-01-27T21:06:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551190000, - "key_as_string": "2017-01-27T21:06:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1075, - "key": 1485551220000, - "key_as_string": "2017-01-27T21:07:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1071, - "key": 1485551250000, - "key_as_string": "2017-01-27T21:07:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04733333333333334 - }, - "doc_count": 1081, - "key": 1485551280000, - "key_as_string": "2017-01-27T21:08:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.044333333333333336 - }, - "doc_count": 1078, - "key": 1485551310000, - "key_as_string": "2017-01-27T21:08:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1079, - "key": 1485551340000, - "key_as_string": "2017-01-27T21:09:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1077, - "key": 1485551370000, - "key_as_string": "2017-01-27T21:09:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1077, - "key": 1485551400000, - "key_as_string": "2017-01-27T21:10:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1075, - "key": 1485551430000, - "key_as_string": "2017-01-27T21:10:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038000000000000006 - }, - "doc_count": 1078, - "key": 1485551460000, - "key_as_string": "2017-01-27T21:11:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037 - }, - "doc_count": 1074, - "key": 1485551490000, - "key_as_string": "2017-01-27T21:11:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036666666666666674 - }, - "doc_count": 1074, - "key": 1485551520000, - "key_as_string": "2017-01-27T21:12:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1076, - "key": 1485551550000, - "key_as_string": "2017-01-27T21:12:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03733333333333333 - }, - "doc_count": 1075, - "key": 1485551580000, - "key_as_string": "2017-01-27T21:13:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1077, - "key": 1485551610000, - "key_as_string": "2017-01-27T21:13:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1080, - "key": 1485551640000, - "key_as_string": "2017-01-27T21:14:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057666666666666665 - }, - "doc_count": 1080, - "key": 1485551670000, - "key_as_string": "2017-01-27T21:14:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.045000000000000005 - }, - "doc_count": 1080, - "key": 1485551700000, - "key_as_string": "2017-01-27T21:15:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1080, - "key": 1485551730000, - "key_as_string": "2017-01-27T21:15:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551760000, - "key_as_string": "2017-01-27T21:16:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038 - }, - "doc_count": 1080, - "key": 1485551790000, - "key_as_string": "2017-01-27T21:16:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551820000, - "key_as_string": "2017-01-27T21:17:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1080, - "key": 1485551850000, - "key_as_string": "2017-01-27T21:17:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1080, - "key": 1485551880000, - "key_as_string": "2017-01-27T21:18:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1080, - "key": 1485551910000, - "key_as_string": "2017-01-27T21:18:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03766666666666666 - }, - "doc_count": 1080, - "key": 1485551940000, - "key_as_string": "2017-01-27T21:19:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485551970000, - "key_as_string": "2017-01-27T21:19:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1077, - "key": 1485552000000, - "key_as_string": "2017-01-27T21:20:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1077, - "key": 1485552030000, - "key_as_string": "2017-01-27T21:20:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.029666666666666664 - }, - "doc_count": 1077, - "key": 1485552060000, - "key_as_string": "2017-01-27T21:21:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.02766666666666667 - }, - "doc_count": 1077, - "key": 1485552090000, - "key_as_string": "2017-01-27T21:21:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.028 - }, - "doc_count": 1077, - "key": 1485552120000, - "key_as_string": "2017-01-27T21:22:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.030666666666666665 - }, - "doc_count": 1077, - "key": 1485552150000, - "key_as_string": "2017-01-27T21:22:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1083, - "key": 1485552180000, - "key_as_string": "2017-01-27T21:23:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1083, - "key": 1485552210000, - "key_as_string": "2017-01-27T21:23:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.041 - }, - "doc_count": 1082, - "key": 1485552240000, - "key_as_string": "2017-01-27T21:24:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1087, - "key": 1485552270000, - "key_as_string": "2017-01-27T21:24:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1083, - "key": 1485552300000, - "key_as_string": "2017-01-27T21:25:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03933333333333333 - }, - "doc_count": 1083, - "key": 1485552330000, - "key_as_string": "2017-01-27T21:25:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1083, - "key": 1485552360000, - "key_as_string": "2017-01-27T21:26:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1083, - "key": 1485552390000, - "key_as_string": "2017-01-27T21:26:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1082, - "key": 1485552420000, - "key_as_string": "2017-01-27T21:27:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333334 - }, - "doc_count": 1083, - "key": 1485552450000, - "key_as_string": "2017-01-27T21:27:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1083, - "key": 1485552480000, - "key_as_string": "2017-01-27T21:28:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1084, - "key": 1485552510000, - "key_as_string": "2017-01-27T21:28:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1083, - "key": 1485552540000, - "key_as_string": "2017-01-27T21:29:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1083, - "key": 1485552570000, - "key_as_string": "2017-01-27T21:29:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04466666666666667 - }, - "doc_count": 1083, - "key": 1485552600000, - "key_as_string": "2017-01-27T21:30:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1083, - "key": 1485552630000, - "key_as_string": "2017-01-27T21:30:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.0505 - }, - "doc_count": 722, - "key": 1485552660000, - "key_as_string": "2017-01-27T21:31:00.000Z" - } - ] - } - } - }, - "hits": { - "hits": [], - "max_score": 0, - "total": 128145 - }, - "status": 200, - "timed_out": false, - "took": 28 -} diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json deleted file mode 100644 index d587e48b31881..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json +++ /dev/null @@ -1,985 +0,0 @@ -{ - "_shards": { - "failed": 0, - "successful": 5, - "total": 5 - }, - "aggregations": { - "c9b5f9c0-e403-11e6-be91-6f7688e9fac7": { - "doc_count": 128145, - "timeseries": { - "buckets": [ - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057 - }, - "doc_count": 368, - "key": 1485549090000, - "key_as_string": "2017-01-27T20:31:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.07466666666666667 - }, - "doc_count": 1106, - "key": 1485549120000, - "key_as_string": "2017-01-27T20:32:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.08033333333333335 - }, - "doc_count": 1107, - "key": 1485549150000, - "key_as_string": "2017-01-27T20:32:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.066 - }, - "doc_count": 1109, - "key": 1485549180000, - "key_as_string": "2017-01-27T20:33:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.05366666666666667 - }, - "doc_count": 1093, - "key": 1485549210000, - "key_as_string": "2017-01-27T20:33:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1086, - "key": 1485549240000, - "key_as_string": "2017-01-27T20:34:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1086, - "key": 1485549270000, - "key_as_string": "2017-01-27T20:34:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1090, - "key": 1485549300000, - "key_as_string": "2017-01-27T20:35:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1085, - "key": 1485549330000, - "key_as_string": "2017-01-27T20:35:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1082, - "key": 1485549360000, - "key_as_string": "2017-01-27T20:36:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1080, - "key": 1485549390000, - "key_as_string": "2017-01-27T20:36:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1082, - "key": 1485549420000, - "key_as_string": "2017-01-27T20:37:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1079, - "key": 1485549450000, - "key_as_string": "2017-01-27T20:37:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1080, - "key": 1485549480000, - "key_as_string": "2017-01-27T20:38:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1080, - "key": 1485549510000, - "key_as_string": "2017-01-27T20:38:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1082, - "key": 1485549540000, - "key_as_string": "2017-01-27T20:39:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.042666666666666665 - }, - "doc_count": 1079, - "key": 1485549570000, - "key_as_string": "2017-01-27T20:39:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485549600000, - "key_as_string": "2017-01-27T20:40:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1075, - "key": 1485549630000, - "key_as_string": "2017-01-27T20:40:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485549660000, - "key_as_string": "2017-01-27T20:41:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1076, - "key": 1485549690000, - "key_as_string": "2017-01-27T20:41:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485549720000, - "key_as_string": "2017-01-27T20:42:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485549750000, - "key_as_string": "2017-01-27T20:42:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1067, - "key": 1485549780000, - "key_as_string": "2017-01-27T20:43:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1065, - "key": 1485549810000, - "key_as_string": "2017-01-27T20:43:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1065, - "key": 1485549840000, - "key_as_string": "2017-01-27T20:44:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036333333333333336 - }, - "doc_count": 1062, - "key": 1485549870000, - "key_as_string": "2017-01-27T20:44:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1063, - "key": 1485549900000, - "key_as_string": "2017-01-27T20:45:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1065, - "key": 1485549930000, - "key_as_string": "2017-01-27T20:45:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1065, - "key": 1485549960000, - "key_as_string": "2017-01-27T20:46:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1069, - "key": 1485549990000, - "key_as_string": "2017-01-27T20:46:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550020000, - "key_as_string": "2017-01-27T20:47:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550050000, - "key_as_string": "2017-01-27T20:47:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550080000, - "key_as_string": "2017-01-27T20:48:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1074, - "key": 1485550110000, - "key_as_string": "2017-01-27T20:48:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1074, - "key": 1485550140000, - "key_as_string": "2017-01-27T20:49:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1074, - "key": 1485550170000, - "key_as_string": "2017-01-27T20:49:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485550200000, - "key_as_string": "2017-01-27T20:50:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485550230000, - "key_as_string": "2017-01-27T20:50:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1074, - "key": 1485550260000, - "key_as_string": "2017-01-27T20:51:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.031 - }, - "doc_count": 1074, - "key": 1485550290000, - "key_as_string": "2017-01-27T20:51:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485550320000, - "key_as_string": "2017-01-27T20:52:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1073, - "key": 1485550350000, - "key_as_string": "2017-01-27T20:52:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550380000, - "key_as_string": "2017-01-27T20:53:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485550410000, - "key_as_string": "2017-01-27T20:53:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1069, - "key": 1485550440000, - "key_as_string": "2017-01-27T20:54:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1069, - "key": 1485550470000, - "key_as_string": "2017-01-27T20:54:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1068, - "key": 1485550500000, - "key_as_string": "2017-01-27T20:55:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1067, - "key": 1485550530000, - "key_as_string": "2017-01-27T20:55:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1065, - "key": 1485550560000, - "key_as_string": "2017-01-27T20:56:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1069, - "key": 1485550590000, - "key_as_string": "2017-01-27T20:56:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1068, - "key": 1485550620000, - "key_as_string": "2017-01-27T20:57:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550650000, - "key_as_string": "2017-01-27T20:57:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1068, - "key": 1485550680000, - "key_as_string": "2017-01-27T20:58:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1071, - "key": 1485550710000, - "key_as_string": "2017-01-27T20:58:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1074, - "key": 1485550740000, - "key_as_string": "2017-01-27T20:59:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1074, - "key": 1485550770000, - "key_as_string": "2017-01-27T20:59:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1074, - "key": 1485550800000, - "key_as_string": "2017-01-27T21:00:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1076, - "key": 1485550830000, - "key_as_string": "2017-01-27T21:00:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1078, - "key": 1485550860000, - "key_as_string": "2017-01-27T21:01:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1077, - "key": 1485550890000, - "key_as_string": "2017-01-27T21:01:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550920000, - "key_as_string": "2017-01-27T21:02:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550950000, - "key_as_string": "2017-01-27T21:02:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1073, - "key": 1485550980000, - "key_as_string": "2017-01-27T21:03:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551010000, - "key_as_string": "2017-01-27T21:03:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1069, - "key": 1485551040000, - "key_as_string": "2017-01-27T21:04:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1068, - "key": 1485551070000, - "key_as_string": "2017-01-27T21:04:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1075, - "key": 1485551100000, - "key_as_string": "2017-01-27T21:05:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485551130000, - "key_as_string": "2017-01-27T21:05:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485551160000, - "key_as_string": "2017-01-27T21:06:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551190000, - "key_as_string": "2017-01-27T21:06:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1075, - "key": 1485551220000, - "key_as_string": "2017-01-27T21:07:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1071, - "key": 1485551250000, - "key_as_string": "2017-01-27T21:07:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04733333333333334 - }, - "doc_count": 1081, - "key": 1485551280000, - "key_as_string": "2017-01-27T21:08:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.044333333333333336 - }, - "doc_count": 1078, - "key": 1485551310000, - "key_as_string": "2017-01-27T21:08:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1079, - "key": 1485551340000, - "key_as_string": "2017-01-27T21:09:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1077, - "key": 1485551370000, - "key_as_string": "2017-01-27T21:09:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1077, - "key": 1485551400000, - "key_as_string": "2017-01-27T21:10:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1075, - "key": 1485551430000, - "key_as_string": "2017-01-27T21:10:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038000000000000006 - }, - "doc_count": 1078, - "key": 1485551460000, - "key_as_string": "2017-01-27T21:11:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037 - }, - "doc_count": 1074, - "key": 1485551490000, - "key_as_string": "2017-01-27T21:11:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036666666666666674 - }, - "doc_count": 1074, - "key": 1485551520000, - "key_as_string": "2017-01-27T21:12:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1076, - "key": 1485551550000, - "key_as_string": "2017-01-27T21:12:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03733333333333333 - }, - "doc_count": 1075, - "key": 1485551580000, - "key_as_string": "2017-01-27T21:13:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1077, - "key": 1485551610000, - "key_as_string": "2017-01-27T21:13:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1080, - "key": 1485551640000, - "key_as_string": "2017-01-27T21:14:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057666666666666665 - }, - "doc_count": 1080, - "key": 1485551670000, - "key_as_string": "2017-01-27T21:14:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.045000000000000005 - }, - "doc_count": 1080, - "key": 1485551700000, - "key_as_string": "2017-01-27T21:15:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1080, - "key": 1485551730000, - "key_as_string": "2017-01-27T21:15:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551760000, - "key_as_string": "2017-01-27T21:16:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038 - }, - "doc_count": 1080, - "key": 1485551790000, - "key_as_string": "2017-01-27T21:16:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551820000, - "key_as_string": "2017-01-27T21:17:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1080, - "key": 1485551850000, - "key_as_string": "2017-01-27T21:17:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1080, - "key": 1485551880000, - "key_as_string": "2017-01-27T21:18:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1080, - "key": 1485551910000, - "key_as_string": "2017-01-27T21:18:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03766666666666666 - }, - "doc_count": 1080, - "key": 1485551940000, - "key_as_string": "2017-01-27T21:19:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485551970000, - "key_as_string": "2017-01-27T21:19:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1077, - "key": 1485552000000, - "key_as_string": "2017-01-27T21:20:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1077, - "key": 1485552030000, - "key_as_string": "2017-01-27T21:20:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.029666666666666664 - }, - "doc_count": 1077, - "key": 1485552060000, - "key_as_string": "2017-01-27T21:21:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.02766666666666667 - }, - "doc_count": 1077, - "key": 1485552090000, - "key_as_string": "2017-01-27T21:21:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.028 - }, - "doc_count": 1077, - "key": 1485552120000, - "key_as_string": "2017-01-27T21:22:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.030666666666666665 - }, - "doc_count": 1077, - "key": 1485552150000, - "key_as_string": "2017-01-27T21:22:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1083, - "key": 1485552180000, - "key_as_string": "2017-01-27T21:23:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1083, - "key": 1485552210000, - "key_as_string": "2017-01-27T21:23:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.041 - }, - "doc_count": 1082, - "key": 1485552240000, - "key_as_string": "2017-01-27T21:24:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1087, - "key": 1485552270000, - "key_as_string": "2017-01-27T21:24:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1083, - "key": 1485552300000, - "key_as_string": "2017-01-27T21:25:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03933333333333333 - }, - "doc_count": 1083, - "key": 1485552330000, - "key_as_string": "2017-01-27T21:25:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1083, - "key": 1485552360000, - "key_as_string": "2017-01-27T21:26:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1083, - "key": 1485552390000, - "key_as_string": "2017-01-27T21:26:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1082, - "key": 1485552420000, - "key_as_string": "2017-01-27T21:27:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333334 - }, - "doc_count": 1083, - "key": 1485552450000, - "key_as_string": "2017-01-27T21:27:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1083, - "key": 1485552480000, - "key_as_string": "2017-01-27T21:28:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1084, - "key": 1485552510000, - "key_as_string": "2017-01-27T21:28:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1083, - "key": 1485552540000, - "key_as_string": "2017-01-27T21:29:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1083, - "key": 1485552570000, - "key_as_string": "2017-01-27T21:29:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04466666666666667 - }, - "doc_count": 1083, - "key": 1485552600000, - "key_as_string": "2017-01-27T21:30:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1083, - "key": 1485552630000, - "key_as_string": "2017-01-27T21:30:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.0505 - }, - "doc_count": 722, - "key": 1485552660000, - "key_as_string": "2017-01-27T21:31:00.000Z" - } - ] - } - } - }, - "hits": { - "hits": [], - "max_score": 0, - "total": 128145 - }, - "status": 200, - "timed_out": false, - "took": 28 -} - diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js deleted file mode 100644 index 1414435017c86..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js +++ /dev/null @@ -1,388 +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 'chai'; -import { bucketTransform } from '../../helpers/bucket_transform'; - -describe('bucketTransform', () => { - describe('count', () => { - it('returns count agg', () => { - const metric = { id: 'test', type: 'count' }; - const fn = bucketTransform.count; - expect(fn(metric)).to.eql({ - bucket_script: { - buckets_path: { count: '_count' }, - script: { source: 'count * 1', lang: 'expression' }, - gap_policy: 'skip', - }, - }); - }); - }); - - describe('std metric', () => { - ['avg', 'max', 'min', 'sum', 'cardinality', 'value_count'].forEach(type => { - it(`returns ${type} agg`, () => { - const metric = { id: 'test', type: type, field: 'cpu.pct' }; - const fn = bucketTransform[type]; - const result = {}; - result[type] = { field: 'cpu.pct' }; - expect(fn(metric)).to.eql(result); - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.avg({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.avg({ id: 'test', type: 'avg' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('extended stats', () => { - ['std_deviation', 'variance', 'sum_of_squares'].forEach(type => { - it(`returns ${type} agg`, () => { - const fn = bucketTransform[type]; - const metric = { id: 'test', type: type, field: 'cpu.pct' }; - expect(fn(metric)).to.eql({ extended_stats: { field: 'cpu.pct' } }); - }); - }); - - it('returns std_deviation agg with sigma', () => { - const fn = bucketTransform.std_deviation; - const metric = { - id: 'test', - type: 'std_deviation', - field: 'cpu.pct', - sigma: 2, - }; - expect(fn(metric)).to.eql({ - extended_stats: { field: 'cpu.pct', sigma: 2 }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.std_deviation({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.std_deviation({ id: 'test', type: 'avg' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('percentiles', () => { - it('returns percentiles agg', () => { - const metric = { - id: 'test', - type: 'percentile', - field: 'cpu.pct', - percentiles: [ - { value: 50, mode: 'line' }, - { value: 10, mode: 'band', percentile: 90 }, - ], - }; - const fn = bucketTransform.percentile; - expect(fn(metric)).to.eql({ - percentiles: { - field: 'cpu.pct', - percents: [50, 10, 90], - }, - }); - }); - - it('define a default 0 value if it was not provided', () => { - const metric = { - id: 'test', - type: 'percentile', - field: 'cpu.pct', - percentiles: [ - { value: 50, mode: 'line' }, - { mode: 'line' }, - { value: undefined, mode: 'line' }, - { value: '', mode: 'line' }, - { value: null, mode: 'line' }, - { value: 0, mode: 'line' }, - ], - }; - expect(bucketTransform.percentile(metric)).to.eql({ - percentiles: { - field: 'cpu.pct', - percents: [50, 0, 0, 0, 0, 0], - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - field: 'cpu.pct', - percentiles: [{ value: 50, mode: 'line' }], - }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - type: 'avg', - percentiles: [{ value: 50, mode: 'line' }], - }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - - it('throws error if percentiles is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - type: 'avg', - field: 'cpu.pct', - }); - expect(run).to.throw(Error, 'Metric missing percentiles'); - }); - }); - - describe('derivative', () => { - it('returns derivative agg with defaults', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'skip', - unit: '10s', - }, - }); - }); - - it('returns derivative agg with unit', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - unit: '1s', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'skip', - unit: '1s', - }, - }); - }); - - it('returns derivative agg with gap_policy', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - gap_policy: 'zero_fill', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'zero_fill', - unit: '10s', - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.derivative({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.derivative({ id: 'test', type: 'derivative' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('serial_diff', () => { - it('returns serial_diff agg with defaults', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'skip', - lag: 1, - }, - }); - }); - - it('returns serial_diff agg with lag', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - lag: 10, - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'skip', - lag: 10, - }, - }); - }); - - it('returns serial_diff agg with gap_policy', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - gap_policy: 'zero_fill', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'zero_fill', - lag: 1, - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.serial_diff({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.serial_diff({ id: 'test', type: 'serial_diff' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('cumulative_sum', () => { - it('returns cumulative_sum agg', () => { - const metric = { id: '2', type: 'cumulative_sum', field: '1' }; - const metrics = [{ id: '1', type: 'sum', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.cumulative_sum; - expect(fn(metric, metrics, '10s')).is.eql({ - cumulative_sum: { buckets_path: '1' }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.cumulative_sum({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.cumulative_sum({ id: 'test', type: 'cumulative_sum' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('calculation', () => { - it('returns calculation(bucket_script)', () => { - const metric = { - id: '2', - type: 'calculation', - script: 'params.idle != null ? 1 - params.idle : 0', - variables: [{ name: 'idle', field: '1' }], - }; - const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; - const fn = bucketTransform.calculation; - expect(fn(metric, metrics, '10s')).is.eql({ - bucket_script: { - buckets_path: { - idle: '1', - }, - gap_policy: 'skip', - script: { - source: 'params.idle != null ? 1 - params.idle : 0', - lang: 'painless', - params: { - _interval: 10000, - }, - }, - }, - }); - }); - - it('throws error if variables is missing', () => { - const run = () => - bucketTransform.calculation({ - id: 'test', - type: 'calculation', - script: 'params.idle != null ? 1 - params.idle : null', - }); - expect(run).to.throw(Error, 'Metric missing variables'); - }); - - it('throws error if script is missing', () => { - const run = () => - bucketTransform.calculation({ - id: 'test', - type: 'calculation', - variables: [{ field: '1', name: 'idle' }], - }); - expect(run).to.throw(Error, 'Metric missing script'); - }); - }); - - describe('positive_only', () => { - it('returns bucket_script', () => { - const metric = { - id: '2', - type: 'positive_only', - field: '1', - }; - const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; - const fn = bucketTransform.positive_only; - expect(fn(metric, metrics, '10s')).is.eql({ - bucket_script: { - buckets_path: { - value: '1', - }, - gap_policy: 'skip', - script: { - source: 'params.value > 0.0 ? params.value : 0.0', - lang: 'painless', - }, - }, - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts similarity index 58% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts index 10ad9e467610e..cf5244f8e5a7d 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts @@ -17,43 +17,41 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { buildProcessorFunction } from '../build_processor_function'; +import { buildProcessorFunction } from './build_processor_function'; describe('buildProcessorFunction(chain, ...args)', () => { const req = {}; const panel = {}; const series = {}; - it('should call each processor', () => { - const first = sinon.spy(() => next => doc => next(doc)); - const second = sinon.spy(() => next => doc => next(doc)); + test('should call each processor', () => { + const first = jest.fn(() => (next: any) => (doc: any) => next(doc)); + const second = jest.fn(() => (next: any) => (doc: any) => next(doc)); buildProcessorFunction([first, second], req, panel, series); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); - it('should chain each processor', () => { - const first = sinon.spy(next => doc => next(doc)); - const second = sinon.spy(next => doc => next(doc)); + test('should chain each processor', () => { + const first = jest.fn(() => (next: any) => (doc: any) => next(doc)); + const second = jest.fn(() => (next: any) => (doc: any) => next(doc)); buildProcessorFunction([() => first, () => second], req, panel, series); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); - it('should next of each processor', () => { - const first = sinon.spy(); - const second = sinon.spy(); + test('should next of each processor', () => { + const first = jest.fn(); + const second = jest.fn(); const fn = buildProcessorFunction( [ - () => next => doc => { + () => (next: any) => (doc: any) => { first(); next(doc); }, - () => next => doc => { + () => (next: any) => (doc: any) => { second(); next(doc); }, @@ -63,7 +61,7 @@ describe('buildProcessorFunction(chain, ...args)', () => { series ); fn({}); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts similarity index 86% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts index 5896a089bafe2..b898f4dbf7a5e 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts @@ -17,11 +17,9 @@ * under the License. */ -export function buildProcessorFunction(chain, ...args) { +export function buildProcessorFunction(chain: any[], ...args: any) { return chain.reduceRight( - (next, fn) => { - return fn(...args)(next); - }, - doc => doc + (next, fn) => fn(...args)(next), + (doc: any) => doc ); } diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js similarity index 79% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js index dc2c2b2cfb1f2..f3e15f2fc65b6 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js @@ -17,27 +17,26 @@ * under the License. */ -import { expect } from 'chai'; -import { getIntervalAndTimefield } from '../get_interval_and_timefield'; +import { getIntervalAndTimefield } from './get_interval_and_timefield'; describe('getIntervalAndTimefield(panel, series)', () => { - it('returns the panel interval and timefield', () => { + test('returns the panel interval and timefield', () => { const panel = { time_field: '@timestamp', interval: 'auto' }; const series = {}; - expect(getIntervalAndTimefield(panel, series)).to.eql({ + expect(getIntervalAndTimefield(panel, series)).toEqual({ timeField: '@timestamp', interval: 'auto', }); }); - it('returns the series interval and timefield', () => { + test('returns the series interval and timefield', () => { const panel = { time_field: '@timestamp', interval: 'auto' }; const series = { override_index_pattern: true, series_interval: '1m', series_time_field: 'time', }; - expect(getIntervalAndTimefield(panel, series)).to.eql({ + expect(getIntervalAndTimefield(panel, series)).toEqual({ timeField: 'time', interval: '1m', }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js index 3def18997863e..db0e8fa3d6bb9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js @@ -94,4 +94,371 @@ describe('src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/bucket_tra }); }); }); + + describe('bucketTransform additional', () => { + describe('count', () => { + test('returns count agg', () => { + const metric = { id: 'test', type: 'count' }; + const fn = bucketTransform.count; + expect(fn(metric)).toEqual({ + bucket_script: { + buckets_path: { count: '_count' }, + script: { source: 'count * 1', lang: 'expression' }, + gap_policy: 'skip', + }, + }); + }); + }); + + describe('std metric', () => { + ['avg', 'max', 'min', 'sum', 'cardinality', 'value_count'].forEach(type => { + test(`returns ${type} agg`, () => { + const metric = { id: 'test', type: type, field: 'cpu.pct' }; + const fn = bucketTransform[type]; + const result = {}; + result[type] = { field: 'cpu.pct' }; + expect(fn(metric)).toEqual(result); + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.avg({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.avg({ id: 'test', type: 'avg' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('extended stats', () => { + ['std_deviation', 'variance', 'sum_of_squares'].forEach(type => { + test(`returns ${type} agg`, () => { + const fn = bucketTransform[type]; + const metric = { id: 'test', type: type, field: 'cpu.pct' }; + expect(fn(metric)).toEqual({ extended_stats: { field: 'cpu.pct' } }); + }); + }); + + test('returns std_deviation agg with sigma', () => { + const fn = bucketTransform.std_deviation; + const metric = { + id: 'test', + type: 'std_deviation', + field: 'cpu.pct', + sigma: 2, + }; + expect(fn(metric)).toEqual({ + extended_stats: { field: 'cpu.pct', sigma: 2 }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.std_deviation({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.std_deviation({ id: 'test', type: 'avg' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('percentiles', () => { + test('returns percentiles agg', () => { + const metric = { + id: 'test', + type: 'percentile', + field: 'cpu.pct', + percentiles: [ + { value: 50, mode: 'line' }, + { value: 10, mode: 'band', percentile: 90 }, + ], + }; + const fn = bucketTransform.percentile; + expect(fn(metric)).toEqual({ + percentiles: { + field: 'cpu.pct', + percents: [50, 10, 90], + }, + }); + }); + + test('define a default 0 value if it was not provided', () => { + const metric = { + id: 'test', + type: 'percentile', + field: 'cpu.pct', + percentiles: [ + { value: 50, mode: 'line' }, + { mode: 'line' }, + { value: undefined, mode: 'line' }, + { value: '', mode: 'line' }, + { value: null, mode: 'line' }, + { value: 0, mode: 'line' }, + ], + }; + expect(bucketTransform.percentile(metric)).toEqual({ + percentiles: { + field: 'cpu.pct', + percents: [50, 0, 0, 0, 0, 0], + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + field: 'cpu.pct', + percentiles: [{ value: 50, mode: 'line' }], + }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + type: 'avg', + percentiles: [{ value: 50, mode: 'line' }], + }); + expect(run).toThrow(new Error('Metric missing field')); + }); + + test('throws error if percentiles is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + type: 'avg', + field: 'cpu.pct', + }); + expect(run).toThrow(new Error('Metric missing percentiles')); + }); + }); + + describe('derivative', () => { + test('returns derivative agg with defaults', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'skip', + unit: '10s', + }, + }); + }); + + test('returns derivative agg with unit', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + unit: '1s', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'skip', + unit: '1s', + }, + }); + }); + + test('returns derivative agg with gap_policy', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + gap_policy: 'zero_fill', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'zero_fill', + unit: '10s', + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.derivative({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.derivative({ id: 'test', type: 'derivative' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('serial_diff', () => { + test('returns serial_diff agg with defaults', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'skip', + lag: 1, + }, + }); + }); + + test('returns serial_diff agg with lag', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + lag: 10, + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'skip', + lag: 10, + }, + }); + }); + + test('returns serial_diff agg with gap_policy', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + gap_policy: 'zero_fill', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'zero_fill', + lag: 1, + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.serial_diff({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.serial_diff({ id: 'test', type: 'serial_diff' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('cumulative_sum', () => { + test('returns cumulative_sum agg', () => { + const metric = { id: '2', type: 'cumulative_sum', field: '1' }; + const metrics = [{ id: '1', type: 'sum', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.cumulative_sum; + expect(fn(metric, metrics, '10s')).toEqual({ + cumulative_sum: { buckets_path: '1' }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.cumulative_sum({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.cumulative_sum({ id: 'test', type: 'cumulative_sum' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('calculation', () => { + test('returns calculation(bucket_script)', () => { + const metric = { + id: '2', + type: 'calculation', + script: 'params.idle != null ? 1 - params.idle : 0', + variables: [{ name: 'idle', field: '1' }], + }; + const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; + const fn = bucketTransform.calculation; + expect(fn(metric, metrics, '10s')).toEqual({ + bucket_script: { + buckets_path: { + idle: '1', + }, + gap_policy: 'skip', + script: { + source: 'params.idle != null ? 1 - params.idle : 0', + lang: 'painless', + params: { + _interval: 10000, + }, + }, + }, + }); + }); + + test('throws error if variables is missing', () => { + const run = () => + bucketTransform.calculation({ + id: 'test', + type: 'calculation', + script: 'params.idle != null ? 1 - params.idle : null', + }); + expect(run).toThrow(new Error('Metric missing variables')); + }); + + test('throws error if script is missing', () => { + const run = () => + bucketTransform.calculation({ + id: 'test', + type: 'calculation', + variables: [{ field: '1', name: 'idle' }], + }); + expect(run).toThrow(new Error('Metric missing script')); + }); + }); + + describe('positive_only', () => { + test('returns bucket_script', () => { + const metric = { + id: '2', + type: 'positive_only', + field: '1', + }; + const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; + const fn = bucketTransform.positive_only; + expect(fn(metric, metrics, '10s')).toEqual({ + bucket_script: { + buckets_path: { + value: '1', + }, + gap_policy: 'skip', + script: { + source: 'params.value > 0.0 ? params.value : 0.0', + lang: 'painless', + }, + }, + }); + }); + }); + }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js index 234953c8f4617..5f5e5ebafa560 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js @@ -17,16 +17,15 @@ * under the License. */ -import { expect } from 'chai'; -import { getAggValue } from '../../helpers/get_agg_value'; +import { getAggValue } from './get_agg_value'; function testAgg(row, metric, expected) { let name = metric.type; if (metric.mode) name += `(${metric.mode})`; if (metric.percent) name += `(${metric.percent})`; - it(`it should return ${name}(${expected})`, () => { + test(`it should return ${name}(${expected})`, () => { const value = getAggValue(row, metric); - expect(value).to.eql(expected); + expect(value).toEqual(expected); }); } diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js similarity index 54% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js index e62cfff1083cf..99bef2de6b72d 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getBucketSize } from '../../helpers/get_bucket_size'; +import { getBucketSize } from './get_bucket_size'; describe('getBucketSize', () => { const req = { @@ -30,39 +29,39 @@ describe('getBucketSize', () => { }, }; - it('returns auto calculated buckets', () => { + test('returns auto calculated buckets', () => { const result = getBucketSize(req, 'auto'); - expect(result).to.have.property('bucketSize', 30); - expect(result).to.have.property('intervalString', '30s'); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); }); - it('returns overridden buckets (1s)', () => { + test('returns overridden buckets (1s)', () => { const result = getBucketSize(req, '1s'); - expect(result).to.have.property('bucketSize', 1); - expect(result).to.have.property('intervalString', '1s'); + expect(result).toHaveProperty('bucketSize', 1); + expect(result).toHaveProperty('intervalString', '1s'); }); - it('returns overridden buckets (10m)', () => { + test('returns overridden buckets (10m)', () => { const result = getBucketSize(req, '10m'); - expect(result).to.have.property('bucketSize', 600); - expect(result).to.have.property('intervalString', '10m'); + expect(result).toHaveProperty('bucketSize', 600); + expect(result).toHaveProperty('intervalString', '10m'); }); - it('returns overridden buckets (1d)', () => { + test('returns overridden buckets (1d)', () => { const result = getBucketSize(req, '1d'); - expect(result).to.have.property('bucketSize', 86400); - expect(result).to.have.property('intervalString', '1d'); + expect(result).toHaveProperty('bucketSize', 86400); + expect(result).toHaveProperty('intervalString', '1d'); }); - it('returns overridden buckets (>=2d)', () => { + test('returns overridden buckets (>=2d)', () => { const result = getBucketSize(req, '>=2d'); - expect(result).to.have.property('bucketSize', 86400 * 2); - expect(result).to.have.property('intervalString', '2d'); + expect(result).toHaveProperty('bucketSize', 86400 * 2); + expect(result).toHaveProperty('intervalString', '2d'); }); - it('returns overridden buckets (>=10s)', () => { + test('returns overridden buckets (>=10s)', () => { const result = getBucketSize(req, '>=10s'); - expect(result).to.have.property('bucketSize', 30); - expect(result).to.have.property('intervalString', '30s'); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js similarity index 53% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js index f5c31fa8ba7ce..0a0e18a696588 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getBucketsPath } from '../../helpers/get_buckets_path'; +import { getBucketsPath } from './get_buckets_path'; describe('getBucketsPath', () => { const metrics = [ @@ -33,43 +32,43 @@ describe('getBucketsPath', () => { { id: 9, type: 'max' }, ]; - it('return path for derivative', () => { - expect(getBucketsPath(1, metrics)).to.equal('1[normalized_value]'); + test('return path for derivative', () => { + expect(getBucketsPath(1, metrics)).toEqual('1[normalized_value]'); }); - it('return path for percentile(50)', () => { - expect(getBucketsPath(2, metrics)).to.equal('2[50.0]'); + test('return path for percentile(50)', () => { + expect(getBucketsPath(2, metrics)).toEqual('2[50.0]'); }); - it('return path for percentile(20.0)', () => { - expect(getBucketsPath(3, metrics)).to.equal('3[20.0]'); + test('return path for percentile(20.0)', () => { + expect(getBucketsPath(3, metrics)).toEqual('3[20.0]'); }); - it('return path for percentile(10.0) with alt id', () => { - expect(getBucketsPath('3[10.0]', metrics)).to.equal('3[10.0]'); + test('return path for percentile(10.0) with alt id', () => { + expect(getBucketsPath('3[10.0]', metrics)).toEqual('3[10.0]'); }); - it('return path for std_deviation(raw)', () => { - expect(getBucketsPath(4, metrics)).to.equal('4[std_deviation]'); + test('return path for std_deviation(raw)', () => { + expect(getBucketsPath(4, metrics)).toEqual('4[std_deviation]'); }); - it('return path for std_deviation(upper)', () => { - expect(getBucketsPath(5, metrics)).to.equal('5[std_upper]'); + test('return path for std_deviation(upper)', () => { + expect(getBucketsPath(5, metrics)).toEqual('5[std_upper]'); }); - it('return path for std_deviation(lower)', () => { - expect(getBucketsPath(6, metrics)).to.equal('6[std_lower]'); + test('return path for std_deviation(lower)', () => { + expect(getBucketsPath(6, metrics)).toEqual('6[std_lower]'); }); - it('return path for sum_of_squares', () => { - expect(getBucketsPath(7, metrics)).to.equal('7[sum_of_squares]'); + test('return path for sum_of_squares', () => { + expect(getBucketsPath(7, metrics)).toEqual('7[sum_of_squares]'); }); - it('return path for variance', () => { - expect(getBucketsPath(8, metrics)).to.equal('8[variance]'); + test('return path for variance', () => { + expect(getBucketsPath(8, metrics)).toEqual('8[variance]'); }); - it('return path for basic metric', () => { - expect(getBucketsPath(9, metrics)).to.equal('9'); + test('return path for basic metric', () => { + expect(getBucketsPath(9, metrics)).toEqual('9'); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js similarity index 51% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js index 5cc94dda6d21a..2529c8c649485 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js @@ -17,44 +17,43 @@ * under the License. */ -import { expect } from 'chai'; -import { getDefaultDecoration } from '../../helpers/get_default_decoration'; +import { getDefaultDecoration } from './get_default_decoration'; describe('getDefaultDecoration', () => { describe('stack option', () => { - it('should set a stack option to none', () => { + test('should set a stack option to none', () => { const series = { id: 'test_id', stacked: 'none', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'none'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'none'); }); - it('should set a stack option to stacked/percent', () => { + test('should set a stack option to stacked/percent', () => { const series = { stacked: 'stacked', id: 'test_id', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'stacked'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'stacked'); series.stacked = 'percent'; - expect(getDefaultDecoration(series)).to.have.property('stack', 'percent'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'percent'); }); - it('should set a stack option to stacked_within_series', () => { + test('should set a stack option to stacked_within_series', () => { const series = { stacked: 'stacked_within_series', id: 'test_id', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'stacked_within_series'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'stacked_within_series'); }); }); describe('lines', () => { - it('return decoration for lines', () => { + test('return decoration for lines', () => { const series = { point_size: 10, chart_type: 'line', @@ -62,29 +61,29 @@ describe('getDefaultDecoration', () => { fill: 1, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', true); - expect(result.lines).to.have.property('fill', 1); - expect(result.lines).to.have.property('lineWidth', 10); - expect(result.points).to.have.property('show', true); - expect(result.points).to.have.property('radius', 1); - expect(result.points).to.have.property('lineWidth', 10); - expect(result.bars).to.have.property('show', false); - expect(result.bars).to.have.property('fill', 1); - expect(result.bars).to.have.property('lineWidth', 10); + expect(result.lines).toHaveProperty('show', true); + expect(result.lines).toHaveProperty('fill', 1); + expect(result.lines).toHaveProperty('lineWidth', 10); + expect(result.points).toHaveProperty('show', true); + expect(result.points).toHaveProperty('radius', 1); + expect(result.points).toHaveProperty('lineWidth', 10); + expect(result.bars).toHaveProperty('show', false); + expect(result.bars).toHaveProperty('fill', 1); + expect(result.bars).toHaveProperty('lineWidth', 10); }); - it('return decoration for lines without points', () => { + test('return decoration for lines without points', () => { const series = { chart_type: 'line', line_width: 10, fill: 1, }; const result = getDefaultDecoration(series); - expect(result.points).to.have.property('show', true); - expect(result.points).to.have.property('lineWidth', 10); + expect(result.points).toHaveProperty('show', true); + expect(result.points).toHaveProperty('lineWidth', 10); }); - it('return decoration for lines with points set to zero (off)', () => { + test('return decoration for lines with points set to zero (off)', () => { const series = { chart_type: 'line', line_width: 10, @@ -92,32 +91,32 @@ describe('getDefaultDecoration', () => { point_size: 0, }; const result = getDefaultDecoration(series); - expect(result.points).to.have.property('show', false); + expect(result.points).toHaveProperty('show', false); }); - it('return decoration for lines (off)', () => { + test('return decoration for lines (off)', () => { const series = { chart_type: 'line', line_width: 0, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', false); + expect(result.lines).toHaveProperty('show', false); }); }); describe('bars', () => { - it('return decoration for bars', () => { + test('return decoration for bars', () => { const series = { chart_type: 'bar', line_width: 10, fill: 1, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', false); - expect(result.points).to.have.property('show', false); - expect(result.bars).to.have.property('show', true); - expect(result.bars).to.have.property('fill', 1); - expect(result.bars).to.have.property('lineWidth', 10); + expect(result.lines).toHaveProperty('show', false); + expect(result.points).toHaveProperty('show', false); + expect(result.bars).toHaveProperty('show', true); + expect(result.bars).toHaveProperty('fill', 1); + expect(result.bars).toHaveProperty('lineWidth', 10); }); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js similarity index 82% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js index b19f6a3241597..13f62739a5485 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js @@ -17,11 +17,10 @@ * under the License. */ -import { expect } from 'chai'; -import { getEsShardTimeout } from '../../helpers/get_es_shard_timeout'; +import { getEsShardTimeout } from './get_es_shard_timeout'; describe('getEsShardTimeout', () => { - it('should return the elasticsearch.shardTimeout', async () => { + test('should return the elasticsearch.shardTimeout', async () => { const req = { getEsShardTimeout: async () => { return 12345; @@ -30,6 +29,6 @@ describe('getEsShardTimeout', () => { const timeout = await getEsShardTimeout(req); - expect(timeout).to.equal(12345); + expect(timeout).toEqual(12345); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js similarity index 76% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js index be99f81dfccc4..42e6cc2c01836 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js @@ -17,26 +17,25 @@ * under the License. */ -import { expect } from 'chai'; -import { getLastMetric } from '../../helpers/get_last_metric'; +import { getLastMetric } from './get_last_metric'; describe('getLastMetric(series)', () => { - it('returns the last metric', () => { + test('returns the last metric', () => { const series = { metrics: [ { id: 1, type: 'avg' }, { id: 2, type: 'moving_average' }, ], }; - expect(getLastMetric(series)).to.eql({ id: 2, type: 'moving_average' }); + expect(getLastMetric(series)).toEqual({ id: 2, type: 'moving_average' }); }); - it('returns the last metric that not a series_agg', () => { + test('returns the last metric that not a series_agg', () => { const series = { metrics: [ { id: 1, type: 'avg' }, { id: 2, type: 'series_agg' }, ], }; - expect(getLastMetric(series)).to.eql({ id: 1, type: 'avg' }); + expect(getLastMetric(series)).toEqual({ id: 1, type: 'avg' }); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js similarity index 69% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js index 68bfa77e25ea3..755568546949c 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getSiblingAggValue } from '../../helpers/get_sibling_agg_value'; +import { getSiblingAggValue } from './get_sibling_agg_value'; describe('getSiblingAggValue', () => { const row = { @@ -32,23 +31,23 @@ describe('getSiblingAggValue', () => { }, }; - it('returns the value for std_deviation_bounds.upper', () => { + test('returns the value for std_deviation_bounds.upper', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'upper' }; - expect(getSiblingAggValue(row, metric)).to.equal(2); + expect(getSiblingAggValue(row, metric)).toEqual(2); }); - it('returns the value for std_deviation_bounds.lower', () => { + test('returns the value for std_deviation_bounds.lower', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'lower' }; - expect(getSiblingAggValue(row, metric)).to.equal(1); + expect(getSiblingAggValue(row, metric)).toEqual(1); }); - it('returns the value for std_deviation', () => { + test('returns the value for std_deviation', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'raw' }; - expect(getSiblingAggValue(row, metric)).to.equal(1.5); + expect(getSiblingAggValue(row, metric)).toEqual(1.5); }); - it('returns the value for basic (max)', () => { + test('returns the value for basic (max)', () => { const metric = { id: 'test', type: 'max_bucket' }; - expect(getSiblingAggValue(row, metric)).to.equal(3); + expect(getSiblingAggValue(row, metric)).toEqual(3); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js similarity index 90% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js index 1057248d2f362..0874d944033f5 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js @@ -17,11 +17,10 @@ * under the License. */ -import { expect } from 'chai'; -import { getSplits } from '../../helpers/get_splits'; +import { getSplits } from './get_splits'; describe('getSplits(resp, panel, series)', () => { - it('should return a splits for everything/filter group bys', () => { + test('should return a splits for everything/filter group bys', () => { const resp = { aggregations: { SERIES: { @@ -41,7 +40,7 @@ describe('getSplits(resp, panel, series)', () => { { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, ], }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES', label: 'Overall Average of Average of cpu', @@ -53,7 +52,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for terms group bys for top_n', () => { + test('should return a splits for terms group bys for top_n', () => { const resp = { aggregations: { SERIES: { @@ -85,7 +84,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'top_n' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -107,7 +106,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for terms group bys', () => { + test('should return a splits for terms group bys', () => { const resp = { aggregations: { SERIES: { @@ -139,7 +138,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -161,7 +160,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for filters group bys', () => { + test('should return a splits for filters group bys', () => { const resp = { aggregations: { SERIES: { @@ -188,7 +187,7 @@ describe('getSplits(resp, panel, series)', () => { metrics: [{ id: 'COUNT', type: 'count' }], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:filter-1', key: 'filter-1', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js similarity index 72% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js index f79d1002b8546..1a1b12c651992 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js @@ -17,12 +17,11 @@ * under the License. */ -import { expect } from 'chai'; -import { getTimerange } from '../../helpers/get_timerange'; +import { getTimerange } from './get_timerange'; import moment from 'moment'; describe('getTimerange(req)', () => { - it('should return a moment object for to and from', () => { + test('should return a moment object for to and from', () => { const req = { payload: { timerange: { @@ -32,9 +31,9 @@ describe('getTimerange(req)', () => { }, }; const { from, to } = getTimerange(req); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toEqual(true); + expect(moment.isMoment(to)).toEqual(true); + expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).toEqual(true); + expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).toEqual(true); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js similarity index 72% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js index e3223ef7b618f..0b007416681ee 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js @@ -17,40 +17,39 @@ * under the License. */ -import { mapBucket } from '../../helpers/map_bucket'; -import { expect } from 'chai'; +import { mapBucket } from './map_bucket'; describe('mapBucket(metric)', () => { - it('returns bucket key and value for basic metric', () => { + test('returns bucket key and value for basic metric', () => { const metric = { id: 'AVG', type: 'avg' }; const bucket = { key: 1234, AVG: { value: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for std_deviation', () => { + test('returns bucket key and value for std_deviation', () => { const metric = { id: 'STDDEV', type: 'std_deviation' }; const bucket = { key: 1234, STDDEV: { std_deviation: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for percentiles', () => { + test('returns bucket key and value for percentiles', () => { const metric = { id: 'PCT', type: 'percentile', percent: 50 }; const bucket = { key: 1234, PCT: { values: { '50.0': 1 } }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for derivative', () => { + test('returns bucket key and value for derivative', () => { const metric = { id: 'DERV', type: 'derivative', field: 'io', unit: '1s' }; const bucket = { key: 1234, DERV: { value: 100, normalized_value: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js similarity index 70% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js index bf16b6e22e8ef..eab06cdccfa66 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js @@ -17,41 +17,40 @@ * under the License. */ -import { expect } from 'chai'; -import { parseSettings } from '../../helpers/parse_settings'; +import { parseSettings } from './parse_settings'; describe('parseSettings', () => { - it('returns the true for "true"', () => { + test('returns the true for "true"', () => { const settings = 'pad=true'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: true, }); }); - it('returns the false for "false"', () => { + test('returns the false for "false"', () => { const settings = 'pad=false'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: false, }); }); - it('returns the true for 1', () => { + test('returns the true for 1', () => { const settings = 'pad=1'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: true, }); }); - it('returns the false for 0', () => { + test('returns the false for 0', () => { const settings = 'pad=0'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: false, }); }); - it('returns the settings as an object', () => { + test('returns the settings as an object', () => { const settings = 'alpha=0.9 beta=0.4 gamma=0.2 period=5 pad=false type=add'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ alpha: 0.9, beta: 0.4, gamma: 0.2, diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js similarity index 64% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js index 55e43cf7bd8ce..b9b73002bafb3 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js @@ -17,12 +17,11 @@ * under the License. */ -import { expect } from 'chai'; import moment from 'moment'; -import { offsetTime } from '../offset_time'; +import { offsetTime } from './offset_time'; describe('offsetTime(req, by)', () => { - it('should return a moment object for to and from', () => { + test('should return a moment object for to and from', () => { const req = { payload: { timerange: { @@ -32,13 +31,13 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, ''); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); + expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).toBeTruthy(); + expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).toBeTruthy(); }); - it('should return a moment object for to and from offset by 1 hour', () => { + test('should return a moment object for to and from offset by 1 hour', () => { const req = { payload: { timerange: { @@ -48,23 +47,23 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, '1h'); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); expect( moment .utc('2017-01-01T00:00:00Z') .subtract(1, 'h') .isSame(from) - ).to.equal(true); + ).toBeTruthy(); expect( moment .utc('2017-01-01T01:00:00Z') .subtract(1, 'h') .isSame(to) - ).to.equal(true); + ).toBeTruthy(); }); - it('should return a moment object for to and from offset by -2 minute', () => { + test('should return a moment object for to and from offset by -2 minute', () => { const req = { payload: { timerange: { @@ -74,13 +73,13 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, '-2m'); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-10T01:02:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-10T02:02:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); + expect(moment.utc('2017-01-10T01:02:00Z').isSame(from)).toBeTruthy(); + expect(moment.utc('2017-01-10T02:02:00Z').isSame(to)).toBeTruthy(); }); - it('should work when prefixing positive offsets with the plus sign', () => { + test('should work when prefixing positive offsets with the plus sign', () => { const req = { payload: { timerange: { @@ -92,7 +91,7 @@ describe('offsetTime(req, by)', () => { const { from: fromSigned, to: toSigned } = offsetTime(req, '+1m'); const { from, to } = offsetTime(req, '1m'); - expect(fromSigned.isSame(from)).to.equal(true); - expect(toSigned.isSame(to)).to.equal(true); + expect(fromSigned.isSame(from)).toBeTruthy(); + expect(toSigned.isSame(to)).toBeTruthy(); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js similarity index 85% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js index 40eaba621aabb..7f309b44d13f4 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js @@ -17,10 +17,8 @@ * under the License. */ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { DefaultSearchCapabilities } from '../../../../search_strategies/default_search_capabilities'; -import { dateHistogram } from '../date_histogram'; +import { DefaultSearchCapabilities } from '../../../search_strategies/default_search_capabilities'; +import { dateHistogram } from './date_histogram'; describe('dateHistogram(req, panel, series)', () => { let panel; @@ -54,18 +52,18 @@ describe('dateHistogram(req, panel, series)', () => { capabilities = new DefaultSearchCapabilities(req); }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns valid date histogram', () => { + test('returns valid date histogram', () => { const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -93,13 +91,13 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - it('returns valid date histogram (offset by 1h)', () => { + test('returns valid date histogram (offset by 1h)', () => { series.offset_time = '1h'; const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -127,7 +125,7 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - it('returns valid date histogram with overridden index pattern', () => { + test('returns valid date histogram with overridden index pattern', () => { series.override_index_pattern = 1; series.series_index_pattern = '*'; series.series_time_field = 'timestamp'; @@ -136,7 +134,7 @@ describe('dateHistogram(req, panel, series)', () => { const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -165,7 +163,7 @@ describe('dateHistogram(req, panel, series)', () => { }); describe('dateHistogram for entire time range mode', () => { - it('should ignore entire range mode for timeseries', () => { + test('should ignore entire range mode for timeseries', () => { panel.time_range_mode = 'entire_time_range'; panel.type = 'timeseries'; @@ -174,18 +172,18 @@ describe('dateHistogram(req, panel, series)', () => { {} ); - expect(doc.aggs.test.aggs.timeseries.auto_date_histogram).to.eql(undefined); - expect(doc.aggs.test.aggs.timeseries.date_histogram).to.exist; + expect(doc.aggs.test.aggs.timeseries.auto_date_histogram).toBeUndefined(); + expect(doc.aggs.test.aggs.timeseries.date_histogram).toBeDefined(); }); - it('should returns valid date histogram for entire range mode', () => { + test('should returns valid date histogram for entire range mode', () => { panel.time_range_mode = 'entire_time_range'; const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js similarity index 92% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js index 0449ee440da81..f3d25a8e44ba7 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { ratios } from '../filter_ratios'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { ratios } from './filter_ratios'; describe('ratios(req, panel, series)', () => { let panel; @@ -55,16 +53,16 @@ describe('ratios(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); ratios(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns filter ratio aggs', () => { + test('returns filter ratio aggs', () => { const next = doc => doc; const doc = ratios(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -119,11 +117,11 @@ describe('ratios(req, panel, series)', () => { }); }); - it('returns empty object when field is not set', () => { + test('returns empty object when field is not set', () => { delete series.metrics[0].field; const next = doc => doc; const doc = ratios(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js similarity index 88% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js index 9393882f12b7e..eaf8ee1549f0b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { metricBuckets } from '../metric_buckets'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { metricBuckets } from './metric_buckets'; describe('metricBuckets(req, panel, series)', () => { let panel; @@ -63,16 +61,16 @@ describe('metricBuckets(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); metricBuckets(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns metric aggs', () => { + test('returns metric aggs', () => { const next = doc => doc; const doc = metricBuckets(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js similarity index 91% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js index 2f2e5f46f834e..06da636f818d5 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { query } from '../query'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { query } from './query'; describe('query(req, panel, series)', () => { let panel; @@ -47,16 +45,16 @@ describe('query(req, panel, series)', () => { series = { id: 'test' }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); query(req, panel, series, config)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns doc with query for timerange', () => { + test('returns doc with query for timerange', () => { const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -79,11 +77,11 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with query for timerange (offset by 1h)', () => { + test('returns doc with query for timerange (offset by 1h)', () => { series.offset_time = '1h'; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -106,7 +104,7 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with global query', () => { + test('returns doc with global query', () => { req.payload.filters = [ { bool: { @@ -122,7 +120,7 @@ describe('query(req, panel, series)', () => { ]; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -157,11 +155,11 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with series filter', () => { + test('returns doc with series filter', () => { series.filter = { query: 'host:web-server', language: 'lucene' }; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -198,7 +196,7 @@ describe('query(req, panel, series)', () => { }, }); }); - it('returns doc with panel filter and global', () => { + test('returns doc with panel filter and global', () => { req.payload.filters = [ { bool: { @@ -215,7 +213,7 @@ describe('query(req, panel, series)', () => { panel.filter = { query: 'host:web-server', language: 'lucene' }; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -265,7 +263,7 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with panel filter (ignoring globals)', () => { + test('returns doc with panel filter (ignoring globals)', () => { req.payload.filters = [ { bool: { @@ -283,7 +281,7 @@ describe('query(req, panel, series)', () => { panel.ignore_global_filter = true; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js similarity index 86% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js index 0f02c755cabcd..8e1c9b0f9ecd9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { siblingBuckets } from '../sibling_buckets'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { siblingBuckets } from './sibling_buckets'; describe('siblingBuckets(req, panel, series)', () => { let panel; @@ -57,16 +55,16 @@ describe('siblingBuckets(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); siblingBuckets(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns sibling aggs', () => { + test('returns sibling aggs', () => { const next = doc => doc; const doc = siblingBuckets(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js similarity index 83% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js index 4e2775d3608e6..5c2468f6b7c35 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByEverything } from '../split_by_everything'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByEverything } from './split_by_everything'; describe('splitByEverything(req, panel, series)', () => { let panel; @@ -39,15 +37,15 @@ describe('splitByEverything(req, panel, series)', () => { }); it('calls next when finished', () => { - const next = sinon.spy(); + const next = jest.fn(); splitByEverything(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); it('returns a valid filter with match_all', () => { const next = doc => doc; const doc = splitByEverything(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filter: { @@ -61,9 +59,9 @@ describe('splitByEverything(req, panel, series)', () => { it('calls next and does not add a filter', () => { series.split_mode = 'terms'; series.terms_field = 'host'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByEverything(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js similarity index 79% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js index 782310ba4d2bf..75ca782a6d7e7 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByFilter } from '../split_by_filter'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByFilter } from './split_by_filter'; describe('splitByFilter(req, panel, series)', () => { let panel; @@ -42,16 +40,16 @@ describe('splitByFilter(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByFilter(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid filter with a query_string', () => { + test('returns a valid filter with a query_string', () => { const next = doc => doc; const doc = splitByFilter(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filter: { @@ -73,11 +71,11 @@ describe('splitByFilter(req, panel, series)', () => { }); }); - it('calls next and does not add a filter', () => { + test('calls next and does not add a filter', () => { series.split_mode = 'terms'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByFilter(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js similarity index 85% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js index 018cb4b003ecf..6108b2bf2cf2b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByFilters } from '../split_by_filters'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByFilters } from './split_by_filters'; describe('splitByFilters(req, panel, series)', () => { let panel; @@ -58,16 +56,16 @@ describe('splitByFilters(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByFilters(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid terms agg', () => { + test('returns a valid terms agg', () => { const next = doc => doc; const doc = splitByFilters(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filters: { @@ -107,11 +105,11 @@ describe('splitByFilters(req, panel, series)', () => { }); }); - it('calls next and does not add a terms agg', () => { + test('calls next and does not add a terms agg', () => { series.split_mode = 'everything'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByFilters(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js similarity index 80% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js index eb1a81baa7fc2..ff7139c380af9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByTerms } from '../split_by_terms'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByTerms } from './split_by_terms'; describe('splitByTerms(req, panel, series)', () => { let panel; @@ -46,16 +44,16 @@ describe('splitByTerms(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByTerms(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid terms agg', () => { + test('returns a valid terms agg', () => { const next = doc => doc; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -70,12 +68,12 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('returns a valid terms agg sort by terms', () => { + test('returns a valid terms agg sort by terms', () => { const next = doc => doc; series.terms_order_by = '_key'; series.terms_direction = 'asc'; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -90,11 +88,11 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('returns a valid terms agg with custom sort', () => { + test('returns a valid terms agg with custom sort', () => { series.terms_order_by = 'avgmetric'; const next = doc => doc; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -116,11 +114,11 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('calls next and does not add a terms agg', () => { + test('calls next and does not add a terms agg', () => { series.split_mode = 'everything'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByTerms(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js similarity index 68% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js index 582466f8eb9fd..22ea2c852e254 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { SeriesAgg as seriesAgg } from '../_series_agg'; +import { SeriesAgg as seriesAgg } from './_series_agg'; describe('seriesAgg', () => { const series = [ @@ -40,8 +39,8 @@ describe('seriesAgg', () => { ]; describe('basic', () => { - it('returns the series sum', () => { - expect(seriesAgg.sum(series)).to.eql([ + test('returns the series sum', () => { + expect(seriesAgg.sum(series)).toEqual([ [ [0, 8], [1, 4], @@ -50,8 +49,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series max', () => { - expect(seriesAgg.max(series)).to.eql([ + test('returns the series max', () => { + expect(seriesAgg.max(series)).toEqual([ [ [0, 4], [1, 2], @@ -60,8 +59,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series min', () => { - expect(seriesAgg.min(series)).to.eql([ + test('returns the series min', () => { + expect(seriesAgg.min(series)).toEqual([ [ [0, 2], [1, 1], @@ -70,8 +69,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series mean', () => { - expect(seriesAgg.mean(series)).to.eql([ + test('returns the series mean', () => { + expect(seriesAgg.mean(series)).toEqual([ [ [0, 8 / 3], [1, 4 / 3], @@ -82,8 +81,8 @@ describe('seriesAgg', () => { }); describe('overall', () => { - it('returns the series overall sum', () => { - expect(seriesAgg.overall_sum(series)).to.eql([ + test('returns the series overall sum', () => { + expect(seriesAgg.overall_sum(series)).toEqual([ [ [0, 21], [1, 21], @@ -92,8 +91,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall max', () => { - expect(seriesAgg.overall_max(series)).to.eql([ + test('returns the series overall max', () => { + expect(seriesAgg.overall_max(series)).toEqual([ [ [0, 4], [1, 4], @@ -102,8 +101,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall min', () => { - expect(seriesAgg.overall_min(series)).to.eql([ + test('returns the series overall min', () => { + expect(seriesAgg.overall_min(series)).toEqual([ [ [0, 1], [1, 1], @@ -112,9 +111,9 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall mean', () => { + test('returns the series overall mean', () => { const value = (8 + 4 + 9) / 3; - expect(seriesAgg.overall_avg(series)).to.eql([ + expect(seriesAgg.overall_avg(series)).toEqual([ [ [0, value], [1, value], @@ -125,8 +124,8 @@ describe('seriesAgg', () => { }); describe('cumulative sum', () => { - it('returns the series cumulative sum', () => { - expect(seriesAgg.cumulative_sum(series)).to.eql([ + test('returns the series cumulative sum', () => { + expect(seriesAgg.cumulative_sum(series)).toEqual([ [ [0, 8], [1, 12], diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js similarity index 57% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js index d40a75c903602..9cb08de8dad23 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { percentile } from '../percentile'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { percentile } from './percentile'; describe('percentile(resp, panel, series)', () => { let panel; @@ -82,72 +80,72 @@ describe('percentile(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); percentile(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = percentile(resp, panel, series)(next)([]); - expect(results).to.have.length(3); + expect(results).toHaveLength(3); - expect(results[0]).to.have.property('id', 'test:10-90'); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('fillBetween', 'test:10-90:90'); - expect(results[0]).to.have.property('label', 'Percentile of cpu (10)'); - expect(results[0]).to.have.property('legend', false); - expect(results[0]).to.have.property('lines'); - expect(results[0].lines).to.eql({ + expect(results[0]).toHaveProperty('id', 'test:10-90'); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('fillBetween', 'test:10-90:90'); + expect(results[0]).toHaveProperty('label', 'Percentile of cpu (10)'); + expect(results[0]).toHaveProperty('legend', false); + expect(results[0]).toHaveProperty('lines'); + expect(results[0].lines).toEqual({ fill: 0.2, lineWidth: 0, show: true, }); - expect(results[0]).to.have.property('points'); - expect(results[0].points).to.eql({ show: false }); - expect(results[0].data).to.eql([ + expect(results[0]).toHaveProperty('points'); + expect(results[0].points).toEqual({ show: false }); + expect(results[0].data).toEqual([ [1, 1], [2, 1.2], ]); - expect(results[1]).to.have.property('id', 'test:10-90:90'); - expect(results[1]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[1]).to.have.property('label', 'Percentile of cpu (10)'); - expect(results[1]).to.have.property('legend', false); - expect(results[1]).to.have.property('lines'); - expect(results[1].lines).to.eql({ + expect(results[1]).toHaveProperty('id', 'test:10-90:90'); + expect(results[1]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[1]).toHaveProperty('label', 'Percentile of cpu (10)'); + expect(results[1]).toHaveProperty('legend', false); + expect(results[1]).toHaveProperty('lines'); + expect(results[1].lines).toEqual({ fill: false, lineWidth: 0, show: true, }); - expect(results[1]).to.have.property('points'); - expect(results[1].points).to.eql({ show: false }); - expect(results[1].data).to.eql([ + expect(results[1]).toHaveProperty('points'); + expect(results[1].points).toEqual({ show: false }); + expect(results[1].data).toEqual([ [1, 5], [2, 5.3], ]); - expect(results[2]).to.have.property('id', 'test:50'); - expect(results[2]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[2]).to.have.property('label', 'Percentile of cpu (50)'); - expect(results[2]).to.have.property('stack', false); - expect(results[2]).to.have.property('lines'); - expect(results[2].lines).to.eql({ + expect(results[2]).toHaveProperty('id', 'test:50'); + expect(results[2]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[2]).toHaveProperty('label', 'Percentile of cpu (50)'); + expect(results[2]).toHaveProperty('stack', false); + expect(results[2]).toHaveProperty('lines'); + expect(results[2].lines).toEqual({ fill: 0, lineWidth: 1, show: true, steps: false, }); - expect(results[2]).to.have.property('bars'); - expect(results[2].bars).to.eql({ + expect(results[2]).toHaveProperty('bars'); + expect(results[2].bars).toEqual({ fill: 0, lineWidth: 1, show: false, }); - expect(results[2]).to.have.property('points'); - expect(results[2].points).to.eql({ show: true, lineWidth: 1, radius: 1 }); - expect(results[2].data).to.eql([ + expect(results[2]).toHaveProperty('points'); + expect(results[2].points).toEqual({ show: true, lineWidth: 1, radius: 1 }); + expect(results[2].data).toEqual([ [1, 2.5], [2, 2.7], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js similarity index 88% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js index 2391cd3bc7698..3e09c51d9184f 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js @@ -17,10 +17,8 @@ * under the License. */ -import { seriesAgg } from '../series_agg'; -import { stdMetric } from '../std_metric'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { seriesAgg } from './series_agg'; +import { stdMetric } from './std_metric'; describe('seriesAgg(resp, panel, series)', () => { let panel; @@ -93,18 +91,18 @@ describe('seriesAgg(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); seriesAgg(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = seriesAgg(resp, panel, series)(results => results); const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); + expect(results).toHaveLength(1); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test', color: '#F00', label: 'Total CPU', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js similarity index 87% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js index 488ae4a8351b7..77949ff94dc4c 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdDeviationBands } from '../std_deviation_bands'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdDeviationBands } from './std_deviation_bands'; describe('stdDeviationBands(resp, panel, series)', () => { let panel; @@ -79,18 +77,18 @@ describe('stdDeviationBands(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdDeviationBands(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdDeviationBands(resp, panel, series)(next)([]); - expect(results).to.have.length(2); + expect(results).toHaveLength(2); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test:upper', label: 'Std. Deviation of cpu', color: 'rgb(255, 0, 0)', @@ -103,7 +101,7 @@ describe('stdDeviationBands(resp, panel, series)', () => { ], }); - expect(results[1]).to.eql({ + expect(results[1]).toEqual({ id: 'test:lower', color: 'rgb(255, 0, 0)', lines: { show: true, fill: false, lineWidth: 0 }, diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js similarity index 87% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js index 14c2c16ef728f..adc5a3a4a991b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdDeviationSibling } from '../std_deviation_sibling'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdDeviationSibling } from './std_deviation_sibling'; describe('stdDeviationSibling(resp, panel, series)', () => { let panel; @@ -79,18 +77,18 @@ describe('stdDeviationSibling(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdDeviationSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdDeviationSibling(resp, panel, series)(next)([]); - expect(results).to.have.length(2); + expect(results).toHaveLength(2); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test:lower', color: 'rgb(255, 0, 0)', lines: { show: true, fill: false, lineWidth: 0 }, @@ -101,7 +99,7 @@ describe('stdDeviationSibling(resp, panel, series)', () => { ], }); - expect(results[1]).to.eql({ + expect(results[1]).toEqual({ id: 'test:upper', label: 'Overall Std. Deviation of Average of cpu', color: 'rgb(255, 0, 0)', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js similarity index 65% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js index 5039a406a6acc..6ddd6f907fa97 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js @@ -17,9 +17,7 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { stdMetric } from '../std_metric'; +import { stdMetric } from './std_metric'; describe('stdMetric(resp, panel, series)', () => { let panel; @@ -60,41 +58,41 @@ describe('stdMetric(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('calls next when finished (percentile)', () => { + test('calls next when finished (percentile)', () => { series.metrics[0].type = 'percentile'; - const next = sinon.spy(d => d); + const next = jest.fn(d => d); const results = stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('calls next when finished (std_deviation band)', () => { + test('calls next when finished (std_deviation band)', () => { series.metrics[0].type = 'std_deviation'; series.metrics[0].mode = 'band'; - const next = sinon.spy(d => d); + const next = jest.fn(d => d); const results = stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('id', 'test'); - expect(results[0]).to.have.property('label', 'Average of cpu'); - expect(results[0]).to.have.property('lines'); - expect(results[0]).to.have.property('stack'); - expect(results[0]).to.have.property('bars'); - expect(results[0]).to.have.property('points'); - expect(results[0].data).to.eql([ + expect(results).toHaveLength(1); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('id', 'test'); + expect(results[0]).toHaveProperty('label', 'Average of cpu'); + expect(results[0]).toHaveProperty('lines'); + expect(results[0]).toHaveProperty('stack'); + expect(results[0]).toHaveProperty('bars'); + expect(results[0]).toHaveProperty('points'); + expect(results[0].data).toEqual([ [1, 1], [2, 2], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js similarity index 82% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js index a243ad525332c..9ed60a6d16492 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdSibling } from '../std_sibling'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdSibling } from './std_sibling'; describe('stdSibling(resp, panel, series)', () => { let panel; @@ -74,26 +72,26 @@ describe('stdSibling(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('calls next when std. deviation bands set', () => { + test('calls next when std. deviation bands set', () => { series.metrics[1].mode = 'band'; - const next = sinon.spy(results => results); + const next = jest.fn(results => results); const results = stdSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdSibling(resp, panel, series)(next)([]); - expect(results).to.have.length(1); + expect(results).toHaveLength(1); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test', label: 'Overall Std. Deviation of Average of cpu', color: 'rgb(255, 0, 0)', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js similarity index 71% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js index 1e6da85f88164..7047c54fa1c0e 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js @@ -17,10 +17,8 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { timeShift } from '../time_shift'; -import { stdMetric } from '../std_metric'; +import { timeShift } from './time_shift'; +import { stdMetric } from './std_metric'; describe('timeShift(resp, panel, series)', () => { let panel; @@ -62,24 +60,24 @@ describe('timeShift(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); timeShift(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = timeShift(resp, panel, series)(results => results); const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('id', 'test'); - expect(results[0]).to.have.property('label', 'Average of cpu'); - expect(results[0]).to.have.property('lines'); - expect(results[0]).to.have.property('stack'); - expect(results[0]).to.have.property('bars'); - expect(results[0]).to.have.property('points'); - expect(results[0].data).to.eql([ + expect(results).toHaveLength(1); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('id', 'test'); + expect(results[0]).toHaveProperty('label', 'Average of cpu'); + expect(results[0]).toHaveProperty('lines'); + expect(results[0]).toHaveProperty('stack'); + expect(results[0]).toHaveProperty('bars'); + expect(results[0]).toHaveProperty('points'); + expect(results[0].data).toEqual([ [1483225200000 + 3600000, 1], [1483225210000 + 3600000, 2], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts index f21bf3d197969..0c75e6ef1c5bd 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts @@ -17,6 +17,8 @@ * under the License. */ +import { buildRequestBody } from './build_request_body'; + const body = JSON.parse(` { "filters": [ @@ -75,15 +77,11 @@ const body = JSON.parse(` } `); -import sinon from 'sinon'; -import { expect } from 'chai'; -import { buildRequestBody } from '../build_request_body'; - describe('buildRequestBody(req)', () => { - it('returns a valid body', () => { + test('returns a valid body', () => { const panel = body.panels[0]; const series = panel.series[0]; - const getValidTimeInterval = sinon.spy(() => '10s'); + const getValidTimeInterval = jest.fn(() => '10s'); const capabilities = { searchTimezone: 'UTC', getValidTimeInterval, @@ -102,7 +100,7 @@ describe('buildRequestBody(req)', () => { capabilities ); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts index fe3137a8f86ba..85e1f8f7eb12b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts @@ -18,6 +18,7 @@ */ import { buildProcessorFunction } from '../build_processor_function'; +// @ts-ignore import { processors } from '../request_processors/series'; /** @@ -33,7 +34,7 @@ import { processors } from '../request_processors/series'; * ] * @returns {Object} doc - processed body */ -export function buildRequestBody(...args) { +export function buildRequestBody(...args: any[]) { const processor = buildProcessorFunction(processors, ...args); const doc = processor({}); return doc; diff --git a/src/legacy/core_plugins/vis_type_vislib/index.ts b/src/legacy/core_plugins/vis_type_vislib/index.ts new file mode 100644 index 0000000000000..8c24368f43ab1 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/index.ts @@ -0,0 +1,44 @@ +/* + * 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 { resolve } from 'path'; +import { Legacy } from 'kibana'; + +import { LegacyPluginApi, LegacyPluginInitializer } from '../../types'; + +const kbnVislibVisTypesPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPluginApi) => + new Plugin({ + id: 'vis_type_vislib', + require: ['kibana', 'elasticsearch', 'visualizations', 'interpreter', 'data'], + publicDir: resolve(__dirname, 'public'), + styleSheetPaths: resolve(__dirname, 'public/index.scss'), + uiExports: { + hacks: [resolve(__dirname, 'public/legacy')], + injectDefaultVars: server => ({}), + }, + init: (server: Legacy.Server) => ({}), + config(Joi: any) { + return Joi.object({ + enabled: Joi.boolean().default(true), + }).default(); + }, + } as Legacy.PluginSpecOptions); + +// eslint-disable-next-line import/no-default-export +export default kbnVislibVisTypesPluginInitializer; diff --git a/src/legacy/core_plugins/vis_type_vislib/package.json b/src/legacy/core_plugins/vis_type_vislib/package.json new file mode 100644 index 0000000000000..e30a9e2b35834 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/package.json @@ -0,0 +1,4 @@ +{ + "name": "vis_type_vislib", + "version": "kibana" +} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/__snapshots__/pie_fn.test.js.snap b/src/legacy/core_plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/__snapshots__/pie_fn.test.js.snap rename to src/legacy/core_plugins/vis_type_vislib/public/__snapshots__/pie_fn.test.ts.snap diff --git a/src/legacy/core_plugins/vis_type_vislib/public/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/_index.scss new file mode 100644 index 0000000000000..64445648ba84a --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/_index.scss @@ -0,0 +1 @@ +@import './vislib/index' diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js b/src/legacy/core_plugins/vis_type_vislib/public/area.ts similarity index 89% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js rename to src/legacy/core_plugins/vis_type_vislib/public/area.ts index fd13067c84cc0..9484ddc16fe62 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/area.ts @@ -18,8 +18,12 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; +// @ts-ignore +import { palettes } from '@elastic/eui/lib/services'; +// @ts-ignore +import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; + +import { Schemas, AggGroupNames } from './legacy_imports'; import { Positions, ChartTypes, @@ -33,17 +37,17 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { KbnVislibVisTypesDependencies } from './plugin'; -export const areaDefinition = { +export const createAreaVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'area', title: i18n.translate('kbnVislibVisTypes.area.areaTitle', { defaultMessage: 'Area' }), icon: 'visArea', description: i18n.translate('kbnVislibVisTypes.area.areaDescription', { defaultMessage: 'Emphasize the quantity beneath a line chart', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'area', @@ -132,7 +136,9 @@ export const areaDefinition = { { group: AggGroupNames.Metrics, name: 'metric', - title: i18n.translate('kbnVislibVisTypes.area.metricsTitle', { defaultMessage: 'Y-axis' }), + title: i18n.translate('kbnVislibVisTypes.area.metricsTitle', { + defaultMessage: 'Y-axis', + }), aggFilter: ['!geo_centroid', '!geo_bounds'], min: 1, defaults: [{ schema: 'metric', type: 'count' }], @@ -140,7 +146,9 @@ export const areaDefinition = { { group: AggGroupNames.Metrics, name: 'radius', - title: i18n.translate('kbnVislibVisTypes.area.radiusTitle', { defaultMessage: 'Dot size' }), + title: i18n.translate('kbnVislibVisTypes.area.radiusTitle', { + defaultMessage: 'Dot size', + }), min: 0, max: 1, aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality'], @@ -148,7 +156,9 @@ export const areaDefinition = { { group: AggGroupNames.Buckets, name: 'segment', - title: i18n.translate('kbnVislibVisTypes.area.segmentTitle', { defaultMessage: 'X-axis' }), + title: i18n.translate('kbnVislibVisTypes.area.segmentTitle', { + defaultMessage: 'X-axis', + }), min: 0, max: 1, aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'], @@ -175,4 +185,4 @@ export const areaDefinition = { }, ]), }, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/basic_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/basic_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx index 2bffcb383dde3..81174d63060e5 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/basic_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../legacy_imports'; import { SwitchOption } from './switch'; import { SelectOption } from './select'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx index 947c7ae7e6e36..2bf58de2f93ed 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx @@ -19,9 +19,10 @@ import React, { useCallback } from 'react'; import { last } from 'lodash'; + import { i18n } from '@kbn/i18n'; -import { RangeValues, RangesParamEditor } from 'ui/vis/editors/default/controls/ranges'; +import { RangeValues, RangesParamEditor } from '../../legacy_imports'; interface ColorRangesProps { 'data-test-subj'?: string; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_schema.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_schema.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_schema.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/color_schema.tsx index 44837c514d4cf..7b4679ba25e8f 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_schema.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_schema.tsx @@ -22,8 +22,7 @@ import { i18n } from '@kbn/i18n'; import { EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; -import { ColorSchema } from 'ui/vislib/components/color/colormaps'; +import { VisOptionsProps, ColorSchema } from '../../legacy_imports'; import { SelectOption } from './select'; import { SwitchOption } from './switch'; import { ColorSchemaVislibParams } from '../../types'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/index.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/number_input.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/number_input.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/number_input.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/range.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/range.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/range.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/range.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/required_number_input.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/required_number_input.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/required_number_input.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/required_number_input.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/select.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/select.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/switch.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/switch.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/switch.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/switch.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/text_input.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/text_input.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/text_input.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/text_input.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/truncate_labels.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/truncate_labels.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/truncate_labels.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/utils.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/common/utils.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/utils.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/utils.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/common/validation_wrapper.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/common/validation_wrapper.tsx index 1dd1ab49d9a47..b38c65d086823 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/validation_wrapper.tsx @@ -18,7 +18,8 @@ */ import React, { useEffect, useState, useCallback } from 'react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; + +import { VisOptionsProps } from '../../legacy_imports'; export interface ValidationVisOptionsProps extends VisOptionsProps { setMultipleValidity(paramName: string, isValid: boolean): void; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/index.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/index.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/index.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/index.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/index.tsx similarity index 97% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/index.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/index.tsx index e3805027d658c..2ba4319a82a95 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/index.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/index.tsx @@ -20,7 +20,7 @@ import React, { useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { GaugeVisParams } from '../../../gauge'; import { RangesPanel } from './ranges_panel'; import { StylePanel } from './style_panel'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/labels_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx index 1045543512c6b..71ffb22243a0f 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx @@ -22,7 +22,7 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; +import { ColorSchemas } from '../../../legacy_imports'; import { ColorRanges, ColorSchemaOptions, SwitchOption } from '../../common'; import { GaugeOptionsInternalProps } from '.'; import { ColorSchemaVislibParams } from '../../../types'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx similarity index 97% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx index a76171673d9a8..0b4986ae8ad80 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/style_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx @@ -22,7 +22,7 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { AggGroupNames } from 'ui/vis/editors/default'; +import { AggGroupNames } from '../../../legacy_imports'; import { SelectOption } from '../../common'; import { GaugeOptionsInternalProps } from '.'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/index.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/index.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx index 659bcf47f7a0b..7ce38fdcda1c8 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/index.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx @@ -18,11 +18,12 @@ */ import React, { useCallback, useEffect, useState } from 'react'; + import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { BasicOptions, ColorRanges, diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/labels_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/labels_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx index c0e9a70e8b11e..6ca0bb26ef535 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/heatmap/labels_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx @@ -18,11 +18,12 @@ */ import React, { useCallback } from 'react'; + import { EuiColorPicker, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { ValueAxis } from '../../../types'; import { HeatmapVisParams } from '../../../heatmap'; import { SwitchOption } from '../../common'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/index.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/index.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/index.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/chart_options.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/custom_extents_options.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/index.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/line_options.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/value_axis_options.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/__snapshots__/y_extents.test.tsx.snap diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx index a32e48baf4588..69622bb3666a6 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.test.tsx @@ -25,6 +25,8 @@ import { Positions, getPositions } from '../../../utils/collections'; import { LabelOptions } from './label_options'; import { categoryAxis } from './mocks'; +jest.mock('ui/new_platform'); + const positions = getPositions(); describe('CategoryAxisPanel component', () => { diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx index 11946a5a6bccd..b83508f3f0896 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx @@ -18,11 +18,12 @@ */ import React, { useCallback } from 'react'; + import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { BasicVislibParams, Axis } from '../../../types'; import { SelectOption, SwitchOption } from '../../common'; import { LabelOptions } from './label_options'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.test.tsx index ba1a46ba7d89e..9679728a2a3d1 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.test.tsx @@ -31,6 +31,8 @@ import { } from '../../../utils/collections'; import { valueAxis, seriesParam } from './mocks'; +jest.mock('ui/new_platform'); + const interpolationModes = getInterpolationModes(); const chartTypes = getChartTypes(); const chartModes = getChartModes(); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx index 1c9357c67c2f0..8830c9164c751 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/chart_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx @@ -18,10 +18,11 @@ */ import React, { useMemo, useCallback } from 'react'; + import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { BasicVislibParams, SeriesParam, ValueAxis } from '../../../types'; import { ChartTypes } from '../../../utils/collections'; import { SelectOption } from '../../common'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx index 5f1779ad35304..a112b9a3db708 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.test.tsx @@ -28,6 +28,8 @@ const DEFAULT_Y_EXTENTS = 'defaultYExtents'; const SCALE = 'scale'; const SET_Y_EXTENTS = 'setYExtents'; +jest.mock('ui/new_platform'); + describe('CustomExtentsOptions component', () => { let setValueAxis: jest.Mock; let setValueAxisScale: jest.Mock; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx index dc5cf42277603..df1920bd4013c 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.test.tsx @@ -19,6 +19,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; + import { MetricsAxisOptions } from './index'; import { BasicVislibParams, SeriesParam, ValueAxis } from '../../../types'; import { ValidationVisOptionsProps } from '../../common'; @@ -26,10 +27,10 @@ import { Positions } from '../../../utils/collections'; import { ValueAxesPanel } from './value_axes_panel'; import { CategoryAxisPanel } from './category_axis_panel'; import { ChartTypes } from '../../../utils/collections'; -import { AggConfig } from 'ui/vis'; -import { AggType } from 'ui/agg_types'; +import { AggConfig, AggType } from '../../../legacy_imports'; import { defaultValueAxisId, valueAxis, seriesParam, categoryAxis } from './mocks'; +jest.mock('ui/new_platform'); jest.mock('./series_panel', () => ({ SeriesPanel: () => 'SeriesPanel', })); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx index 2ca4ed1e2343d..85077ed492331 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/index.tsx @@ -21,7 +21,7 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { cloneDeep, uniq, get } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; -import { AggConfig } from 'ui/vis'; +import { AggConfig } from '../../../legacy_imports'; import { BasicVislibParams, ValueAxis, SeriesParam, Axis } from '../../../types'; import { ValidationVisOptionsProps } from '../../common'; import { SeriesPanel } from './series_panel'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.test.tsx index abb3a2455f9f9..91d9987c77f3b 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.test.tsx @@ -23,6 +23,8 @@ import { LabelOptions, LabelOptionsProps } from './label_options'; import { TruncateLabelsOption } from '../../common'; import { valueAxis, categoryAxis } from './mocks'; +jest.mock('ui/new_platform'); + const FILTER = 'filter'; const ROTATE = 'rotate'; const DISABLED = 'disabled'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx index 427d43e18cca6..6a94eabe25243 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/label_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx @@ -18,11 +18,12 @@ */ import React, { useCallback, useMemo } from 'react'; + import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { BasicVislibParams, Axis } from '../../../types'; import { SelectOption, SwitchOption, TruncateLabelsOption } from '../../common'; import { getRotateOptions } from '../../../utils/collections'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx index 0e603814493fa..98ef8a094a260 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx @@ -24,6 +24,8 @@ import { NumberInputOption } from '../../common'; import { getInterpolationModes } from '../../../utils/collections'; import { seriesParam } from './mocks'; +jest.mock('ui/new_platform'); + const LINE_WIDTH = 'lineWidth'; const DRAW_LINES = 'drawLinesBetweenPoints'; const interpolationModes = getInterpolationModes(); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx index 9514b69a20b04..0848b708b9094 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/line_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx @@ -18,10 +18,11 @@ */ import React, { useCallback } from 'react'; + import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { Vis } from 'ui/vis'; +import { Vis } from '../../../legacy_imports'; import { SeriesParam } from '../../../types'; import { NumberInputOption, SelectOption, SwitchOption } from '../../common'; import { SetChart } from './chart_options'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/mocks.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/mocks.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx similarity index 97% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx index 5a455f4adde31..4d87cc61797fc 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/series_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/series_panel.tsx @@ -18,11 +18,12 @@ */ import React from 'react'; + import { EuiPanel, EuiTitle, EuiSpacer, EuiAccordion } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { BasicVislibParams } from '../../../types'; import { ChartOptions } from './chart_options'; import { SetParamByIndex, ChangeValueAxis } from './'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts index 7144b0ad4902e..7c4f3b3ec8843 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/utils.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/utils.ts @@ -44,7 +44,7 @@ const makeSerie = ( }; const isAxisHorizontal = (position: Positions) => - [Positions.TOP, Positions.BOTTOM].includes(position); + [Positions.TOP, Positions.BOTTOM].includes(position as any); const RADIX = 10; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx index 080c64db7ff85..7524c7a13435b 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.test.tsx @@ -25,6 +25,8 @@ import { Positions, getScaleTypes, getAxisModes, getPositions } from '../../../u import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { valueAxis, seriesParam } from './mocks'; +jest.mock('ui/new_platform'); + const positions = getPositions(); const axisModes = getAxisModes(); const scaleTypes = getScaleTypes(); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/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 similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axes_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axes_panel.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx index 8cb476508c78b..bd512e9365783 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx @@ -32,6 +32,8 @@ import { } from '../../../utils/collections'; import { valueAxis, categoryAxis } from './mocks'; +jest.mock('ui/new_platform'); + const POSITION = 'position'; const positions = getPositions(); const axisModes = getAxisModes(); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/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 similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/value_axis_options.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx index 243950b762390..b4ea4cb42ee60 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/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 @@ -100,7 +100,7 @@ function ValueAxisOptions(props: ValueAxisOptionsParams) { if (isCategoryAxisHorizontal) { return isAxisHorizontal(position); } - return [Positions.LEFT, Positions.RIGHT].includes(position); + return [Positions.LEFT, Positions.RIGHT].includes(position as any); }, [isCategoryAxisHorizontal] ); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx similarity index 99% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.test.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx index 2df17b6e34985..17c47b35b20dc 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx @@ -23,6 +23,8 @@ import { YExtents, YExtentsProps } from './y_extents'; import { ScaleTypes } from '../../../utils/collections'; import { NumberInputOption } from '../../common'; +jest.mock('ui/new_platform'); + describe('YExtents component', () => { let setMultipleValidity: jest.Mock; let setScale: jest.Mock; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/y_extents.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx index 53dde185ec09f..056eb70cb256b 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/pie.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx @@ -17,11 +17,12 @@ * under the License. */ import React from 'react'; + import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../legacy_imports'; import { BasicOptions, TruncateLabelsOption, SwitchOption } from '../common'; import { PieVisParams } from '../../pie'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx similarity index 98% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx index 63b2449b823d5..bdb4d3f39c12b 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/grid_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx @@ -17,11 +17,12 @@ * under the License. */ import React, { useMemo, useEffect, useCallback } from 'react'; + import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { VisOptionsProps } from '../../../legacy_imports'; import { SelectOption, SwitchOption } from '../../common'; import { BasicVislibParams, ValueAxis } from '../../../types'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/index.ts similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/index.ts rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/index.ts diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/point_series.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx similarity index 100% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/point_series/threshold_panel.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.js b/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts similarity index 77% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.js rename to src/legacy/core_plugins/vis_type_vislib/public/gauge.ts index a472d20e07224..5dcc8ad16918d 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/gauge.ts @@ -18,14 +18,43 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; + +import { Schemas, AggGroupNames, ColorSchemas, RangeValues } from './legacy_imports'; import { GaugeOptions } from './components/options'; import { getGaugeCollections, Alignments, ColorModes, GaugeTypes } from './utils/collections'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { ColorSchemaVislibParams, Labels, Style } from './types'; +import { KbnVislibVisTypesDependencies } from './plugin'; + +export interface Gauge extends ColorSchemaVislibParams { + backStyle: 'Full'; + gaugeStyle: 'Full'; + orientation: 'vertical'; + type: 'meter'; + alignment: Alignments; + colorsRange: RangeValues[]; + extendRange: boolean; + gaugeType: GaugeTypes; + labels: Labels; + percentageMode: boolean; + outline?: boolean; + scale: { + show: boolean; + labels: false; + color: 'rgba(105,112,125,0.2)'; + }; + style: Style; +} + +export interface GaugeVisParams { + type: 'gauge'; + addTooltip: boolean; + addLegend: boolean; + isDisplayWarning: boolean; + gauge: Gauge; +} -export const gaugeDefinition = { +export const createGaugeVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'gauge', title: i18n.translate('kbnVislibVisTypes.gauge.gaugeTitle', { defaultMessage: 'Gauge' }), icon: 'visGauge', @@ -79,7 +108,7 @@ export const gaugeDefinition = { }, }, }, - visualization: vislibVisController, + visualization: createVislibVisController(deps), editorConfig: { collections: getGaugeCollections(), optionsTemplate: GaugeOptions, @@ -115,4 +144,4 @@ export const gaugeDefinition = { ]), }, useCustomNoDataScreen: true, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/goal.js b/src/legacy/core_plugins/vis_type_vislib/public/goal.ts similarity index 90% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/goal.js rename to src/legacy/core_plugins/vis_type_vislib/public/goal.ts index 71fcd6593e72c..302d5f6393ef9 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/goal.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/goal.ts @@ -18,21 +18,21 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; + +import { Schemas, AggGroupNames, ColorSchemas } from './legacy_imports'; import { GaugeOptions } from './components/options'; import { getGaugeCollections, GaugeTypes, ColorModes } from './utils/collections'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { KbnVislibVisTypesDependencies } from './plugin'; -export const goalDefinition = { +export const createGoalVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'goal', title: i18n.translate('kbnVislibVisTypes.goal.goalTitle', { defaultMessage: 'Goal' }), icon: 'visGoal', description: i18n.translate('kbnVislibVisTypes.goal.goalDescription', { defaultMessage: 'A goal chart indicates how close you are to your final goal.', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { addTooltip: true, @@ -108,4 +108,4 @@ export const goalDefinition = { ]), }, useCustomNoDataScreen: true, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.js b/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts similarity index 81% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.js rename to src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts index 292e108053598..eb5f84b409838 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/heatmap.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/heatmap.ts @@ -18,21 +18,35 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; + +import { Schemas, AggGroupNames, ColorSchemas, RangeValues } from './legacy_imports'; import { AxisTypes, getHeatmapCollections, Positions, ScaleTypes } from './utils/collections'; import { HeatmapOptions } from './components/options'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { TimeMarker } from './vislib/visualizations/time_marker'; +import { CommonVislibParams, ColorSchemaVislibParams, ValueAxis } from './types'; +import { KbnVislibVisTypesDependencies } from './plugin'; + +export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaVislibParams { + type: 'heatmap'; + addLegend: boolean; + enableHover: boolean; + colorsNumber: number | ''; + colorsRange: RangeValues[]; + valueAxes: ValueAxis[]; + setColorRange: boolean; + percentageMode: boolean; + times: TimeMarker[]; +} -export const heatmapDefinition = { +export const createHeatmapVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'heatmap', title: i18n.translate('kbnVislibVisTypes.heatmap.heatmapTitle', { defaultMessage: 'Heat Map' }), icon: 'visHeatmap', description: i18n.translate('kbnVislibVisTypes.heatmap.heatmapDescription', { defaultMessage: 'Shade cells within a matrix', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'heatmap', @@ -122,4 +136,4 @@ export const heatmapDefinition = { }, ]), }, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js b/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts similarity index 92% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js rename to src/legacy/core_plugins/vis_type_vislib/public/histogram.ts index bc017b5a1a871..f92875a62cfd7 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/histogram.ts @@ -18,8 +18,13 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; +// @ts-ignore +import { palettes } from '@elastic/eui/lib/services'; +// @ts-ignore +import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; + +import { Schemas, AggGroupNames } from './legacy_imports'; + import { Positions, ChartTypes, @@ -32,10 +37,10 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { KbnVislibVisTypesDependencies } from './plugin'; -export const histogramDefinition = { +export const createHistogramVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'histogram', title: i18n.translate('kbnVislibVisTypes.histogram.histogramTitle', { defaultMessage: 'Vertical Bar', @@ -44,7 +49,7 @@ export const histogramDefinition = { description: i18n.translate('kbnVislibVisTypes.histogram.histogramDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'histogram', @@ -183,4 +188,4 @@ export const histogramDefinition = { }, ]), }, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts similarity index 92% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js rename to src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts index ee3570314618a..ada0c6b44ff70 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts @@ -18,8 +18,13 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; +// @ts-ignore +import { palettes } from '@elastic/eui/lib/services'; +// @ts-ignore +import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; + +import { Schemas, AggGroupNames } from './legacy_imports'; + import { Positions, ChartTypes, @@ -32,10 +37,10 @@ import { getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { KbnVislibVisTypesDependencies } from './plugin'; -export const horizontalBarDefinition = { +export const createHorizontalBarVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'horizontal_bar', title: i18n.translate('kbnVislibVisTypes.horizontalBar.horizontalBarTitle', { defaultMessage: 'Horizontal Bar', @@ -44,7 +49,7 @@ export const horizontalBarDefinition = { description: i18n.translate('kbnVislibVisTypes.horizontalBar.horizontalBarDescription', { defaultMessage: 'Assign a continuous variable to each axis', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'histogram', @@ -182,4 +187,4 @@ export const horizontalBarDefinition = { }, ]), }, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.d.ts b/src/legacy/core_plugins/vis_type_vislib/public/index.ts similarity index 74% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.d.ts rename to src/legacy/core_plugins/vis_type_vislib/public/index.ts index bf55abfe8161a..5abe79daf11fa 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.d.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/index.ts @@ -17,16 +17,9 @@ * under the License. */ -import { CommonVislibParams } from './types'; +import { PluginInitializerContext } from '../../../../core/public'; +import { KbnVislibVisTypesPlugin as Plugin } from './plugin'; -export interface PieVisParams extends CommonVislibParams { - type: 'pie'; - addLegend: boolean; - isDonut: boolean; - labels: { - show: boolean; - values: boolean; - last_level: boolean; - truncate: number | null; - }; +export function plugin(initializerContext: PluginInitializerContext) { + return new Plugin(initializerContext); } diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts new file mode 100644 index 0000000000000..3d4cf55adc5e0 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { npSetup, npStart } from 'ui/new_platform'; +import { PluginInitializerContext } from 'kibana/public'; + +/* eslint-disable prettier/prettier */ +import { + initializeHierarchicalTooltipFormatter, + getHierarchicalTooltipFormatter, + // @ts-ignore +} from 'ui/vis/components/tooltip/_hierarchical_tooltip_formatter'; +import { + initializePointSeriesTooltipFormatter, + getPointSeriesTooltipFormatter, + // @ts-ignore +} from 'ui/vis/components/tooltip/_pointseries_tooltip_formatter'; +import { + vislibSeriesResponseHandlerProvider, + vislibSlicesResponseHandlerProvider, + // @ts-ignore +} from 'ui/vis/response_handlers/vislib'; +// @ts-ignore +import { vislibColor } from 'ui/vis/components/color/color'; + +import { plugin } from '.'; +import { + KbnVislibVisTypesPluginSetupDependencies, + KbnVislibVisTypesPluginStartDependencies, +} 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, + __LEGACY: { + initializeHierarchicalTooltipFormatter, + getHierarchicalTooltipFormatter, + initializePointSeriesTooltipFormatter, + getPointSeriesTooltipFormatter, + vislibSeriesResponseHandlerProvider, + vislibSlicesResponseHandlerProvider, + vislibColor, + }, +}; + +const startPlugins: Readonly = { + expressions: npStart.plugins.expressions, + visualizations: visualizationsStart, +}; + +const pluginInstance = plugin({} as PluginInitializerContext); + +export const setup = pluginInstance.setup(npSetup.core, setupPlugins); +export const start = pluginInstance.start(npStart.core, startPlugins); 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 new file mode 100644 index 0000000000000..2970942f221e8 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default'; +export { Schemas } from 'ui/vis/editors/default/schemas'; +export { RangeValues, RangesParamEditor } from 'ui/vis/editors/default/controls/ranges'; +export { ColorSchema, ColorSchemas, colorSchemas, getHeatmapColors } from 'ui/color_maps'; +export { AggConfig, Vis, VisParams } from 'ui/vis'; +export { AggType } from 'ui/agg_types'; +export { CUSTOM_LEGEND_VIS_TYPES, VisLegend } from 'ui/vis/vis_types/vislib_vis_legend'; +// @ts-ignore +export { Tooltip } from 'ui/vis/components/tooltip'; +// @ts-ignore +export { SimpleEmitter } from 'ui/utils/simple_emitter'; +// @ts-ignore +export { Binder } from 'ui/binder'; +export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +// @ts-ignore +export { tabifyAggResponse } from 'ui/agg_response/tabify'; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js b/src/legacy/core_plugins/vis_type_vislib/public/line.ts similarity index 92% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js rename to src/legacy/core_plugins/vis_type_vislib/public/line.ts index d6d075f452fed..35a059fadddcb 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/line.ts @@ -18,8 +18,12 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; +// @ts-ignore +import { palettes } from '@elastic/eui/lib/services'; +// @ts-ignore +import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; + +import { Schemas, AggGroupNames } from './legacy_imports'; import { Positions, ChartTypes, @@ -32,18 +36,18 @@ import { InterpolationModes, getConfigCollections, } from './utils/collections'; -import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { KbnVislibVisTypesDependencies } from './plugin'; -export const lineDefinition = { +export const createLineVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'line', title: i18n.translate('kbnVislibVisTypes.line.lineTitle', { defaultMessage: 'Line' }), icon: 'visLine', description: i18n.translate('kbnVislibVisTypes.line.lineDescription', { defaultMessage: 'Emphasize trends', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'line', @@ -175,4 +179,4 @@ export const lineDefinition = { }, ]), }, -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.js b/src/legacy/core_plugins/vis_type_vislib/public/pie.ts similarity index 81% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.js rename to src/legacy/core_plugins/vis_type_vislib/public/pie.ts index 1cef3114f047d..32307b7a117a1 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie.ts @@ -18,20 +18,34 @@ */ import { i18n } from '@kbn/i18n'; -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; + +import { Schemas, AggGroupNames } from './legacy_imports'; import { PieOptions } from './components/options'; import { getPositions, Positions } from './utils/collections'; -import { vislibVisController } from './controller'; +import { createVislibVisController } from './vis_controller'; +import { CommonVislibParams } from './types'; +import { KbnVislibVisTypesDependencies } from './plugin'; + +export interface PieVisParams extends CommonVislibParams { + type: 'pie'; + addLegend: boolean; + isDonut: boolean; + labels: { + show: boolean; + values: boolean; + last_level: boolean; + truncate: number | null; + }; +} -export const pieDefinition = { +export const createPieVisTypeDefinition = (deps: KbnVislibVisTypesDependencies) => ({ name: 'pie', title: i18n.translate('kbnVislibVisTypes.pie.pieTitle', { defaultMessage: 'Pie' }), icon: 'visPie', description: i18n.translate('kbnVislibVisTypes.pie.pieDescription', { defaultMessage: 'Compare parts of a whole', }), - visualization: vislibVisController, + visualization: createVislibVisController(deps), visConfig: { defaults: { type: 'pie', @@ -89,4 +103,4 @@ export const pieDefinition = { }, hierarchicalData: true, responseHandler: 'vislib_slices', -}; +}); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.test.js b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts similarity index 92% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts index 4d932e6e9518e..786de0cc79b86 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.test.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.test.ts @@ -19,10 +19,14 @@ // eslint-disable-next-line import { functionWrapper } from '../../../../plugins/expressions/public/functions/tests/utils'; -import { kibanaPie } from './pie_fn'; +import { createPieVisFn } from './pie_fn'; +import { KbnVislibVisTypesDependencies } from './plugin'; jest.mock('ui/new_platform'); +const deps: KbnVislibVisTypesDependencies = { + vislibSlicesResponseHandlerProvider: () => ({ handler: mockResponseHandler }), +} as any; const mockResponseHandler = jest.fn().mockReturnValue( Promise.resolve({ hits: 1, @@ -39,20 +43,15 @@ const mockResponseHandler = jest.fn().mockReturnValue( }, }) ); -jest.mock('ui/vis/response_handlers/vislib', () => ({ - vislibSlicesResponseHandlerProvider: () => ({ handler: mockResponseHandler }), -})); describe('interpreter/functions#pie', () => { - const fn = functionWrapper(kibanaPie); + const fn = functionWrapper(createPieVisFn(deps)); const context = { type: 'kibana_datatable', rows: [{ 'col-0-1': 0 }], columns: [{ id: 'col-0-1', name: 'Count' }], }; const visConfig = { - addTooltip: true, - addLegend: false, type: 'pie', addTooltip: true, addLegend: true, diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.js b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts similarity index 68% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.js rename to src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts index f66fd53e59efe..4b536caedb121 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/pie_fn.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/pie_fn.ts @@ -17,11 +17,37 @@ * under the License. */ -import { functionsRegistry } from 'plugins/interpreter/registries'; -import { vislibSlicesResponseHandlerProvider as vislibSlicesResponseHandler } from 'ui/vis/response_handlers/vislib'; import { i18n } from '@kbn/i18n'; -export const kibanaPie = () => ({ +import { + ExpressionFunction, + KibanaDatatable, + Render, +} from '../../../../plugins/expressions/public'; +import { KbnVislibVisTypesDependencies } from './plugin'; + +const name = 'kibana_pie'; + +type Context = KibanaDatatable; + +interface Arguments { + visConfig: string; +} + +type VisParams = Required; + +interface RenderValue { + visConfig: VisParams; +} + +type Return = Promise>; + +export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): ExpressionFunction< + typeof name, + Context, + Arguments, + Return +> => ({ name: 'kibana_pie', type: 'render', context: { @@ -32,14 +58,15 @@ export const kibanaPie = () => ({ }), args: { visConfig: { - types: ['string', 'null'], + types: ['string'], default: '"{}"', + help: '', }, }, async fn(context, args) { const visConfig = JSON.parse(args.visConfig); - const responseHandler = vislibSlicesResponseHandler().handler; + const responseHandler = deps.vislibSlicesResponseHandlerProvider().handler; const convertedData = await responseHandler(context, visConfig.dimensions); return { @@ -56,5 +83,3 @@ export const kibanaPie = () => ({ }; }, }); - -functionsRegistry.register(kibanaPie); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts new file mode 100644 index 0000000000000..a2e8512b2201b --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/plugin.ts @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { + CoreSetup, + CoreStart, + Plugin, + IUiSettingsClient, + PluginInitializerContext, +} from 'kibana/public'; + +import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; +import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public'; +import { createKbnVislibVisTypesFn } from './vis_type_vislib_vis_fn'; +import { createPieVisFn } from './pie_fn'; +import { + createHistogramVisTypeDefinition, + createLineVisTypeDefinition, + createPieVisTypeDefinition, + createAreaVisTypeDefinition, + createHeatmapVisTypeDefinition, + createHorizontalBarVisTypeDefinition, + createGaugeVisTypeDefinition, + createGoalVisTypeDefinition, +} from './vis_type_vislib_vis_types'; + +type ResponseHandlerProvider = () => { + name: string; + handler: (response: any, dimensions: any) => Promise; +}; +type KbnVislibVisTypesCoreSetup = CoreSetup; + +export interface LegacyDependencies { + initializeHierarchicalTooltipFormatter: () => Promise; + getHierarchicalTooltipFormatter: () => Promise; + initializePointSeriesTooltipFormatter: () => void; + getPointSeriesTooltipFormatter: () => void; + vislibSeriesResponseHandlerProvider: ResponseHandlerProvider; + vislibSlicesResponseHandlerProvider: ResponseHandlerProvider; + vislibColor: (colors: Array, mappings: any) => (value: any) => any; +} + +export type KbnVislibVisTypesDependencies = LegacyDependencies & { + uiSettings: IUiSettingsClient; +}; + +/** @internal */ +export interface KbnVislibVisTypesPluginSetupDependencies { + expressions: ReturnType; + visualizations: VisualizationsSetup; + __LEGACY: LegacyDependencies; +} + +/** @internal */ +export interface KbnVislibVisTypesPluginStartDependencies { + expressions: ReturnType; + visualizations: VisualizationsStart; +} + +/** @internal */ +export class KbnVislibVisTypesPlugin implements Plugin, void> { + constructor(public initializerContext: PluginInitializerContext) {} + + public async setup( + core: KbnVislibVisTypesCoreSetup, + { expressions, visualizations, __LEGACY }: KbnVislibVisTypesPluginSetupDependencies + ) { + const visualizationDependencies: Readonly = { + ...__LEGACY, + uiSettings: core.uiSettings, + }; + + expressions.registerFunction(createKbnVislibVisTypesFn(visualizationDependencies)); + expressions.registerFunction(createPieVisFn(visualizationDependencies)); + + [ + createHistogramVisTypeDefinition, + createLineVisTypeDefinition, + createPieVisTypeDefinition, + createAreaVisTypeDefinition, + createHeatmapVisTypeDefinition, + createHorizontalBarVisTypeDefinition, + createGaugeVisTypeDefinition, + createGoalVisTypeDefinition, + ].forEach(vis => visualizations.types.createBaseVisualization(vis(visualizationDependencies))); + } + + public start(core: CoreStart, deps: KbnVislibVisTypesPluginStartDependencies) { + // nothing to do here + } +} diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts b/src/legacy/core_plugins/vis_type_vislib/public/types.ts similarity index 95% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts rename to src/legacy/core_plugins/vis_type_vislib/public/types.ts index b023eb54f7295..b6928be89f648 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/types.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/types.ts @@ -17,8 +17,8 @@ * under the License. */ -import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; -import { TimeMarker } from 'ui/vislib/visualizations/time_marker'; +import { ColorSchemas } from './legacy_imports'; +import { TimeMarker } from './vislib/visualizations/time_marker'; import { Positions, ChartModes, diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts similarity index 73% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts rename to src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts index 6fe30483a32e8..810ddeea73834 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/collections.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts @@ -18,14 +18,16 @@ */ import { i18n } from '@kbn/i18n'; -import { colorSchemas } from 'ui/vislib/components/color/colormaps'; +import { $Values } from '@kbn/utility-types'; +import { colorSchemas } from '../legacy_imports'; -export enum Positions { - RIGHT = 'right', - LEFT = 'left', - TOP = 'top', - BOTTOM = 'bottom', -} +export const Positions = Object.freeze({ + RIGHT: 'right' as 'right', + LEFT: 'left' as 'left', + TOP: 'top' as 'top', + BOTTOM: 'bottom' as 'bottom', +}); +export type Positions = $Values; const getPositions = () => [ { @@ -54,11 +56,12 @@ const getPositions = () => [ }, ]; -export enum ChartTypes { - LINE = 'line', - AREA = 'area', - HISTOGRAM = 'histogram', -} +export const ChartTypes = Object.freeze({ + LINE: 'line' as 'line', + AREA: 'area' as 'area', + HISTOGRAM: 'histogram' as 'histogram', +}); +export type ChartTypes = $Values; const getChartTypes = () => [ { @@ -81,10 +84,11 @@ const getChartTypes = () => [ }, ]; -export enum ChartModes { - NORMAL = 'normal', - STACKED = 'stacked', -} +export const ChartModes = Object.freeze({ + NORMAL: 'normal' as 'normal', + STACKED: 'stacked' as 'stacked', +}); +export type ChartModes = $Values; const getChartModes = () => [ { @@ -101,11 +105,12 @@ const getChartModes = () => [ }, ]; -export enum InterpolationModes { - LINEAR = 'linear', - CARDINAL = 'cardinal', - STEP_AFTER = 'step-after', -} +export const InterpolationModes = Object.freeze({ + LINEAR: 'linear' as 'linear', + CARDINAL: 'cardinal' as 'cardinal', + STEP_AFTER: 'step-after' as 'step-after', +}); +export type InterpolationModes = $Values; const getInterpolationModes = () => [ { @@ -128,16 +133,18 @@ const getInterpolationModes = () => [ }, ]; -export enum AxisTypes { - CATEGORY = 'category', - VALUE = 'value', -} +export const AxisTypes = Object.freeze({ + CATEGORY: 'category' as 'category', + VALUE: 'value' as 'value', +}); +export type AxisTypes = $Values; -export enum ScaleTypes { - LINEAR = 'linear', - LOG = 'log', - SQUARE_ROOT = 'square root', -} +export const ScaleTypes = Object.freeze({ + LINEAR: 'linear' as 'linear', + LOG: 'log' as 'log', + SQUARE_ROOT: 'square root' as 'square root', +}); +export type ScaleTypes = $Values; const getScaleTypes = () => [ { @@ -160,12 +167,13 @@ const getScaleTypes = () => [ }, ]; -export enum AxisModes { - NORMAL = 'normal', - PERCENTAGE = 'percentage', - WIGGLE = 'wiggle', - SILHOUETTE = 'silhouette', -} +export const AxisModes = Object.freeze({ + NORMAL: 'normal' as 'normal', + PERCENTAGE: 'percentage' as 'percentage', + WIGGLE: 'wiggle' as 'wiggle', + SILHOUETTE: 'silhouette' as 'silhouette', +}); +export type AxisModes = $Values; const getAxisModes = () => [ { @@ -194,17 +202,19 @@ const getAxisModes = () => [ }, ]; -export enum Rotates { - HORIZONTAL = 0, - VERTICAL = 90, - ANGLED = 75, -} +export const Rotates = Object.freeze({ + HORIZONTAL: 0, + VERTICAL: 90, + ANGLED: 75, +}); +export type Rotates = $Values; -export enum ThresholdLineStyles { - FULL = 'full', - DASHED = 'dashed', - DOT_DASHED = 'dot-dashed', -} +export const ThresholdLineStyles = Object.freeze({ + FULL: 'full' as 'full', + DASHED: 'dashed' as 'dashed', + DOT_DASHED: 'dot-dashed' as 'dot-dashed', +}); +export type ThresholdLineStyles = $Values; const getThresholdLineStyles = () => [ { @@ -248,16 +258,18 @@ const getRotateOptions = () => [ }, ]; -export enum GaugeTypes { - ARC = 'Arc', - CIRCLE = 'Circle', -} +export const GaugeTypes = Object.freeze({ + ARC: 'Arc' as 'Arc', + CIRCLE: 'Circle' as 'Circle', +}); +export type GaugeTypes = $Values; -export enum ColorModes { - BACKGROUND = 'Background', - LABELS = 'Labels', - NONE = 'None', -} +export const ColorModes = Object.freeze({ + BACKGROUND: 'Background' as 'Background', + LABELS: 'Labels' as 'Labels', + NONE: 'None' as 'None', +}); +export type ColorModes = $Values; const getGaugeTypes = () => [ { @@ -274,11 +286,12 @@ const getGaugeTypes = () => [ }, ]; -export enum Alignments { - AUTOMATIC = 'automatic', - HORIZONTAL = 'horizontal', - VERTICAL = 'vertical', -} +export const Alignments = Object.freeze({ + AUTOMATIC: 'automatic' as 'automatic', + HORIZONTAL: 'horizontal' as 'horizontal', + VERTICAL: 'vertical' as 'vertical', +}); +export type Alignments = $Values; const getAlignments = () => [ { diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx b/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx similarity index 96% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx rename to src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx index 7e4140606762f..adb93ca8011b2 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/utils/common_config.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/utils/common_config.tsx @@ -18,8 +18,9 @@ */ import React from 'react'; -import { VisOptionsProps } from 'ui/vis/editors/default'; import { i18n } from '@kbn/i18n'; + +import { VisOptionsProps } from '../legacy_imports'; import { PointSeriesOptions, MetricsAxisOptions } from '../components/options'; import { ValidationWrapper } from '../components/common'; import { BasicVislibParams } from '../types'; 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 new file mode 100644 index 0000000000000..cff9a0a2e8551 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_controller.tsx @@ -0,0 +1,147 @@ +/* + * 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 'jquery'; +import React, { RefObject } from 'react'; + +import { CUSTOM_LEGEND_VIS_TYPES, VisLegend, Vis, VisParams } from './legacy_imports'; +// @ts-ignore +import { Vis as Vislib } from './vislib/vis'; +import { Positions } from './utils/collections'; +import { KbnVislibVisTypesDependencies } from './plugin'; +import { mountReactNode } from '../../../../core/public/utils'; + +const legendClassName = { + top: 'visLib--legend-top', + bottom: 'visLib--legend-bottom', + left: 'visLib--legend-left', + right: 'visLib--legend-right', +}; + +export const createVislibVisController = (deps: KbnVislibVisTypesDependencies) => { + return class VislibVisController { + unmount: (() => void) | null = null; + visParams?: VisParams; + legendRef: RefObject; + container: HTMLDivElement; + chartEl: HTMLDivElement; + legendEl: HTMLDivElement; + vislibVis: any; + + constructor(public el: Element, public vis: Vis) { + this.el = el; + this.vis = vis; + this.unmount = null; + this.legendRef = React.createRef(); + + // vis mount point + this.container = document.createElement('div'); + this.container.className = 'visLib'; + this.el.appendChild(this.container); + + // chart mount point + this.chartEl = document.createElement('div'); + this.chartEl.className = 'visLib__chart'; + this.container.appendChild(this.chartEl); + + // legend mount point + this.legendEl = document.createElement('div'); + this.legendEl.className = 'visLib__legend'; + this.container.appendChild(this.legendEl); + } + + render(esResponse: any, visParams: VisParams) { + if (this.vislibVis) { + this.destroy(); + } + + return new Promise(async resolve => { + if (this.el.clientWidth === 0 || this.el.clientHeight === 0) { + return resolve(); + } + + await deps.initializeHierarchicalTooltipFormatter(); + await deps.initializePointSeriesTooltipFormatter(); + + this.vislibVis = new Vislib(this.chartEl, visParams, deps); + this.vislibVis.on('brush', this.vis.API.events.brush); + this.vislibVis.on('click', this.vis.API.events.filter); + this.vislibVis.on('renderComplete', resolve); + + this.vislibVis.initVisConfig(esResponse, this.vis.getUiState()); + + if (visParams.addLegend) { + $(this.container) + .attr('class', (i, cls) => { + return cls.replace(/visLib--legend-\S+/g, ''); + }) + .addClass((legendClassName as any)[visParams.legendPosition]); + + this.mountLegend(esResponse, visParams.legendPosition); + } + + this.vislibVis.render(esResponse, this.vis.getUiState()); + + // refreshing the legend after the chart is rendered. + // this is necessary because some visualizations + // provide data necessary for the legend only after a render cycle. + if ( + visParams.addLegend && + CUSTOM_LEGEND_VIS_TYPES.includes(this.vislibVis.visConfigArgs.type) + ) { + this.unmountLegend(); + this.mountLegend(esResponse, visParams.legendPosition); + this.vislibVis.render(esResponse, this.vis.getUiState()); + } + }); + } + + mountLegend(visData: any, position: Positions) { + this.unmount = mountReactNode( + + )(this.legendEl); + } + + unmountLegend() { + if (this.unmount) { + this.unmount(); + } + } + + destroy() { + if (this.unmount) { + this.unmount(); + } + + if (this.vislibVis) { + this.vislibVis.off('brush', this.vis.API.events.brush); + this.vislibVis.off('click', this.vis.API.events.filter); + this.vislibVis.destroy(); + delete this.vislibVis; + } + } + }; +}; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/vislib_fn.js b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts similarity index 68% rename from src/legacy/core_plugins/kbn_vislib_vis_types/public/vislib_fn.js rename to src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts index 85ea5994548d6..0a685cd70e089 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/vislib_fn.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_fn.ts @@ -17,11 +17,36 @@ * under the License. */ -import { functionsRegistry } from 'plugins/interpreter/registries'; import { i18n } from '@kbn/i18n'; -import { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; -export const vislib = () => ({ +import { + ExpressionFunction, + KibanaDatatable, + Render, +} from '../../../../plugins/expressions/public'; +import { KbnVislibVisTypesDependencies } from './plugin'; + +const name = 'vislib'; + +type Context = KibanaDatatable; + +interface Arguments { + type: string; + visConfig: string; +} + +type VisParams = Required; + +interface RenderValue { + visType: string; + visConfig: VisParams; +} + +type Return = Promise>; + +export const createKbnVislibVisTypesFn = ( + deps: KbnVislibVisTypesDependencies +) => (): ExpressionFunction => ({ name: 'vislib', type: 'render', context: { @@ -34,14 +59,16 @@ export const vislib = () => ({ type: { types: ['string'], default: '""', + help: 'vislib vis type', }, visConfig: { - types: ['string', 'null'], + types: ['string'], default: '"{}"', + help: '', }, }, async fn(context, args) { - const responseHandler = vislibSeriesResponseHandlerProvider().handler; + const responseHandler = deps.vislibSeriesResponseHandlerProvider().handler; const visConfigParams = JSON.parse(args.visConfig); const convertedData = await responseHandler(context, visConfigParams.dimensions); @@ -60,5 +87,3 @@ export const vislib = () => ({ }; }, }); - -functionsRegistry.register(vislib); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts new file mode 100644 index 0000000000000..f44d503895483 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vis_type_vislib_vis_types.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. + */ + +export { createHistogramVisTypeDefinition } from './histogram'; +export { createLineVisTypeDefinition } from './line'; +export { createPieVisTypeDefinition } from './pie'; +export { createAreaVisTypeDefinition } from './area'; +export { createHeatmapVisTypeDefinition } from './heatmap'; +export { createHorizontalBarVisTypeDefinition } from './horizontal_bar'; +export { createGaugeVisTypeDefinition } from './gauge'; +export { createGoalVisTypeDefinition } from './goal'; diff --git a/src/legacy/ui/public/vislib/VISLIB.md b/src/legacy/core_plugins/vis_type_vislib/public/vislib/VISLIB.md similarity index 100% rename from src/legacy/ui/public/vislib/VISLIB.md rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/VISLIB.md diff --git a/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js similarity index 97% rename from src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js index 1cafbadcff655..36c5b60abf5c6 100644 --- a/src/legacy/ui/public/vislib/__tests__/components/heatmap_color.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/heatmap_color.js @@ -19,7 +19,8 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { getHeatmapColors } from '../../components/color/heatmap_color'; + +import { getHeatmapColors } from '../../../legacy_imports'; describe('Vislib Heatmap Color Module Test Suite', function() { const emptyObject = {}; diff --git a/src/legacy/ui/public/vislib/__tests__/components/labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/components/labels.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/components/labels.js diff --git a/src/legacy/ui/public/vislib/__tests__/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/index.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/__snapshots__/dispatch_heatmap.test.js.snap b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/__snapshots__/dispatch_heatmap.test.js.snap similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/__snapshots__/dispatch_heatmap.test.js.snap rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/__snapshots__/dispatch_heatmap.test.js.snap diff --git a/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js similarity index 98% rename from src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js index 8b32943b64ea8..3081c12415076 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/axis/axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis/axis.js @@ -20,9 +20,11 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; +import 'ui/persisted_state'; + import expect from '@kbn/expect'; import $ from 'jquery'; -import '../../../../persisted_state'; + import { Axis } from '../../../lib/axis'; import { VisConfig } from '../../../lib/vis_config'; @@ -119,7 +121,8 @@ describe('Vislib Axis Class Test Suite', function() { }, data, persistedState, - $('.x-axis-div')[0] + $('.x-axis-div')[0], + () => undefined ); yAxis = new Axis(visConfig, { type: 'value', diff --git a/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js similarity index 97% rename from src/legacy/ui/public/vislib/__tests__/lib/axis_title.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js index d71184fdc1223..cbb294c3b44e4 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/axis_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/axis_title.js @@ -21,12 +21,14 @@ import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; import ngMock from 'ng_mock'; + import expect from '@kbn/expect'; +import 'ui/persisted_state'; + import { AxisTitle } from '../../lib/axis/axis_title'; import { AxisConfig } from '../../lib/axis/axis_config'; import { VisConfig } from '../../lib/vis_config'; import { Data } from '../../lib/data'; -import '../../../persisted_state'; describe('Vislib AxisTitle Class Test Suite', function() { let PersistedState; @@ -118,14 +120,15 @@ describe('Vislib AxisTitle Class Test Suite', function() { .style('height', '20px') .style('width', '20px'); - dataObj = new Data(data, new PersistedState()); + dataObj = new Data(data, new PersistedState(), () => undefined); visConfig = new VisConfig( { type: 'histogram', }, data, new PersistedState(), - el.node() + el.node(), + () => undefined ); const xAxisConfig = new AxisConfig(visConfig, { position: 'bottom', diff --git a/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js similarity index 98% rename from src/legacy/ui/public/vislib/__tests__/lib/chart_title.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js index e64999e7bd329..b2086d0749a41 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/chart_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/chart_title.js @@ -21,9 +21,9 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; + import { ChartTitle } from '../../lib/chart_title'; import { VisConfig } from '../../lib/vis_config'; -import '../../../persisted_state'; describe('Vislib ChartTitle Class Test Suite', function() { let persistedState; @@ -112,7 +112,8 @@ describe('Vislib ChartTitle Class Test Suite', function() { }, data, persistedState, - el.node() + el.node(), + () => undefined ); chartTitle = new ChartTitle(visConfig); }) diff --git a/src/legacy/ui/public/vislib/__tests__/lib/data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js similarity index 92% rename from src/legacy/ui/public/vislib/__tests__/lib/data.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js index c12259ee55a5a..5811b1d238163 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/data.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/data.js @@ -20,9 +20,9 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import 'ui/persisted_state'; import { Data } from '../../lib/data'; -import '../../../persisted_state'; const seriesData = { label: '', @@ -168,7 +168,7 @@ describe('Vislib Data Class Test Suite', function() { }); it('should return an object', function() { - const rowIn = new Data(rowsData, persistedState); + const rowIn = new Data(rowsData, persistedState, () => undefined); expect(_.isObject(rowIn)).to.be(true); }); }); @@ -182,7 +182,7 @@ describe('Vislib Data Class Test Suite', function() { }; beforeEach(function() { - data = new Data(pieData, persistedState); + data = new Data(pieData, persistedState, () => undefined); }); it('should remove zero values', function() { @@ -196,7 +196,7 @@ describe('Vislib Data Class Test Suite', function() { let serOut; beforeEach(function() { - serIn = new Data(seriesData, persistedState); + serIn = new Data(seriesData, persistedState, () => undefined); serOut = serIn.flatten(); }); @@ -210,7 +210,7 @@ describe('Vislib Data Class Test Suite', function() { function testLength(inputData) { return function() { - const data = new Data(inputData, persistedState); + const data = new Data(inputData, persistedState, () => undefined); const len = _.reduce( data.chartData(), function(sum, chart) { @@ -266,7 +266,7 @@ describe('Vislib Data Class Test Suite', function() { }; beforeEach(function() { - data = new Data(geohashGridData, persistedState); + data = new Data(geohashGridData, persistedState, () => undefined); }); describe('getVisData', function() { @@ -287,7 +287,7 @@ describe('Vislib Data Class Test Suite', function() { describe('null value check', function() { it('should return false', function() { - const data = new Data(rowsData, persistedState); + const data = new Data(rowsData, persistedState, () => undefined); expect(data.hasNullValues()).to.be(false); }); @@ -307,7 +307,7 @@ describe('Vislib Data Class Test Suite', function() { ], }); - const data = new Data(nullRowData, persistedState); + const data = new Data(nullRowData, persistedState, () => undefined); expect(data.hasNullValues()).to.be(true); }); }); diff --git a/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js similarity index 90% rename from src/legacy/ui/public/vislib/__tests__/lib/dispatch.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js index f2d2e7d05a34d..a93db5637c89d 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/dispatch.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch.js @@ -20,22 +20,23 @@ import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; + import expect from '@kbn/expect'; +import 'ui/persisted_state'; // Data -import data from 'fixtures/vislib/mock_data/date_histogram/_series'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; -import { SimpleEmitter } from '../../../utils/simple_emitter'; +import data from './fixtures/mock_data/date_histogram/_series'; +import getFixturesVislibVisFixtureProvider from './fixtures/_vis_fixture'; +import { SimpleEmitter } from '../../../legacy_imports'; describe('Vislib Dispatch Class Test Suite', function() { function destroyVis(vis) { vis.destroy(); } - function getEls(el, n, type) { + function getEls(element, n, type) { return d3 - .select(el) + .select(element) .data(new Array(n)) .enter() .append(type); @@ -48,7 +49,8 @@ describe('Vislib Dispatch Class Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); vis.render(data, persistedState); }) @@ -74,8 +76,9 @@ describe('Vislib Dispatch Class Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); persistedState = new ($injector.get('PersistedState'))(); + vis = getVis(); vis.on('brush', _.noop); vis.render(data, persistedState); }) @@ -91,7 +94,7 @@ describe('Vislib Dispatch Class Test Suite', function() { const apply = chart.events.addEvent('event', _.noop); expect(apply).to.be.a('function'); - const els = getEls(vis.el, 3, 'div'); + const els = getEls(vis.element, 3, 'div'); apply(els); els.each(function() { expect(d3.select(this).on('event')).to.be(_.noop); @@ -114,7 +117,7 @@ describe('Vislib Dispatch Class Test Suite', function() { const apply = chart.events[name](chart.series[0].chartEl); expect(apply).to.be.a('function'); - const els = getEls(vis.el, 3, 'div'); + const els = getEls(vis.element, 3, 'div'); apply(els); els.each(function() { expect(d3.select(this).on(event)).to.be.a('function'); @@ -188,7 +191,8 @@ describe('Vislib Dispatch Class Test Suite', function() { let persistedState; ngMock.module('kibana'); ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); vis.on('someEvent', _.noop); vis.render(data, persistedState); @@ -207,7 +211,8 @@ describe('Vislib Dispatch Class Test Suite', function() { let persistedState; ngMock.module('kibana'); ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); vis.render(data, persistedState); vis.on('someEvent', _.noop); diff --git a/src/legacy/ui/public/vislib/__tests__/lib/dispatch_heatmap.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_heatmap.test.js similarity index 88% rename from src/legacy/ui/public/vislib/__tests__/lib/dispatch_heatmap.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_heatmap.test.js index 19e78ef4f30c2..e22f19ea643fd 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/dispatch_heatmap.test.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_heatmap.test.js @@ -16,7 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + import mockDispatchDataD3 from './fixtures/dispatch_heatmap_d3.json'; +import { Dispatch } from '../../lib/dispatch'; +import mockdataPoint from './fixtures/dispatch_heatmap_data_point.json'; +import mockConfigPercentage from './fixtures/dispatch_heatmap_config.json'; + +jest.mock('ui/new_platform'); jest.mock('d3', () => ({ event: { target: { @@ -26,16 +32,14 @@ jest.mock('d3', () => ({ }, }, })); - -import { Dispatch } from '../../lib/dispatch'; -import mockdataPoint from './fixtures/dispatch_heatmap_data_point.json'; -import mockConfigPercentage from './fixtures/dispatch_heatmap_config.json'; - -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: () => ({ - get: () => '', - }), - addBasePath: () => {}, +jest.mock('../../../legacy_imports.ts', () => ({ + ...jest.requireActual('../../../legacy_imports.ts'), + chrome: { + getUiSettingsClient: () => ({ + get: () => '', + }), + addBasePath: () => {}, + }, })); function getHandlerMock(config = {}, data = {}) { diff --git a/src/legacy/ui/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js similarity index 90% rename from src/legacy/ui/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js index e196c1bde0737..8fe9ac24db77b 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/dispatch_vertical_bar_chart.test.js @@ -16,7 +16,14 @@ * specific language governing permissions and limitations * under the License. */ + import mockDispatchDataD3 from './fixtures/dispatch_bar_chart_d3.json'; +import { Dispatch } from '../../lib/dispatch'; +import mockdataPoint from './fixtures/dispatch_bar_chart_data_point.json'; +import mockConfigPercentage from './fixtures/dispatch_bar_chart_config_percentage.json'; +import mockConfigNormal from './fixtures/dispatch_bar_chart_config_normal.json'; + +jest.mock('ui/new_platform'); jest.mock('d3', () => ({ event: { target: { @@ -26,17 +33,14 @@ jest.mock('d3', () => ({ }, }, })); - -import { Dispatch } from '../../lib/dispatch'; -import mockdataPoint from './fixtures/dispatch_bar_chart_data_point.json'; -import mockConfigPercentage from './fixtures/dispatch_bar_chart_config_percentage.json'; -import mockConfigNormal from './fixtures/dispatch_bar_chart_config_normal.json'; - -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: () => ({ - get: () => '', - }), - addBasePath: () => {}, +jest.mock('../../../legacy_imports.ts', () => ({ + ...jest.requireActual('../../../legacy_imports.ts'), + chrome: { + getUiSettingsClient: () => ({ + get: () => '', + }), + addBasePath: () => {}, + }, })); function getHandlerMock(config = {}, data = {}) { diff --git a/src/legacy/ui/public/vislib/__tests__/lib/error_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/error_handler.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/error_handler.js diff --git a/src/fixtures/vislib/_vis_fixture.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js similarity index 61% rename from src/fixtures/vislib/_vis_fixture.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js index d71c76a1fd99e..c49ca732f0915 100644 --- a/src/fixtures/vislib/_vis_fixture.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/_vis_fixture.js @@ -19,7 +19,23 @@ import _ from 'lodash'; import $ from 'jquery'; -import { VislibVisProvider } from 'ui/vislib/vis'; + +import { Vis } from '../../../vis'; + +// TODO: remove legacy imports when/of converting tests to jest +import { + setHierarchicalTooltipFormatter, + getHierarchicalTooltipFormatter, +} from 'ui/vis/components/tooltip/_hierarchical_tooltip_formatter'; +import { + setPointSeriesTooltipFormatter, + getPointSeriesTooltipFormatter, +} from 'ui/vis/components/tooltip/_pointseries_tooltip_formatter'; +import { + vislibSeriesResponseHandlerProvider, + vislibSlicesResponseHandlerProvider, +} from 'ui/vis/response_handlers/vislib'; +import { vislibColor } from 'ui/vis/components/color/color'; const $visCanvas = $('
') .attr('id', 'vislib-vis-fixtures') @@ -52,11 +68,25 @@ afterEach(function() { count = 0; }); -export default function VislibFixtures(Private) { - return function(visLibParams) { - const Vis = Private(VislibVisProvider); +const getDeps = () => { + const uiSettings = new Map(); + return { + uiSettings, + vislibColor, + getHierarchicalTooltipFormatter, + getPointSeriesTooltipFormatter, + vislibSeriesResponseHandlerProvider, + vislibSlicesResponseHandlerProvider, + }; +}; + +export default function getVislibFixtures(Private) { + setHierarchicalTooltipFormatter(Private); + setPointSeriesTooltipFormatter(Private); + + return function(visLibParams, element) { return new Vis( - $visCanvas.new(), + element || $visCanvas.new(), _.defaults({}, visLibParams || {}, { addTooltip: true, addLegend: true, @@ -64,7 +94,8 @@ export default function VislibFixtures(Private) { setYExtents: false, yAxis: {}, type: 'histogram', - }) + }), + getDeps() ); }; } diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_normal.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_normal.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_normal.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_normal.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_percentage.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_percentage.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_percentage.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_config_percentage.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_d3.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_d3.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_d3.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_d3.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_data_point.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_data_point.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_data_point.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_bar_chart_data_point.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_config.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_config.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_config.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_config.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_d3.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_d3.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_d3.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_d3.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_data_point.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_data_point.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_data_point.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/dispatch_heatmap_data_point.json diff --git a/src/fixtures/vislib/mock_data/date_histogram/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_columns.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_rows.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_rows_series_with_holes.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_rows_series_with_holes.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_monthly_interval.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_series_monthly_interval.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_monthly_interval.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_series_neg.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_neg.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_series_neg.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_neg.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_series_pos_neg.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_pos_neg.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_series_pos_neg.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_series_pos_neg.js diff --git a/src/fixtures/vislib/mock_data/date_histogram/_stacked_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_stacked_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/date_histogram/_stacked_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/date_histogram/_stacked_series.js diff --git a/src/fixtures/vislib/mock_data/filters/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/filters/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_columns.js diff --git a/src/fixtures/vislib/mock_data/filters/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/filters/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_rows.js diff --git a/src/fixtures/vislib/mock_data/filters/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/filters/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/filters/_series.js diff --git a/src/fixtures/vislib/mock_data/geohash/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/geohash/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_columns.js diff --git a/src/fixtures/vislib/mock_data/geohash/_geo_json.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_geo_json.js similarity index 100% rename from src/fixtures/vislib/mock_data/geohash/_geo_json.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_geo_json.js diff --git a/src/fixtures/vislib/mock_data/geohash/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/geohash/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/geohash/_rows.js diff --git a/src/fixtures/vislib/mock_data/histogram/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/histogram/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_columns.js diff --git a/src/fixtures/vislib/mock_data/histogram/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/histogram/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_rows.js diff --git a/src/fixtures/vislib/mock_data/histogram/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/histogram/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_series.js diff --git a/src/fixtures/vislib/mock_data/histogram/_slices.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_slices.js similarity index 100% rename from src/fixtures/vislib/mock_data/histogram/_slices.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/histogram/_slices.js diff --git a/src/fixtures/vislib/mock_data/not_enough_data/_one_point.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/not_enough_data/_one_point.js similarity index 100% rename from src/fixtures/vislib/mock_data/not_enough_data/_one_point.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/not_enough_data/_one_point.js diff --git a/src/fixtures/vislib/mock_data/range/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/range/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_columns.js diff --git a/src/fixtures/vislib/mock_data/range/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/range/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_rows.js diff --git a/src/fixtures/vislib/mock_data/range/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/range/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/range/_series.js diff --git a/src/fixtures/vislib/mock_data/significant_terms/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/significant_terms/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_columns.js diff --git a/src/fixtures/vislib/mock_data/significant_terms/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/significant_terms/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_rows.js diff --git a/src/fixtures/vislib/mock_data/significant_terms/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/significant_terms/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/significant_terms/_series.js diff --git a/src/fixtures/vislib/mock_data/stacked/_stacked.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/stacked/_stacked.js similarity index 100% rename from src/fixtures/vislib/mock_data/stacked/_stacked.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/stacked/_stacked.js diff --git a/src/fixtures/vislib/mock_data/terms/_columns.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_columns.js similarity index 100% rename from src/fixtures/vislib/mock_data/terms/_columns.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_columns.js diff --git a/src/fixtures/vislib/mock_data/terms/_rows.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_rows.js similarity index 100% rename from src/fixtures/vislib/mock_data/terms/_rows.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_rows.js diff --git a/src/fixtures/vislib/mock_data/terms/_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_series.js similarity index 100% rename from src/fixtures/vislib/mock_data/terms/_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_series.js diff --git a/src/fixtures/vislib/mock_data/terms/_seriesMultiple.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_seriesMultiple.js similarity index 100% rename from src/fixtures/vislib/mock_data/terms/_seriesMultiple.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_seriesMultiple.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js similarity index 87% rename from src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js index d37d67567e8a5..b309c97d24000 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/handler/handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/handler/handler.js @@ -21,13 +21,14 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; // Data -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import columns from 'fixtures/vislib/mock_data/date_histogram/_columns'; -import rows from 'fixtures/vislib/mock_data/date_histogram/_rows'; -import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; +import series from '../fixtures/mock_data/date_histogram/_series'; +import columns from '../fixtures/mock_data/date_histogram/_columns'; +import rows from '../fixtures/mock_data/date_histogram/_rows'; +import stackedSeries from '../fixtures/mock_data/date_histogram/_stacked_series'; import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../../persisted_state'; +import 'ui/persisted_state'; + +import getFixturesVislibVisFixtureProvider from '../fixtures/_vis_fixture'; const dateHistogramArray = [series, columns, rows, stackedSeries]; const names = ['series', 'columns', 'rows', 'stackedSeries']; @@ -40,7 +41,8 @@ dateHistogramArray.forEach(function(data, i) { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); vis.render(data, persistedState); }) @@ -106,12 +108,12 @@ dateHistogramArray.forEach(function(data, i) { describe('removeAll Method', function() { beforeEach(function() { ngMock.inject(function() { - vis.handler.removeAll(vis.el); + vis.handler.removeAll(vis.element); }); }); it('should remove all DOM elements from the el', function() { - expect($(vis.el).children().length).to.be(0); + expect($(vis.element).children().length).to.be(0); }); }); @@ -121,7 +123,7 @@ dateHistogramArray.forEach(function(data, i) { }); it('should return an error classed DOM element with a text message', function() { - expect($(vis.el).find('.error').length).to.be(1); + expect($(vis.element).find('.error').length).to.be(1); expect($('.error h4').html()).to.be('This is an error!'); }); }); diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js similarity index 65% rename from src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js index 853a00d035a07..c8636f34ce6f8 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout.js @@ -20,16 +20,16 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import 'ui/persisted_state'; // Data -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import columns from 'fixtures/vislib/mock_data/date_histogram/_columns'; -import rows from 'fixtures/vislib/mock_data/date_histogram/_rows'; -import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; +import series from '../fixtures/mock_data/date_histogram/_series'; +import columns from '../fixtures/mock_data/date_histogram/_columns'; +import rows from '../fixtures/mock_data/date_histogram/_rows'; +import stackedSeries from '../fixtures/mock_data/date_histogram/_stacked_series'; import $ from 'jquery'; import { Layout } from '../../../lib/layout/layout'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../../persisted_state'; +import getFixturesVislibVisFixtureProvider from '../fixtures/_vis_fixture'; import { VisConfig } from '../../../lib/vis_config'; const dateHistogramArray = [series, columns, rows, stackedSeries]; @@ -46,7 +46,8 @@ dateHistogramArray.forEach(function(data, i) { beforeEach(function() { ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); vis.render(data, persistedState); numberOfCharts = vis.handler.charts.length; @@ -59,17 +60,17 @@ dateHistogramArray.forEach(function(data, i) { describe('createLayout Method', function() { it('should append all the divs', function() { - expect($(vis.el).find('.visWrapper').length).to.be(1); - expect($(vis.el).find('.visAxis--y').length).to.be(2); - expect($(vis.el).find('.visWrapper__column').length).to.be(1); - expect($(vis.el).find('.visAxis__column--y').length).to.be(2); - expect($(vis.el).find('.y-axis-title').length).to.be.above(0); - expect($(vis.el).find('.visAxis__splitAxes--y').length).to.be(2); - expect($(vis.el).find('.visAxis__spacer--y').length).to.be(4); - expect($(vis.el).find('.visWrapper__chart').length).to.be(numberOfCharts); - expect($(vis.el).find('.visAxis--x').length).to.be(2); - expect($(vis.el).find('.visAxis__splitAxes--x').length).to.be(2); - expect($(vis.el).find('.x-axis-title').length).to.be.above(0); + expect($(vis.element).find('.visWrapper').length).to.be(1); + expect($(vis.element).find('.visAxis--y').length).to.be(2); + expect($(vis.element).find('.visWrapper__column').length).to.be(1); + expect($(vis.element).find('.visAxis__column--y').length).to.be(2); + expect($(vis.element).find('.y-axis-title').length).to.be.above(0); + expect($(vis.element).find('.visAxis__splitAxes--y').length).to.be(2); + expect($(vis.element).find('.visAxis__spacer--y').length).to.be(4); + expect($(vis.element).find('.visWrapper__chart').length).to.be(numberOfCharts); + expect($(vis.element).find('.visAxis--x').length).to.be(2); + expect($(vis.element).find('.visAxis__splitAxes--x').length).to.be(2); + expect($(vis.element).find('.x-axis-title').length).to.be.above(0); }); }); @@ -81,35 +82,36 @@ dateHistogramArray.forEach(function(data, i) { }, data, persistedState, - vis.el + vis.element, + () => undefined ); testLayout = new Layout(visConfig); }); it('should append a div with the correct class name', function() { - expect($(vis.el).find('.chart').length).to.be(numberOfCharts); + expect($(vis.element).find('.chart').length).to.be(numberOfCharts); }); it('should bind data to the DOM element', function() { expect( - !!$(vis.el) + !!$(vis.element) .find('.chart') .data() ).to.be(true); }); it('should create children', function() { - expect(typeof $(vis.el).find('.x-axis-div')).to.be('object'); + expect(typeof $(vis.element).find('.x-axis-div')).to.be('object'); }); it('should call split function when provided', function() { - expect(typeof $(vis.el).find('.x-axis-div')).to.be('object'); + expect(typeof $(vis.element).find('.x-axis-div')).to.be('object'); }); it('should throw errors when incorrect arguments provided', function() { expect(function() { testLayout.layout({ - parent: vis.el, + parent: vis.element, type: undefined, class: 'chart', }); @@ -131,7 +133,7 @@ dateHistogramArray.forEach(function(data, i) { expect(function() { testLayout.layout({ - parent: vis.el, + parent: vis.element, type: function(d) { return d; }, @@ -143,26 +145,26 @@ dateHistogramArray.forEach(function(data, i) { describe('appendElem Method', function() { beforeEach(function() { - vis.handler.layout.appendElem(vis.el, 'svg', 'column'); + vis.handler.layout.appendElem(vis.element, 'svg', 'column'); vis.handler.layout.appendElem('.visChart', 'div', 'test'); }); it('should append DOM element to el with a class name', function() { - expect(typeof $(vis.el).find('.column')).to.be('object'); - expect(typeof $(vis.el).find('.test')).to.be('object'); + expect(typeof $(vis.element).find('.column')).to.be('object'); + expect(typeof $(vis.element).find('.test')).to.be('object'); }); }); describe('removeAll Method', function() { beforeEach(function() { - d3.select(vis.el) + d3.select(vis.element) .append('div') .attr('class', 'visualize'); - vis.handler.layout.removeAll(vis.el); + vis.handler.layout.removeAll(vis.element); }); it('should remove all DOM elements from the el', function() { - expect($(vis.el).children().length).to.be(0); + expect($(vis.element).children().length).to.be(0); }); }); }); diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/layout/layout_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/layout_types.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/layout/types/column_layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/layout/types/column_layout.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/types/point_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/point_series.js diff --git a/src/legacy/ui/public/vislib/__tests__/lib/types/testdata_linechart_percentile.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/testdata_linechart_percentile.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/types/testdata_linechart_percentile.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/testdata_linechart_percentile.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/types/testdata_linechart_percentile_result.json b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/testdata_linechart_percentile_result.json similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/lib/types/testdata_linechart_percentile_result.json rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/types/testdata_linechart_percentile_result.json diff --git a/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js similarity index 98% rename from src/legacy/ui/public/vislib/__tests__/lib/vis_config.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js index c9dcd4737b51a..3f0253b4a4670 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/vis_config.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/vis_config.js @@ -20,8 +20,8 @@ import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import 'ui/persisted_state'; import { VisConfig } from '../../lib/vis_config'; -import '../../../persisted_state'; describe('Vislib VisConfig Class Test Suite', function() { let el; @@ -101,7 +101,8 @@ describe('Vislib VisConfig Class Test Suite', function() { }, data, new PersistedState(), - el + el, + () => undefined ); }) ); diff --git a/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js similarity index 98% rename from src/legacy/ui/public/vislib/__tests__/lib/x_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js index 2fb7763756975..09fe067537c7f 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/x_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/x_axis.js @@ -21,8 +21,8 @@ import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import 'ui/persisted_state'; import $ from 'jquery'; -import '../../../persisted_state'; import { Axis } from '../../lib/axis'; import { VisConfig } from '../../lib/vis_config'; @@ -124,7 +124,8 @@ describe('Vislib xAxis Class Test Suite', function() { }, data, persistedState, - $('.x-axis-div')[0] + $('.x-axis-div')[0], + () => undefined ); xAxis = new Axis(visConfig, { type: 'category', diff --git a/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js similarity index 99% rename from src/legacy/ui/public/vislib/__tests__/lib/y_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js index 0189b8b960d32..e857aca3bf3ed 100644 --- a/src/legacy/ui/public/vislib/__tests__/lib/y_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/y_axis.js @@ -21,8 +21,8 @@ import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; +import 'ui/persisted_state'; import $ from 'jquery'; -import '../../../persisted_state'; import { Axis } from '../../lib/axis'; import { VisConfig } from '../../lib/vis_config'; @@ -97,7 +97,8 @@ function createData(seriesData) { }, data, persistedState, - node + node, + () => undefined ); return new YAxis( visConfig, diff --git a/src/legacy/ui/public/vislib/__tests__/vis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js similarity index 92% rename from src/legacy/ui/public/vislib/__tests__/vis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js index f10f44b7100d8..a6d1c4daf5d2c 100644 --- a/src/legacy/ui/public/vislib/__tests__/vis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/vis.js @@ -18,16 +18,17 @@ */ import _ from 'lodash'; -import expect from '@kbn/expect'; +import $ from 'jquery'; import ngMock from 'ng_mock'; -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import columns from 'fixtures/vislib/mock_data/date_histogram/_columns'; -import rows from 'fixtures/vislib/mock_data/date_histogram/_rows'; -import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; -import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../persisted_state'; +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + +import series from './lib/fixtures/mock_data/date_histogram/_series'; +import columns from './lib/fixtures/mock_data/date_histogram/_columns'; +import rows from './lib/fixtures/mock_data/date_histogram/_rows'; +import stackedSeries from './lib/fixtures/mock_data/date_histogram/_stacked_series'; +import getFixturesVislibVisFixtureProvider from './lib/fixtures/_vis_fixture'; const dataArray = [series, columns, rows, stackedSeries]; @@ -45,9 +46,10 @@ dataArray.forEach(function(data, i) { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(); persistedState = new ($injector.get('PersistedState'))(); - secondVis = Private(FixturesVislibVisFixtureProvider)(); + secondVis = getVis(); }) ); @@ -99,7 +101,7 @@ dataArray.forEach(function(data, i) { }); it('should not remove visualizations that have not been destroyed', function() { - expect($(vis.el).find('.visWrapper').length).to.be(1); + expect($(vis.element).find('.visWrapper').length).to.be(1); }); }); diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js similarity index 93% rename from src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js index d81fd66f1e111..7fe350bd85e05 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/area_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/area_chart.js @@ -18,20 +18,22 @@ */ import d3 from 'd3'; -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; - import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; + +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; + const dataTypesArray = { - 'series pos': require('fixtures/vislib/mock_data/date_histogram/_series'), - 'series pos neg': require('fixtures/vislib/mock_data/date_histogram/_series_pos_neg'), - 'series neg': require('fixtures/vislib/mock_data/date_histogram/_series_neg'), - 'term columns': require('fixtures/vislib/mock_data/terms/_columns'), - 'range rows': require('fixtures/vislib/mock_data/range/_rows'), - stackedSeries: require('fixtures/vislib/mock_data/date_histogram/_stacked_series'), + 'series pos': require('../lib/fixtures/mock_data/date_histogram/_series'), + 'series pos neg': require('../lib/fixtures/mock_data/date_histogram/_series_pos_neg'), + 'series neg': require('../lib/fixtures/mock_data/date_histogram/_series_neg'), + 'term columns': require('../lib/fixtures/mock_data/terms/_columns'), + 'range rows': require('../lib/fixtures/mock_data/range/_rows'), + stackedSeries: require('../lib/fixtures/mock_data/date_histogram/_stacked_series'), }; const visLibParams = { @@ -49,7 +51,8 @@ _.forOwn(dataTypesArray, function(dataType, dataTypeName) { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); vis.on('brush', _.noop); vis.render(dataType, persistedState); diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js similarity index 93% rename from src/legacy/ui/public/vislib/__tests__/visualizations/chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js index f876db0aa6b22..088d3377af4dd 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/chart.js @@ -18,15 +18,16 @@ */ import d3 from 'd3'; -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { VislibVisProvider } from '../../vis'; -import '../../../persisted_state'; + +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + import { Chart } from '../../visualizations/_chart'; +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; describe('Vislib _chart Test Suite', function() { let persistedState; - let Vis; let vis; let el; let myChart; @@ -111,7 +112,7 @@ describe('Vislib _chart Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - Vis = Private(VislibVisProvider); + const getVis = getFixturesVislibVisFixtureProvider(Private); persistedState = new ($injector.get('PersistedState'))(); el = d3 @@ -126,7 +127,7 @@ describe('Vislib _chart Test Suite', function() { zeroFill: true, }; - vis = new Vis(el[0][0], config); + vis = getVis(config, el[0][0]); vis.render(data, persistedState); myChart = vis.handler.charts[0]; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js similarity index 91% rename from src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js index 2253783e7e644..d02060ef29bdd 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/column_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/column_chart.js @@ -17,24 +17,25 @@ * under the License. */ -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + // Data -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import seriesPosNeg from 'fixtures/vislib/mock_data/date_histogram/_series_pos_neg'; -import seriesNeg from 'fixtures/vislib/mock_data/date_histogram/_series_neg'; -import termsColumns from 'fixtures/vislib/mock_data/terms/_columns'; -import histogramRows from 'fixtures/vislib/mock_data/histogram/_rows'; -import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; -import { seriesMonthlyInterval } from 'fixtures/vislib/mock_data/date_histogram/_series_monthly_interval'; -import { rowsSeriesWithHoles } from 'fixtures/vislib/mock_data/date_histogram/_rows_series_with_holes'; -import rowsWithZeros from 'fixtures/vislib/mock_data/date_histogram/_rows'; +import series from '../lib/fixtures/mock_data/date_histogram/_series'; +import seriesPosNeg from '../lib/fixtures/mock_data/date_histogram/_series_pos_neg'; +import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; +import termsColumns from '../lib/fixtures/mock_data/terms/_columns'; +import histogramRows from '../lib/fixtures/mock_data/histogram/_rows'; +import stackedSeries from '../lib/fixtures/mock_data/date_histogram/_stacked_series'; +import { seriesMonthlyInterval } from '../lib/fixtures/mock_data/date_histogram/_series_monthly_interval'; +import { rowsSeriesWithHoles } from '../lib/fixtures/mock_data/date_histogram/_rows_series_with_holes'; +import rowsWithZeros from '../lib/fixtures/mock_data/date_histogram/_rows'; import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; // tuple, with the format [description, mode, data] const dataTypesArray = [ @@ -69,7 +70,8 @@ dataTypesArray.forEach(function(dataType) { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); vis.on('brush', _.noop); vis.render(data, persistedState); @@ -257,7 +259,8 @@ describe('stackData method - data set with zeros in percentage mode', function() beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); vis.on('brush', _.noop); }) @@ -307,7 +310,8 @@ describe('datumWidth - split chart data set with holes', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); vis.on('brush', _.noop); vis.render(rowsSeriesWithHoles, persistedState); @@ -344,7 +348,8 @@ describe('datumWidth - monthly interval', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); vis.on('brush', _.noop); vis.render(seriesMonthlyInterval, persistedState); diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js similarity index 94% rename from src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js index 45d9d4a2e374b..074b34e1c03c4 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/gauge_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/gauge_chart.js @@ -17,13 +17,15 @@ * under the License. */ -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import $ from 'jquery'; import _ from 'lodash'; -import data from 'fixtures/vislib/mock_data/terms/_seriesMultiple'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; + +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + +import data from '../lib/fixtures/mock_data/terms/_seriesMultiple'; +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; describe('Vislib Gauge Chart Test Suite', function() { let PersistedState; @@ -89,7 +91,7 @@ describe('Vislib Gauge Chart Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vislibVis = Private(FixturesVislibVisFixtureProvider); + vislibVis = getFixturesVislibVisFixtureProvider(Private); PersistedState = $injector.get('PersistedState'); generateVis(); }) diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js similarity index 92% rename from src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js index f1dc4bf07ee31..bf1dbad0b44cf 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/heatmap_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/heatmap_chart.js @@ -17,20 +17,21 @@ * under the License. */ -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; import d3 from 'd3'; +import expect from '@kbn/expect'; +import 'ui/persisted_state'; + // Data -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import seriesPosNeg from 'fixtures/vislib/mock_data/date_histogram/_series_pos_neg'; -import seriesNeg from 'fixtures/vislib/mock_data/date_histogram/_series_neg'; -import termsColumns from 'fixtures/vislib/mock_data/terms/_columns'; -import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; +import series from '../lib/fixtures/mock_data/date_histogram/_series'; +import seriesPosNeg from '../lib/fixtures/mock_data/date_histogram/_series_pos_neg'; +import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; +import termsColumns from '../lib/fixtures/mock_data/terms/_columns'; +import stackedSeries from '../lib/fixtures/mock_data/date_histogram/_stacked_series'; import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; // tuple, with the format [description, mode, data] const dataTypesArray = [ @@ -74,7 +75,7 @@ describe('Vislib Heatmap Chart Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vislibVis = Private(FixturesVislibVisFixtureProvider); + vislibVis = getFixturesVislibVisFixtureProvider(Private); PersistedState = $injector.get('PersistedState'); generateVis(); }) diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js similarity index 92% rename from src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js index 354be1f0ced0f..d010944a19e47 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/line_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/line_chart.js @@ -20,18 +20,19 @@ import d3 from 'd3'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; +import $ from 'jquery'; import _ from 'lodash'; +import 'ui/persisted_state'; + // Data -import seriesPos from 'fixtures/vislib/mock_data/date_histogram/_series'; -import seriesPosNeg from 'fixtures/vislib/mock_data/date_histogram/_series_pos_neg'; -import seriesNeg from 'fixtures/vislib/mock_data/date_histogram/_series_neg'; -import histogramColumns from 'fixtures/vislib/mock_data/histogram/_columns'; -import rangeRows from 'fixtures/vislib/mock_data/range/_rows'; -import termSeries from 'fixtures/vislib/mock_data/terms/_series'; -import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import '../../../persisted_state'; +import seriesPos from '../lib/fixtures/mock_data/date_histogram/_series'; +import seriesPosNeg from '../lib/fixtures/mock_data/date_histogram/_series_pos_neg'; +import seriesNeg from '../lib/fixtures/mock_data/date_histogram/_series_neg'; +import histogramColumns from '../lib/fixtures/mock_data/histogram/_columns'; +import rangeRows from '../lib/fixtures/mock_data/range/_rows'; +import termSeries from '../lib/fixtures/mock_data/terms/_series'; +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; const dataTypes = [ ['series pos', seriesPos], @@ -54,6 +55,7 @@ describe('Vislib Line Chart', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { + const getVis = getFixturesVislibVisFixtureProvider(Private); const visLibParams = { type: 'line', addLegend: true, @@ -61,10 +63,10 @@ describe('Vislib Line Chart', function() { drawLinesBetweenPoints: true, }; - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); - vis.on('brush', _.noop); vis.render(data, persistedState); + vis.on('brush', _.noop); }) ); diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js similarity index 94% rename from src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js index 9d299c4d3a5df..381dfcd387cc2 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/pie_chart.js @@ -18,17 +18,20 @@ */ import d3 from 'd3'; -import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import _ from 'lodash'; -import fixtures from 'fixtures/fake_hierarchical_data'; import $ from 'jquery'; -import FixturesVislibVisFixtureProvider from 'fixtures/vislib/_vis_fixture'; -import { Vis } from '../../../vis'; -import '../../../persisted_state'; + +import expect from '@kbn/expect'; +// TODO: Remove ui imports once converting to jest +import 'ui/persisted_state'; +import { vislibSlicesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; + +import fixtures from 'fixtures/fake_hierarchical_data'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { vislibSlicesResponseHandlerProvider } from '../../../vis/response_handlers/vislib'; -import { tabifyAggResponse } from '../../../agg_response/tabify'; + +import getFixturesVislibVisFixtureProvider from '../lib/fixtures/_vis_fixture'; +import { Vis, tabifyAggResponse } from '../../../legacy_imports'; const rowAgg = [ { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, @@ -129,7 +132,8 @@ describe('No global chart settings', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - chart1 = Private(FixturesVislibVisFixtureProvider)(visLibParams1); + const getVis = getFixturesVislibVisFixtureProvider(Private); + chart1 = getVis(visLibParams1); persistedState = new ($injector.get('PersistedState'))(); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); responseHandler = vislibSlicesResponseHandlerProvider().handler; @@ -163,7 +167,7 @@ describe('No global chart settings', function() { }); it('should render chart titles for all charts', function() { - expect($(chart1.el).find('.visAxis__splitTitles--y').length).to.be(1); + expect($(chart1.element).find('.visAxis__splitTitles--y').length).to.be(1); }); describe('_validatePieData method', function() { @@ -221,7 +225,8 @@ describe('Vislib PieChart Class Test Suite', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject(function(Private, $injector) { - vis = Private(FixturesVislibVisFixtureProvider)(visLibParams); + const getVis = getFixturesVislibVisFixtureProvider(Private); + vis = getVis(visLibParams); persistedState = new ($injector.get('PersistedState'))(); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); responseHandler = vislibSlicesResponseHandlerProvider().handler; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js similarity index 97% rename from src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js index cfe61d6f35198..ec22d43c08cb2 100644 --- a/src/legacy/ui/public/vislib/__tests__/visualizations/time_marker.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/time_marker.js @@ -20,8 +20,8 @@ import d3 from 'd3'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import series from 'fixtures/vislib/mock_data/date_histogram/_series'; -import terms from 'fixtures/vislib/mock_data/terms/_columns'; +import series from '../lib/fixtures/mock_data/date_histogram/_series'; +import terms from '../lib/fixtures/mock_data/terms/_columns'; import $ from 'jquery'; import { TimeMarker } from '../../visualizations/time_marker'; diff --git a/src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js similarity index 100% rename from src/legacy/ui/public/vislib/__tests__/visualizations/vis_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/visualizations/vis_types.js diff --git a/src/legacy/ui/public/vislib/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss similarity index 100% rename from src/legacy/ui/public/vislib/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/_index.scss diff --git a/src/legacy/ui/public/vislib/_variables.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/_variables.scss similarity index 100% rename from src/legacy/ui/public/vislib/_variables.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/_variables.scss diff --git a/src/legacy/ui/public/vislib/components/labels/data_array.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/data_array.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/data_array.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/data_array.js diff --git a/src/legacy/ui/public/vislib/components/labels/flatten_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/flatten_series.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/flatten_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/flatten_series.js diff --git a/src/legacy/ui/public/vislib/components/labels/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/index.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/index.js diff --git a/src/legacy/ui/public/vislib/components/labels/labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/labels.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/labels.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/labels.js diff --git a/src/legacy/ui/public/vislib/components/labels/truncate_labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/truncate_labels.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/truncate_labels.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/truncate_labels.js diff --git a/src/legacy/ui/public/vislib/components/labels/uniq_labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/uniq_labels.js similarity index 100% rename from src/legacy/ui/public/vislib/components/labels/uniq_labels.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/labels/uniq_labels.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/flatten_data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/flatten_data.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/flatten_data.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/flatten_data.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/inject_zeros.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/inject_zeros.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/inject_zeros.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/inject_zeros.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/ordered_x_keys.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/ordered_x_keys.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/ordered_x_keys.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/ordered_x_keys.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/uniq_keys.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/uniq_keys.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/uniq_keys.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/uniq_keys.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/zero_fill_data_array.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_fill_data_array.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/zero_fill_data_array.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_fill_data_array.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/zero_filled_array.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_filled_array.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/zero_filled_array.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_filled_array.js diff --git a/src/legacy/ui/public/vislib/components/zero_injection/zero_injection.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_injection.test.js similarity index 100% rename from src/legacy/ui/public/vislib/components/zero_injection/zero_injection.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/components/zero_injection/zero_injection.test.js diff --git a/src/legacy/ui/public/vislib/errors.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/errors.ts similarity index 95% rename from src/legacy/ui/public/vislib/errors.ts rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/errors.ts index 0c6e720f0ef32..9014349c38d25 100644 --- a/src/legacy/ui/public/vislib/errors.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/errors.ts @@ -19,7 +19,7 @@ /* eslint-disable max-classes-per-file */ -import { KbnError } from '../../../../plugins/kibana_utils/public'; +import { KbnError } from '../../../../../plugins/kibana_utils/public'; export class VislibError extends KbnError { constructor(message: string) { diff --git a/src/legacy/ui/public/vislib/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/index.js similarity index 100% rename from src/legacy/ui/public/vislib/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/index.js diff --git a/src/legacy/ui/public/vislib/lib/_alerts.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_alerts.scss similarity index 100% rename from src/legacy/ui/public/vislib/lib/_alerts.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_alerts.scss diff --git a/src/legacy/ui/public/vislib/lib/_data_label.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_data_label.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/_data_label.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_data_label.js diff --git a/src/legacy/ui/public/vislib/lib/_error_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_error_handler.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/_error_handler.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_error_handler.js diff --git a/src/legacy/ui/public/vislib/lib/_handler.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_handler.scss similarity index 100% rename from src/legacy/ui/public/vislib/lib/_handler.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_handler.scss diff --git a/src/legacy/ui/public/vislib/lib/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_index.scss similarity index 100% rename from src/legacy/ui/public/vislib/lib/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/_index.scss diff --git a/src/legacy/ui/public/vislib/lib/alerts.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/alerts.js similarity index 97% rename from src/legacy/ui/public/vislib/lib/alerts.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/alerts.js index cf79dabf1b07e..086b4e31be1a3 100644 --- a/src/legacy/ui/public/vislib/lib/alerts.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/alerts.js @@ -71,11 +71,11 @@ export class Alerts { const alerts = this.alerts; const vis = this.vis; - $(vis.el) + $(vis.element) .find('.visWrapper__alerts') .append($('
').addClass('visAlerts__tray')); if (!alerts.size()) return; - $(vis.el) + $(vis.element) .find('.visAlerts__tray') .append(alerts.value()); } @@ -89,13 +89,13 @@ export class Alerts { }; if (this.alertDefs.find(alertDef => alertDef.msg === alert.msg)) return; this.alertDefs.push(alert); - $(vis.el) + $(vis.element) .find('.visAlerts__tray') .append(this._addAlert(alert)); } destroy() { - $(this.vis.el) + $(this.vis.element) .find('.visWrapper__alerts') .remove(); } diff --git a/src/legacy/ui/public/vislib/lib/axis/axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis.js diff --git a/src/legacy/ui/public/vislib/lib/axis/axis_config.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_config.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/axis_config.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_config.js diff --git a/src/legacy/ui/public/vislib/lib/axis/axis_labels.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/axis_labels.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js diff --git a/src/legacy/ui/public/vislib/lib/axis/axis_scale.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_scale.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/axis_scale.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_scale.js diff --git a/src/legacy/ui/public/vislib/lib/axis/axis_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_title.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/axis_title.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_title.js diff --git a/src/legacy/ui/public/vislib/lib/axis/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/index.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/index.js diff --git a/src/legacy/ui/public/vislib/lib/axis/scale_modes.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/scale_modes.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/scale_modes.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/scale_modes.js diff --git a/src/legacy/ui/public/vislib/lib/axis/time_ticks.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/time_ticks.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/time_ticks.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/time_ticks.js diff --git a/src/legacy/ui/public/vislib/lib/axis/time_ticks.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/time_ticks.test.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/axis/time_ticks.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/time_ticks.test.js diff --git a/src/legacy/ui/public/vislib/lib/chart_grid.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_grid.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/chart_grid.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_grid.js diff --git a/src/legacy/ui/public/vislib/lib/chart_title.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js similarity index 98% rename from src/legacy/ui/public/vislib/lib/chart_title.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js index f79d14a3deaa6..1c84f98614b05 100644 --- a/src/legacy/ui/public/vislib/lib/chart_title.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/chart_title.js @@ -19,8 +19,9 @@ import d3 from 'd3'; import _ from 'lodash'; + import { ErrorHandler } from './_error_handler'; -import { Tooltip } from '../../vis/components/tooltip'; +import { Tooltip } from '../../legacy_imports'; export class ChartTitle extends ErrorHandler { constructor(visConfig) { diff --git a/src/legacy/ui/public/vislib/lib/data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js similarity index 98% rename from src/legacy/ui/public/vislib/lib/data.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js index c10449c681a3c..c7824c43eeec5 100644 --- a/src/legacy/ui/public/vislib/lib/data.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js @@ -19,11 +19,11 @@ import d3 from 'd3'; 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 { vislibColor } from '../../vis/components/color/color'; -import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities'; +import { getFormat } from '../../legacy_imports'; /** * Provides an API for pulling values off the data @@ -35,8 +35,9 @@ import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities'; * @param attr {Object|*} Visualization options */ export class Data { - constructor(data, uiState) { + constructor(data, uiState, vislibColor) { this.uiState = uiState; + this.vislibColor = vislibColor; this.data = this.copyDataObj(data); this.type = this.getDataType(); this._cleanVisData(); @@ -472,7 +473,7 @@ export class Data { const defaultColors = this.uiState.get('vis.defaultColors'); const overwriteColors = this.uiState.get('vis.colors'); const colors = defaultColors ? _.defaults({}, overwriteColors, defaultColors) : overwriteColors; - return vislibColor(this.getLabels(), colors); + return this.vislibColor(this.getLabels(), colors); } /** @@ -482,7 +483,7 @@ export class Data { * @returns {Function} Performs lookup on string and returns hex color */ getPieColorFunc() { - return vislibColor( + return this.vislibColor( this.pieNames(this.getVisData()).map(function(d) { return d.label; }), diff --git a/src/legacy/ui/public/vislib/lib/dispatch.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/dispatch.js similarity index 92% rename from src/legacy/ui/public/vislib/lib/dispatch.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/dispatch.js index fb5cc127c27fd..404f7ef82d97f 100644 --- a/src/legacy/ui/public/vislib/lib/dispatch.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/dispatch.js @@ -20,10 +20,8 @@ import d3 from 'd3'; import { get } from 'lodash'; import $ from 'jquery'; -import { SimpleEmitter } from '../../utils/simple_emitter'; -import chrome from 'ui/chrome'; -const config = chrome.getUiSettingsClient(); +import { SimpleEmitter } from '../../legacy_imports'; /** * Handles event responses @@ -33,9 +31,10 @@ const config = chrome.getUiSettingsClient(); * @param handler {Object} Reference to Handler Class Object */ export class Dispatch extends SimpleEmitter { - constructor(handler) { + constructor(handler, uiSettings) { super(); this.handler = handler; + this.uiSettings = uiSettings; this._listeners = {}; } @@ -196,7 +195,7 @@ export class Dispatch extends SimpleEmitter { const addEvent = this.addEvent; const $el = this.handler.el; if (!this.handler.highlight) { - this.handler.highlight = self.highlight; + this.handler.highlight = self.getHighlighter(self.uiSettings); } function hover(d, i) { @@ -289,21 +288,23 @@ export class Dispatch extends SimpleEmitter { } /** - * Highlight the element that is under the cursor + * return function to Highlight the element that is under the cursor * by reducing the opacity of all the elements on the graph. - * @param element {d3.Selection} - * @method highlight + * @param uiSettings + * @method getHighlighter */ - highlight(element) { - const label = this.getAttribute('data-label'); - if (!label) return; - const dimming = config.get('visualization:dimmingOpacity'); - $(element) - .parent() - .find('[data-label]') - .css('opacity', 1) //Opacity 1 is needed to avoid the css application - .not((els, el) => String($(el).data('label')) === label) - .css('opacity', justifyOpacity(dimming)); + getHighlighter(uiSettings) { + return function highlight(element) { + const label = this.getAttribute('data-label'); + if (!label) return; + const dimming = uiSettings.get('visualization:dimmingOpacity'); + $(element) + .parent() + .find('[data-label]') + .css('opacity', 1) //Opacity 1 is needed to avoid the css application + .not((els, el) => String($(el).data('label')) === label) + .css('opacity', justifyOpacity(dimming)); + }; } /** diff --git a/src/legacy/ui/public/vislib/lib/handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/handler.js similarity index 96% rename from src/legacy/ui/public/vislib/lib/handler.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/handler.js index 6047faa0c6b15..b887b61578cc4 100644 --- a/src/legacy/ui/public/vislib/lib/handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/handler.js @@ -20,15 +20,16 @@ import d3 from 'd3'; import _ from 'lodash'; import MarkdownIt from 'markdown-it'; + import { NoResults } from '../errors'; -import { Binder } from '../../binder'; import { Layout } from './layout/layout'; import { ChartTitle } from './chart_title'; import { Alerts } from './alerts'; import { Axis } from './axis/axis'; import { ChartGrid as Grid } from './chart_grid'; import { visTypes as chartTypes } from '../visualizations/vis_types'; -import { dispatchRenderComplete } from '../../../../../plugins/kibana_utils/public'; +import { Binder } from '../../legacy_imports'; +import { dispatchRenderComplete } from '../../../../../../plugins/kibana_utils/public'; const markdownIt = new MarkdownIt({ html: false, @@ -45,9 +46,10 @@ const markdownIt = new MarkdownIt({ * create the visualization */ export class Handler { - constructor(vis, visConfig) { + constructor(vis, visConfig, deps) { this.el = visConfig.get('el'); this.ChartClass = chartTypes[visConfig.get('type')]; + this.deps = deps; this.charts = []; this.vis = vis; @@ -151,7 +153,7 @@ export class Handler { let loadedCount = 0; const chartSelection = selection.selectAll('.chart'); chartSelection.each(function(chartData) { - const chart = new self.ChartClass(self, this, chartData); + const chart = new self.ChartClass(self, this, chartData, self.deps); self.vis.eventNames().forEach(function(event) { self.enable(event, chart); diff --git a/src/legacy/ui/public/vislib/lib/layout/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/_index.scss similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/_index.scss diff --git a/src/legacy/ui/public/vislib/lib/layout/_layout.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/_layout.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss diff --git a/src/legacy/ui/public/vislib/lib/layout/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/index.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/index.js diff --git a/src/legacy/ui/public/vislib/lib/layout/layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/layout.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/layout.js diff --git a/src/legacy/ui/public/vislib/lib/layout/layout_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/layout_types.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/layout_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/layout_types.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/chart_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/chart_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/chart_title_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/chart_title_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/x_axis_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/x_axis_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/y_axis_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/column_chart/y_axis_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/gauge_chart/chart_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/gauge_chart/chart_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/pie_chart/chart_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/pie_chart/chart_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js diff --git a/src/legacy/ui/public/vislib/lib/layout/types/column_layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/column_layout.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/types/column_layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/column_layout.js diff --git a/src/legacy/ui/public/vislib/lib/layout/types/gauge_layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/gauge_layout.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/types/gauge_layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/gauge_layout.js diff --git a/src/legacy/ui/public/vislib/lib/layout/types/pie_layout.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/pie_layout.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/layout/types/pie_layout.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/layout/types/pie_layout.js diff --git a/src/legacy/ui/public/vislib/lib/types/gauge.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/gauge.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/types/gauge.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/gauge.js diff --git a/src/legacy/ui/public/vislib/lib/types/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/index.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/types/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/index.js diff --git a/src/legacy/ui/public/vislib/lib/types/pie.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/pie.js similarity index 100% rename from src/legacy/ui/public/vislib/lib/types/pie.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/pie.js diff --git a/src/legacy/ui/public/vislib/lib/types/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js similarity index 98% rename from src/legacy/ui/public/vislib/lib/types/point_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js index 332f7408ebc66..eab3bc02f4eec 100644 --- a/src/legacy/ui/public/vislib/lib/types/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.js @@ -202,7 +202,7 @@ export const vislibPointSeriesTypes = { 'Positive and negative values are not accurately represented by stacked ' + 'area charts. Either changing the chart mode to "overlap" or using a ' + 'bar chart is recommended.', - test: function(vis, data) { + test: function(_, data) { if (!data.shouldBeStacked() || data.maxNumberOfSeries() < 2) return; const hasPos = data.getYMax(data._getY) > 0; @@ -216,7 +216,7 @@ export const vislibPointSeriesTypes = { 'Parts of or the entire area chart might not be displayed due to null ' + 'values in the data. A line chart is recommended when displaying data ' + 'with null values.', - test: function(vis, data) { + test: function(_, data) { return data.hasNullValues(); }, }, @@ -229,7 +229,7 @@ export const vislibPointSeriesTypes = { const tooManySeries = defaults.charts.length && defaults.charts[0].series.length > cfg.heatmapMaxBuckets; if (hasCharts && tooManySeries) { - defaults.error = i18n.translate('common.ui.vislib.heatmap.maxBucketsText', { + defaults.error = i18n.translate('kbnVislibVisTypes.vislib.heatmap.maxBucketsText', { defaultMessage: 'There are too many series defined ({nr}). The configured maximum is {max}.', values: { diff --git a/src/legacy/ui/public/vislib/lib/types/point_series.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js similarity index 98% rename from src/legacy/ui/public/vislib/lib/types/point_series.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js index cada6127282d8..38a6be548594f 100644 --- a/src/legacy/ui/public/vislib/lib/types/point_series.test.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import stackedSeries from '../../../../../../fixtures/vislib/mock_data/date_histogram/_stacked_series'; +import stackedSeries from '../../__tests__/lib/fixtures/mock_data/date_histogram/_stacked_series'; import { vislibPointSeriesTypes } from './point_series'; describe('vislibPointSeriesTypes', () => { diff --git a/src/legacy/ui/public/vislib/lib/vis_config.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/vis_config.js similarity index 93% rename from src/legacy/ui/public/vislib/lib/vis_config.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/vis_config.js index 5f10e89474809..091e6b1752d8d 100644 --- a/src/legacy/ui/public/vislib/lib/vis_config.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/vis_config.js @@ -35,8 +35,8 @@ const DEFAULT_VIS_CONFIG = { }; export class VisConfig { - constructor(visConfigArgs, data, uiState, el) { - this.data = new Data(data, uiState); + constructor(visConfigArgs, data, uiState, el, vislibColor) { + this.data = new Data(data, uiState, vislibColor); const visType = visTypes[visConfigArgs.type]; const typeDefaults = visType(visConfigArgs, this.data); diff --git a/src/legacy/ui/public/vislib/partials/touchdown.tmpl.html b/src/legacy/core_plugins/vis_type_vislib/public/vislib/partials/touchdown.tmpl.html similarity index 100% rename from src/legacy/ui/public/vislib/partials/touchdown.tmpl.html rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/partials/touchdown.tmpl.html diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/vis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/vis.js new file mode 100644 index 0000000000000..32afb6a008b61 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/vis.js @@ -0,0 +1,184 @@ +/* + * 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 d3 from 'd3'; +import { EventEmitter } from 'events'; + +import { VislibError } from './errors'; +import { VisConfig } from './lib/vis_config'; +import { Handler } from './lib/handler'; + +/** + * Creates the visualizations. + * + * @class Vis + * @constructor + * @param element {HTMLElement} jQuery selected HTML element + * @param config {Object} Parameters that define the chart type and chart options + */ +export class Vis extends EventEmitter { + constructor(element, visConfigArgs, deps) { + super(); + this.element = element.get ? element.get(0) : element; + this.visConfigArgs = _.cloneDeep(visConfigArgs); + this.visConfigArgs.dimmingOpacity = deps.uiSettings.get('visualization:dimmingOpacity'); + this.visConfigArgs.heatmapMaxBuckets = deps.uiSettings.get('visualization:heatmap:maxBuckets'); + this.deps = deps; + } + + hasLegend() { + return this.visConfigArgs.addLegend; + } + + initVisConfig(data, uiState) { + this.data = data; + this.uiState = uiState; + this.visConfig = new VisConfig( + this.visConfigArgs, + this.data, + this.uiState, + this.element, + this.deps.vislibColor + ); + } + + /** + * Renders the visualization + * + * @method render + * @param data {Object} Elasticsearch query results + */ + render(data, uiState) { + if (!data) { + throw new Error('No valid data!'); + } + + if (this.handler) { + this.data = null; + this._runOnHandler('destroy'); + } + + this.initVisConfig(data, uiState); + + this.handler = new Handler(this, this.visConfig, this.deps); + this._runOnHandler('render'); + } + + getLegendLabels() { + return this.visConfig ? this.visConfig.get('legend.labels', null) : null; + } + + getLegendColors() { + return this.visConfig ? this.visConfig.get('legend.colors', null) : null; + } + + _runOnHandler(method) { + try { + this.handler[method](); + } catch (error) { + if (error instanceof VislibError) { + error.displayToScreen(this.handler); + } else { + throw error; + } + } + } + + /** + * Destroys the visualization + * Removes chart and all elements associated with it. + * Removes chart and all elements associated with it. + * Remove event listeners and pass destroy call down to owned objects. + * + * @method destroy + */ + destroy() { + const selection = d3.select(this.element).select('.visWrapper'); + + if (this.handler) this._runOnHandler('destroy'); + + selection.remove(); + } + + /** + * Sets attributes on the visualization + * + * @method set + * @param name {String} An attribute name + * @param val {*} Value to which the attribute name is set + */ + set(name, val) { + this.visConfigArgs[name] = val; + this.render(this.data, this.uiState); + } + + /** + * Gets attributes from the visualization + * + * @method get + * @param name {String} An attribute name + * @returns {*} The value of the attribute name + */ + get(name) { + return this.visConfig.get(name); + } + + /** + * Turns on event listeners. + * + * @param event {String} + * @param listener{Function} + * @returns {*} + */ + on(event, listener) { + const first = this.listenerCount(event) === 0; + const ret = EventEmitter.prototype.on.call(this, event, listener); + const added = this.listenerCount(event) > 0; + + // if this is the first listener added for the event + // enable the event in the handler + if (first && added && this.handler) this.handler.enable(event); + + return ret; + } + + /** + * Turns off event listeners. + * + * @param event {String} + * @param listener{Function} + * @returns {*} + */ + off(event, listener) { + const last = this.listenerCount(event) === 1; + const ret = EventEmitter.prototype.off.call(this, event, listener); + const removed = this.listenerCount(event) === 0; + + // Once all listeners are removed, disable the events in the handler + if (last && removed && this.handler) this.handler.disable(event); + return ret; + } + + removeAllListeners(event) { + const ret = EventEmitter.prototype.removeAllListeners.call(this, event); + this.handler.disable(event); + return ret; + } +} diff --git a/src/legacy/ui/public/vislib/vislib.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/vislib.js similarity index 82% rename from src/legacy/ui/public/vislib/vislib.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/vislib.js index 847deb8273a73..024dee60ef2bf 100644 --- a/src/legacy/ui/public/vislib/vislib.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/vislib.js @@ -23,8 +23,7 @@ import './lib/types'; import './lib/layout/layout_types'; import './lib/data'; import './visualizations/vis_types'; -import { mappedColors } from '../vis/components/color/mapped_colors'; -import { VislibVisProvider } from './vis'; +import { Vis } from './vis'; // prefetched for faster optimization runs // end prefetching @@ -36,11 +35,9 @@ import { VislibVisProvider } from './vis'; * @main vislib * @return {Object} Contains the version number and the Vis Class for creating visualizations */ -export function VislibProvider(Private, $rootScope) { - $rootScope.$on('$routeChangeStart', () => mappedColors.purge()); - +export function VislibProvider() { return { version: '0.0.0', - Vis: Private(VislibVisProvider), + Vis, }; } diff --git a/src/legacy/ui/public/vislib/visualizations/_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js similarity index 81% rename from src/legacy/ui/public/vislib/visualizations/_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js index 2fbd96d6a070a..ac6e8130a846a 100644 --- a/src/legacy/ui/public/vislib/visualizations/_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/_chart.js @@ -19,12 +19,10 @@ import d3 from 'd3'; import _ from 'lodash'; + import { dataLabel } from '../lib/_data_label'; import { Dispatch } from '../lib/dispatch'; -import { Tooltip } from '../../vis/components/tooltip'; -import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities'; -import { getHierarchicalTooltipFormatter } from '../../vis/components/tooltip/_hierarchical_tooltip_formatter'; -import { getPointSeriesTooltipFormatter } from '../../vis/components/tooltip/_pointseries_tooltip_formatter'; +import { Tooltip, getFormat } from '../../legacy_imports'; /** * The Base Class for all visualizations. @@ -36,26 +34,26 @@ import { getPointSeriesTooltipFormatter } from '../../vis/components/tooltip/_po * @param chartData {Object} Elasticsearch query results for this specific chart */ export class Chart { - constructor(handler, el, chartData) { + constructor(handler, element, chartData, deps) { this.handler = handler; - this.chartEl = el; + this.chartEl = element; this.chartData = chartData; this.tooltips = []; - const events = (this.events = new Dispatch(handler)); + const events = (this.events = new Dispatch(handler, deps.uiSettings)); const fieldFormatter = getFormat(this.handler.data.get('tooltipFormatter')); const tooltipFormatterProvider = this.handler.visConfig.get('type') === 'pie' - ? getHierarchicalTooltipFormatter() - : getPointSeriesTooltipFormatter(); + ? deps.getHierarchicalTooltipFormatter() + : deps.getPointSeriesTooltipFormatter(); const tooltipFormatter = tooltipFormatterProvider(fieldFormatter); if (this.handler.visConfig && this.handler.visConfig.get('addTooltip', false)) { - const $el = this.handler.el; + const element = this.handler.el; // Add tooltip - this.tooltip = new Tooltip('chart', $el, tooltipFormatter, events); + this.tooltip = new Tooltip('chart', element, tooltipFormatter, events); this.tooltips.push(this.tooltip); } diff --git a/src/legacy/ui/public/vislib/visualizations/gauge_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js similarity index 97% rename from src/legacy/ui/public/vislib/visualizations/gauge_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js index c67b1b8881d69..729c664032603 100644 --- a/src/legacy/ui/public/vislib/visualizations/gauge_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauge_chart.js @@ -22,8 +22,8 @@ import { Chart } from './_chart'; import { gaugeTypes } from './gauges/gauge_types'; export class GaugeChart extends Chart { - constructor(handler, chartEl, chartData) { - super(handler, chartEl, chartData); + constructor(handler, chartEl, chartData, deps) { + super(handler, chartEl, chartData, deps); this.gaugeConfig = handler.visConfig.get('gauge', {}); this.gauge = new gaugeTypes[this.gaugeConfig.type](this); } diff --git a/src/legacy/ui/public/vislib/visualizations/gauges/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/_index.scss similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/gauges/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/_index.scss diff --git a/src/legacy/ui/public/vislib/visualizations/gauges/_meter.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/_meter.scss similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/gauges/_meter.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/_meter.scss diff --git a/src/legacy/ui/public/vislib/visualizations/gauges/gauge_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/gauge_types.js similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/gauges/gauge_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/gauge_types.js diff --git a/src/legacy/ui/public/vislib/visualizations/gauges/meter.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/meter.js similarity index 99% rename from src/legacy/ui/public/vislib/visualizations/gauges/meter.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/meter.js index 25da3ba957181..f519914662251 100644 --- a/src/legacy/ui/public/vislib/visualizations/gauges/meter.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/gauges/meter.js @@ -19,7 +19,8 @@ import d3 from 'd3'; import _ from 'lodash'; -import { getHeatmapColors } from '../../components/color/heatmap_color'; + +import { getHeatmapColors } from '../../../legacy_imports'; const arcAngles = { angleFactor: 0.75, diff --git a/src/legacy/ui/public/vislib/visualizations/pie_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js similarity index 99% rename from src/legacy/ui/public/vislib/visualizations/pie_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js index 6d51c69892bc0..a2cbf0fe295ce 100644 --- a/src/legacy/ui/public/vislib/visualizations/pie_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/pie_chart.js @@ -42,8 +42,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class PieChart extends Chart { - constructor(handler, chartEl, chartData) { - super(handler, chartEl, chartData); + constructor(handler, chartEl, chartData, deps) { + super(handler, chartEl, chartData, deps); const charts = this.handler.data.getVisData(); this._validatePieData(charts); this._attr = _.defaults(handler.visConfig.get('chart', {}), defaults); diff --git a/src/legacy/ui/public/vislib/visualizations/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js similarity index 97% rename from src/legacy/ui/public/vislib/visualizations/point_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js index 84dbea2ccc823..c838c51d34bf5 100644 --- a/src/legacy/ui/public/vislib/visualizations/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series.js @@ -20,7 +20,8 @@ import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; -import { Tooltip } from '../../vis/components/tooltip'; + +import { Tooltip } from '../../legacy_imports'; import { Chart } from './_chart'; import { TimeMarker } from './time_marker'; import { seriesTypes } from './point_series/series_types'; @@ -39,9 +40,10 @@ const touchdownTmpl = _.template(touchdownTmplHtml); * @param chartData {Object} Elasticsearch query results for this specific chart */ export class PointSeries extends Chart { - constructor(handler, chartEl, chartData) { - super(handler, chartEl, chartData); + constructor(handler, chartEl, chartData, deps) { + super(handler, chartEl, chartData, deps); + this.deps = deps; this.handler = handler; this.chartData = chartData; this.chartEl = chartEl; @@ -255,7 +257,7 @@ export class PointSeries extends Chart { if (!seriArgs.show) return; const SeriClass = seriTypes[seriArgs.type || self.handler.visConfig.get('chart.type')] || seriTypes.line; - const series = new SeriClass(self.handler, svg, data.series[i], seriArgs); + const series = new SeriClass(self.handler, svg, data.series[i], seriArgs, this.deps); series.events = self.events; svg.call(series.draw()); self.series.push(series); diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/_index.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_index.scss similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/point_series/_index.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_index.scss diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/_labels.scss b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_labels.scss similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/point_series/_labels.scss rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_labels.scss diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_point_series.js similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/_point_series.js diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/area_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js similarity index 98% rename from src/legacy/ui/public/vislib/visualizations/point_series/area_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js index 08147bacdcc98..274ae82271e96 100644 --- a/src/legacy/ui/public/vislib/visualizations/point_series/area_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/area_chart.js @@ -43,8 +43,8 @@ const defaults = { * chart */ export class AreaChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs) { - super(handler, chartEl, chartData, seriesConfigArgs); + constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { + super(handler, chartEl, chartData, seriesConfigArgs, deps); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); this.isOverlapping = this.seriesConfig.mode !== 'stacked'; diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/column_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js similarity index 98% rename from src/legacy/ui/public/vislib/visualizations/point_series/column_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js index 1f18141d86299..4b422d9b1419f 100644 --- a/src/legacy/ui/public/vislib/visualizations/point_series/column_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/column_chart.js @@ -57,8 +57,8 @@ function datumWidth(defaultWidth, datum, nextDatum, scale, gutterWidth, groupCou * @param chartData {Object} Elasticsearch query results for this specific chart */ export class ColumnChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs) { - super(handler, chartEl, chartData, seriesConfigArgs); + constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { + super(handler, chartEl, chartData, seriesConfigArgs, deps); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); this.labelOptions = _.defaults(handler.visConfig.get('labels', {}), defaults.showLabel); } diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/heatmap_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js similarity index 98% rename from src/legacy/ui/public/vislib/visualizations/point_series/heatmap_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js index 1bc33bd5bbade..948cf98a64352 100644 --- a/src/legacy/ui/public/vislib/visualizations/point_series/heatmap_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/heatmap_chart.js @@ -19,10 +19,12 @@ import _ from 'lodash'; import moment from 'moment'; -import { PointSeries } from './_point_series'; -import { getHeatmapColors } from '../../components/color/heatmap_color'; + import { isColorDark } from '@elastic/eui'; +import { PointSeries } from './_point_series'; +import { getHeatmapColors } from '../../../legacy_imports'; + const defaults = { color: undefined, // todo fillColor: undefined, // todo @@ -38,8 +40,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class HeatmapChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs) { - super(handler, chartEl, chartData, seriesConfigArgs); + constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { + super(handler, chartEl, chartData, seriesConfigArgs, deps); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); this.handler.visConfig.set('legend', { diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/line_chart.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js similarity index 98% rename from src/legacy/ui/public/vislib/visualizations/point_series/line_chart.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js index 57090b5424f93..0038b4401b302 100644 --- a/src/legacy/ui/public/vislib/visualizations/point_series/line_chart.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/line_chart.js @@ -42,8 +42,8 @@ const defaults = { * @param chartData {Object} Elasticsearch query results for this specific chart */ export class LineChart extends PointSeries { - constructor(handler, chartEl, chartData, seriesConfigArgs) { - super(handler, chartEl, chartData, seriesConfigArgs); + constructor(handler, chartEl, chartData, seriesConfigArgs, deps) { + super(handler, chartEl, chartData, seriesConfigArgs, deps); this.seriesConfig = _.defaults(seriesConfigArgs || {}, defaults); } diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/series_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/series_types.js similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/point_series/series_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/point_series/series_types.js diff --git a/src/legacy/ui/public/vislib/visualizations/time_marker.d.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/time_marker.d.ts similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/time_marker.d.ts rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/time_marker.d.ts diff --git a/src/legacy/ui/public/vislib/visualizations/time_marker.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/time_marker.js similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/time_marker.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/time_marker.js diff --git a/src/legacy/ui/public/vislib/visualizations/vis_types.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/vis_types.js similarity index 100% rename from src/legacy/ui/public/vislib/visualizations/vis_types.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/visualizations/vis_types.js diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index 92d8ac2c7db3a..e10cbe9aefea6 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -27,4 +27,6 @@ export { } from '../../../ui/public/agg_types/buckets/date_histogram'; export { createFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities'; export { I18nContext } from '../../../ui/public/i18n'; +import chrome from '../../../ui/public/chrome'; +export { chrome as legacyChrome }; import '../../../ui/public/directives/bind'; diff --git a/src/legacy/core_plugins/visualizations/public/expressions/vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js similarity index 96% rename from src/legacy/core_plugins/visualizations/public/expressions/vis.js rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js index cbadfd9da3788..81224b65f7786 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/vis.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js @@ -29,8 +29,9 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; -import { PersistedState } from '../../../../ui/public/persisted_state'; -import { getTypes } from '../np_ready/public/services'; +import { PersistedState } from '../../../legacy_imports'; + +import { getTypes } from '../services'; export class Vis extends EventEmitter { constructor(visState = { type: 'histogram' }) { diff --git a/src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts similarity index 87% rename from src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts index 37b437c1c2dd6..24eb974f6edee 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts @@ -19,13 +19,10 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import chrome from 'ui/chrome'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import { PersistedState } from 'ui/persisted_state'; import { VisResponseValue } from 'src/plugins/visualizations/public'; import { ExpressionFunction, Render } from 'src/plugins/expressions/public'; -import { npStart } from 'ui/new_platform'; -import { getTypes } from '../np_ready/public/services'; +import { PersistedState } from '../../../legacy_imports'; +import { getTypes, getIndexPatterns, getFilterManager } from '../services'; interface Arguments { index?: string | null; @@ -90,15 +87,10 @@ export const visualization = (): ExpressionFunctionVisualization => ({ }, }, async fn(context, args, handlers) { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private') as any; - const indexPatterns = npStart.plugins.data.indexPatterns; - const queryFilter = Private(FilterBarQueryFilterProvider); - const visConfigParams = args.visConfig ? JSON.parse(args.visConfig) : {}; const schemas = args.schemas ? JSON.parse(args.schemas) : {}; const visType = getTypes().get(args.type || 'histogram') as any; - const indexPattern = args.index ? await indexPatterns.get(args.index) : null; + const indexPattern = args.index ? await getIndexPatterns().get(args.index) : null; const uiStateParams = args.uiState ? JSON.parse(args.uiState) : {}; const uiState = new PersistedState(uiStateParams); @@ -114,7 +106,7 @@ export const visualization = (): ExpressionFunctionVisualization => ({ filters: get(context, 'filters', null), uiState, inspectorAdapters: handlers.inspectorAdapters, - queryFilter, + queryFilter: getFilterManager(), forceFetch: true, }); } diff --git a/src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx similarity index 92% rename from src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx index 5f894c7eb60e3..2a12884ecf7c8 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx @@ -17,12 +17,12 @@ * under the License. */ -import chrome from 'ui/chrome'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; +import { legacyChrome } from '../../../legacy_imports'; // @ts-ignore import { Vis } from './vis'; -import { Visualization } from '../np_ready/public/components'; +import { Visualization } from '../components'; export const visualization = () => ({ name: 'visualization', @@ -31,7 +31,7 @@ export const visualization = () => ({ render: async (domNode: HTMLElement, config: any, handlers: any) => { const { visData, visConfig, params } = config; const visType = config.visType || visConfig.type; - const $injector = await chrome.dangerouslyGetActiveInjector(); + const $injector = await legacyChrome.dangerouslyGetActiveInjector(); const $rootScope = $injector.get('$rootScope') as any; if (handlers.vis) { 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 index 7584556324e8b..cfd22f88167c5 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { TypesService, TypesSetup, TypesStart } from './types'; import { @@ -27,13 +28,14 @@ import { setIndexPatterns, setSavedObjects, setUsageCollector, + setFilterManager, } from './services'; import { VisualizeEmbeddableFactory } from '../../embeddable/visualize_embeddable_factory'; import { VISUALIZE_EMBEDDABLE_TYPE } from '../../embeddable'; import { ExpressionsSetup } from '../../../../../../plugins/expressions/public'; import { IEmbeddableSetup } from '../../../../../../plugins/embeddable/public'; -import { visualization as visualizationFunction } from '../../expressions/visualization_function'; -import { visualization as visualizationRenderer } from '../../expressions/visualization_renderer'; +import { visualization as visualizationFunction } from './expressions/visualization_function'; +import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { DataPublicPluginStart } from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; /** @@ -106,6 +108,7 @@ export class VisualizationsPlugin setHttp(core.http); setSavedObjects(core.savedObjects); setIndexPatterns(data.indexPatterns); + setFilterManager(data.query.filterManager); return { types, diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts index 4b426fee6c7da..433c5c7b6df0d 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts @@ -26,7 +26,7 @@ import { } from 'src/core/public'; import { TypesStart } from './types'; import { createGetterSetter } from '../../../../../../plugins/kibana_utils/public'; -import { IndexPatternsContract } from '../../../../../../plugins/data/public'; +import { FilterManager, IndexPatternsContract } from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); @@ -43,6 +43,10 @@ export const [getTypes, setTypes] = createGetterSetter('Types'); export const [getI18n, setI18n] = createGetterSetter('I18n'); +export const [getFilterManager, setFilterManager] = createGetterSetter( + 'FilterManager' +); + export const [getIndexPatterns, setIndexPatterns] = createGetterSetter( 'IndexPatterns' ); diff --git a/src/legacy/ui/public/UI_SYSTEMS.md b/src/legacy/ui/public/UI_SYSTEMS.md index 63fd602075653..37bfbcf92f640 100644 --- a/src/legacy/ui/public/UI_SYSTEMS.md +++ b/src/legacy/ui/public/UI_SYSTEMS.md @@ -6,7 +6,3 @@ In this directory you'll find various UI systems you can use to craft effective * [banners](notify/banners/BANNERS.md) * [toastNotifications](notify/toasts/TOAST_NOTIFICATIONS.md) - -## ui/vislib - -* [VisLib](vislib/VISLIB.md) \ No newline at end of file diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss index 747ad025ef691..f5a1d0a7922a7 100644 --- a/src/legacy/ui/public/_index.scss +++ b/src/legacy/ui/public/_index.scss @@ -26,5 +26,4 @@ // Can't import vis folder here because of cascading issues, it's imported in core_plugins/kibana // @import './vis/index'; -@import './vislib/index'; @import './visualize/index'; diff --git a/src/legacy/ui/public/vislib/components/color/colormaps.ts b/src/legacy/ui/public/color_maps/color_maps.ts similarity index 100% rename from src/legacy/ui/public/vislib/components/color/colormaps.ts rename to src/legacy/ui/public/color_maps/color_maps.ts diff --git a/src/legacy/ui/public/vislib/components/color/heatmap_color.js b/src/legacy/ui/public/color_maps/heatmap_color.js similarity index 98% rename from src/legacy/ui/public/vislib/components/color/heatmap_color.js rename to src/legacy/ui/public/color_maps/heatmap_color.js index 5e788cd1f3345..06d754235f88b 100644 --- a/src/legacy/ui/public/vislib/components/color/heatmap_color.js +++ b/src/legacy/ui/public/color_maps/heatmap_color.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import { vislibColorMaps } from './colormaps'; +import { vislibColorMaps } from './color_maps'; function enforceBounds(x) { if (x < 0) { diff --git a/src/legacy/ui/public/color_maps/index.ts b/src/legacy/ui/public/color_maps/index.ts new file mode 100644 index 0000000000000..50dfe682f4418 --- /dev/null +++ b/src/legacy/ui/public/color_maps/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './color_maps'; +// @ts-ignore +export { getHeatmapColors } from './heatmap_color'; +// @ts-ignore +export * from './truncated_color_maps'; diff --git a/src/legacy/ui/public/vislib/components/color/truncated_colormaps.js b/src/legacy/ui/public/color_maps/truncated_color_maps.js similarity index 86% rename from src/legacy/ui/public/vislib/components/color/truncated_colormaps.js rename to src/legacy/ui/public/color_maps/truncated_color_maps.js index ccf005b3726a8..cb7772c875e48 100644 --- a/src/legacy/ui/public/vislib/components/color/truncated_colormaps.js +++ b/src/legacy/ui/public/color_maps/truncated_color_maps.js @@ -17,14 +17,14 @@ * under the License. */ -import { vislibColorMaps } from './colormaps'; +import { vislibColorMaps } from './color_maps'; export const truncatedColorMaps = {}; const colormaps = vislibColorMaps; for (const key in colormaps) { if (colormaps.hasOwnProperty(key)) { - //slice off lightest colors + // slice off lightest colors truncatedColorMaps[key] = { ...colormaps[key], value: colormaps[key].value.slice(Math.floor(colormaps[key].value.length / 4)), @@ -32,7 +32,7 @@ for (const key in colormaps) { } } -export const colorSchemas = Object.values(truncatedColorMaps).map(({ id, label }) => ({ +export const truncatedColorSchemas = Object.values(truncatedColorMaps).map(({ id, label }) => ({ value: id, text: label, })); diff --git a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js b/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js index 26a9c5b008f70..aef7bc3913a49 100644 --- a/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js +++ b/src/legacy/ui/public/vis/components/tooltip/_hierarchical_tooltip_formatter.js @@ -19,6 +19,9 @@ import _ from 'lodash'; import $ from 'jquery'; + +import chrome from 'ui/chrome'; + import { collectBranch } from './_collect_branch'; import numeral from 'numeral'; import template from './_hierarchical_tooltip.html'; @@ -68,6 +71,12 @@ export const getHierarchicalTooltipFormatter = () => { return _tooltipFormatter; }; +export const initializeHierarchicalTooltipFormatter = async () => { + const $injector = await chrome.dangerouslyGetActiveInjector(); + const Private = $injector.get('Private'); + _tooltipFormatter = Private(HierarchicalTooltipFormatterProvider); +}; + export const setHierarchicalTooltipFormatter = Private => { _tooltipFormatter = Private(HierarchicalTooltipFormatterProvider); }; diff --git a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js b/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js index fa0b030c736c1..88c9e3d67b4a9 100644 --- a/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js +++ b/src/legacy/ui/public/vis/components/tooltip/_pointseries_tooltip_formatter.js @@ -18,6 +18,9 @@ */ import $ from 'jquery'; + +import chrome from 'ui/chrome'; + import template from './_pointseries_tooltip.html'; export function PointSeriesTooltipFormatterProvider($compile, $rootScope) { @@ -75,6 +78,12 @@ export const getPointSeriesTooltipFormatter = () => { return _tooltipFormatter; }; +export const initializePointSeriesTooltipFormatter = async () => { + const $injector = await chrome.dangerouslyGetActiveInjector(); + const Private = $injector.get('Private'); + _tooltipFormatter = Private(PointSeriesTooltipFormatterProvider); +}; + export const setPointSeriesTooltipFormatter = Private => { _tooltipFormatter = Private(PointSeriesTooltipFormatterProvider); }; diff --git a/src/legacy/ui/public/vis/editors/default/agg_groups.ts b/src/legacy/ui/public/vis/editors/default/agg_groups.ts index f55e6ecd79155..e84306144fa63 100644 --- a/src/legacy/ui/public/vis/editors/default/agg_groups.ts +++ b/src/legacy/ui/public/vis/editors/default/agg_groups.ts @@ -18,11 +18,14 @@ */ import { i18n } from '@kbn/i18n'; +import { $Values } from '@kbn/utility-types'; -export enum AggGroupNames { - Buckets = 'buckets', - Metrics = 'metrics', -} +export const AggGroupNames = Object.freeze({ + Buckets: 'buckets' as 'buckets', + Metrics: 'metrics' as 'metrics', + None: 'none' as 'none', +}); +export type AggGroupNames = $Values; export const aggGroupNamesMap = () => ({ [AggGroupNames.Metrics]: i18n.translate('common.ui.vis.editors.aggGroups.metricsText', { diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx index 528914f4fd006..1c8690f6deb79 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx @@ -66,7 +66,7 @@ function DefaultEditorAggGroup({ setTouched, setValidity, }: DefaultEditorAggGroupProps) { - const groupNameLabel = aggGroupNamesMap()[groupName]; + const groupNameLabel = (aggGroupNamesMap() as any)[groupName]; // e.g. buckets can have no aggs const group: AggConfig[] = state.aggs.aggs.filter((agg: AggConfig) => agg.schema.group === groupName) || []; diff --git a/src/legacy/ui/public/vis/editors/default/schemas.js b/src/legacy/ui/public/vis/editors/default/schemas.ts similarity index 70% rename from src/legacy/ui/public/vis/editors/default/schemas.js rename to src/legacy/ui/public/vis/editors/default/schemas.ts index 69449dc8504a8..e86a73732c3f4 100644 --- a/src/legacy/ui/public/vis/editors/default/schemas.js +++ b/src/legacy/ui/public/vis/editors/default/schemas.ts @@ -18,13 +18,44 @@ */ import _ from 'lodash'; + +import { Optional } from '@kbn/utility-types'; + +import { AggParam } from '../../../agg_types'; import { IndexedArray } from '../../../indexed_array'; import { RowsOrColumnsControl } from './controls/rows_or_columns'; import { RadiusRatioOptionControl } from './controls/radius_ratio_option'; import { AggGroupNames } from './agg_groups'; +import { AggControlProps } from './controls/agg_control_props'; + +export interface Schema { + aggFilter: string | string[]; + editor: boolean | string; + group: AggGroupNames; + max: number; + min: number; + name: string; + params: AggParam[]; + title: string; + defaults: unknown; + hideCustomLabel?: boolean; + mustBeFirst?: boolean; + aggSettings?: any; + editorComponent?: React.ComponentType; +} class Schemas { - constructor(schemas) { + // @ts-ignore + all: IndexedArray; + + constructor( + schemas: Array< + Optional< + Schema, + 'min' | 'max' | 'group' | 'title' | 'aggFilter' | 'editor' | 'params' | 'defaults' + > + > + ) { _(schemas || []) .map(schema => { if (!schema.name) throw new Error('all schema must have a unique name'); @@ -35,7 +66,7 @@ class Schemas { name: 'row', default: true, }, - ]; + ] as AggParam[]; schema.editorComponent = RowsOrColumnsControl; } else if (schema.name === 'radius') { schema.editorComponent = RadiusRatioOptionControl; @@ -51,21 +82,23 @@ class Schemas { params: [], }); - return schema; + return schema as Schema; }) - .tap(schemas => { + .tap((fullSchemas: Schema[]) => { this.all = new IndexedArray({ index: ['name'], group: ['group'], immutable: true, - initialSet: schemas, + initialSet: fullSchemas, }); }) .groupBy('group') .forOwn((group, groupName) => { + // @ts-ignore this[groupName] = new IndexedArray({ index: ['name'], immutable: true, + // @ts-ignore initialSet: group, }); }) diff --git a/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss b/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss index 4d7c0e2bdcadb..62050ce4e99fd 100644 --- a/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss +++ b/src/legacy/ui/public/vis/vis_types/_vislib_vis_legend.scss @@ -1,4 +1,4 @@ -@import '../../vislib/variables'; +@import '../../../../core_plugins/vis_type_vislib/public/vislib/variables'; // NOTE: Some of the styles attempt to align with the TSVB legend diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/pie_utils.ts b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/pie_utils.ts new file mode 100644 index 0000000000000..d9eea83d40b48 --- /dev/null +++ b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/pie_utils.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; + +/** + * Returns an array of names ordered by appearance in the nested array + * of objects + * + * > Duplicated utilty method from vislib Data class to decouple `vislib_vis_legend` from `vislib` + * + * @see src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/data.js + * + * @returns {Array} Array of unique names (strings) + */ +export function getPieNames(data: any[]): string[] { + const names: string[] = []; + + _.forEach(data, function(obj) { + const columns = obj.raw ? obj.raw.columns : undefined; + _.forEach(getNames(obj, columns), function(name) { + names.push(name); + }); + }); + + return _.uniq(names, 'label'); +} + +/** + * Flattens hierarchical data into an array of objects with a name and index value. + * The indexed value determines the order of nesting in the data. + * Returns an array with names sorted by the index value. + * + * @param data {Object} Chart data object + * @param columns {Object} Contains formatter information + * @returns {Array} Array of names (strings) + */ +function getNames(data: any, columns: any): string[] { + const slices = data.slices; + + if (slices.children) { + const namedObj = returnNames(slices.children, 0, columns); + + return _(namedObj) + .sortBy(function(obj) { + return obj.index; + }) + .unique(function(d) { + return d.label; + }) + .value(); + } + + return []; +} + +/** + * Helper function for getNames + * Returns an array of objects with a name (key) value and an index value. + * The index value allows us to sort the names in the correct nested order. + * + * @param array {Array} Array of data objects + * @param index {Number} Number of times the object is nested + * @param columns {Object} Contains name formatter information + * @returns {Array} Array of labels (strings) + */ +function returnNames(array: any[], index: number, columns: any): any[] { + const names: any[] = []; + + _.forEach(array, function(obj) { + names.push({ + label: obj.name, + values: [obj.rawData], + index, + }); + + if (obj.children) { + const plusIndex = index + 1; + + _.forEach(returnNames(obj.children, plusIndex, columns), function(namedObj) { + names.push(namedObj); + }); + } + }); + + return names; +} diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx index f0100e369f050..d98590f9885b9 100644 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx +++ b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx @@ -23,12 +23,11 @@ import { compact, uniq, map } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eui'; -// @ts-ignore -import { Data } from '../../../vislib/lib/data'; // @ts-ignore import { createFiltersFromEvent } from '../../../../../core_plugins/visualizations/public'; import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; import { VisLegendItem } from './vislib_vis_legend_item'; +import { getPieNames } from './pie_utils'; import { getTableAggs } from '../../../visualize/loader/pipeline_helpers/utilities'; export interface VisLegendProps { @@ -128,7 +127,7 @@ export class VisLegend extends PureComponent { if (!data) return []; data = data.columns || data.rows || [data]; - if (type === 'pie') return Data.prototype.pieNames(data); + if (type === 'pie') return getPieNames(data); return this.getSeriesLabels(data); }; diff --git a/src/legacy/ui/public/vislib/vis.js b/src/legacy/ui/public/vislib/vis.js deleted file mode 100644 index 6ce58c1f5b23b..0000000000000 --- a/src/legacy/ui/public/vislib/vis.js +++ /dev/null @@ -1,190 +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 d3 from 'd3'; -import { EventEmitter } from 'events'; -import chrome from '../chrome'; -import { VislibError } from './errors'; -import { VisConfig } from './lib/vis_config'; -import { Handler } from './lib/handler'; -import { setHierarchicalTooltipFormatter } from '../vis/components/tooltip/_hierarchical_tooltip_formatter'; -import { setPointSeriesTooltipFormatter } from '../vis/components/tooltip/_pointseries_tooltip_formatter'; - -const config = chrome.getUiSettingsClient(); - -export function VislibVisProvider(Private) { - setHierarchicalTooltipFormatter(Private); - setPointSeriesTooltipFormatter(Private); - - /** - * Creates the visualizations. - * - * @class Vis - * @constructor - * @param $el {HTMLElement} jQuery selected HTML element - * @param config {Object} Parameters that define the chart type and chart options - */ - class Vis extends EventEmitter { - constructor($el, visConfigArgs) { - super(); - this.el = $el.get ? $el.get(0) : $el; - this.visConfigArgs = _.cloneDeep(visConfigArgs); - this.visConfigArgs.dimmingOpacity = config.get('visualization:dimmingOpacity'); - this.visConfigArgs.heatmapMaxBuckets = config.get('visualization:heatmap:maxBuckets'); - } - - hasLegend() { - return this.visConfigArgs.addLegend; - } - - initVisConfig(data, uiState) { - this.data = data; - - this.uiState = uiState; - - this.visConfig = new VisConfig(this.visConfigArgs, this.data, this.uiState, this.el); - } - - /** - * Renders the visualization - * - * @method render - * @param data {Object} Elasticsearch query results - */ - render(data, uiState) { - if (!data) { - throw new Error('No valid data!'); - } - - if (this.handler) { - this.data = null; - this._runOnHandler('destroy'); - } - - this.initVisConfig(data, uiState); - - this.handler = new Handler(this, this.visConfig); - this._runOnHandler('render'); - } - - getLegendLabels() { - return this.visConfig ? this.visConfig.get('legend.labels', null) : null; - } - - getLegendColors() { - return this.visConfig ? this.visConfig.get('legend.colors', null) : null; - } - - _runOnHandler(method) { - try { - this.handler[method](); - } catch (error) { - if (error instanceof VislibError) { - error.displayToScreen(this.handler); - } else { - throw error; - } - } - } - - /** - * Destroys the visualization - * Removes chart and all elements associated with it. - * Removes chart and all elements associated with it. - * Remove event listeners and pass destroy call down to owned objects. - * - * @method destroy - */ - destroy() { - const selection = d3.select(this.el).select('.visWrapper'); - - if (this.handler) this._runOnHandler('destroy'); - - selection.remove(); - } - - /** - * Sets attributes on the visualization - * - * @method set - * @param name {String} An attribute name - * @param val {*} Value to which the attribute name is set - */ - set(name, val) { - this.visConfigArgs[name] = val; - this.render(this.data, this.uiState); - } - - /** - * Gets attributes from the visualization - * - * @method get - * @param name {String} An attribute name - * @returns {*} The value of the attribute name - */ - get(name) { - return this.visConfig.get(name); - } - - /** - * Turns on event listeners. - * - * @param event {String} - * @param listener{Function} - * @returns {*} - */ - on(event, listener) { - const first = this.listenerCount(event) === 0; - const ret = EventEmitter.prototype.on.call(this, event, listener); - const added = this.listenerCount(event) > 0; - - // if this is the first listener added for the event - // enable the event in the handler - if (first && added && this.handler) this.handler.enable(event); - - return ret; - } - - /** - * Turns off event listeners. - * - * @param event {String} - * @param listener{Function} - * @returns {*} - */ - off(event, listener) { - const last = this.listenerCount(event) === 1; - const ret = EventEmitter.prototype.off.call(this, event, listener); - const removed = this.listenerCount(event) === 0; - - // Once all listeners are removed, disable the events in the handler - if (last && removed && this.handler) this.handler.disable(event); - return ret; - } - - removeAllListeners(event) { - const ret = EventEmitter.prototype.removeAllListeners.call(this, event); - this.handler.disable(event); - return ret; - } - } - - return Vis; -} diff --git a/src/plugins/bfetch/README.md b/src/plugins/bfetch/README.md index 9c18720e30d96..9ed90a4de306e 100644 --- a/src/plugins/bfetch/README.md +++ b/src/plugins/bfetch/README.md @@ -3,7 +3,54 @@ `bfetch` allows to batch HTTP requests and streams responses back. +# Example + +We will create a batch processing endpoint that receives a number then doubles it +and streams it back. We will also consider the number to be time in milliseconds +and before streaming the number back the server will wait for the specified number of +milliseconds. + +To do that, first create server-side batch processing route using [`addBatchProcessingRoute`](./docs/server/reference.md#addBatchProcessingRoute). + +```ts +plugins.bfetch.addBatchProcessingRoute<{ num: number }, { num: number }>( + '/my-plugin/double', + () => ({ + onBatchItem: async ({ num }) => { + // Validate inputs. + if (num < 0) throw new Error('Invalid number'); + // Wait number of specified milliseconds. + await new Promise(r => setTimeout(r, num)); + // Double the number and send it back. + return { num: 2 * num }; + }, + }) +); +``` + +Now on client-side create `double` function using [`batchedFunction`](./docs/browser/reference.md#batchedFunction). +The newly created `double` function can be called many times and it +will package individual calls into batches and send them to the server. + +```ts +const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ + url: '/my-plugin/double', +}); +``` + +Note: the created `double` must accept a single object argument (`{ num: number }` in this case) +and it will return a promise that resolves into an object, too (also `{ num: number }` in this case). + +Use the `double` function. + +```ts +double({ num: 1 }).then(console.log, console.error); // { num: 2 } +double({ num: 2 }).then(console.log, console.error); // { num: 4 } +double({ num: 3 }).then(console.log, console.error); // { num: 6 } +``` + + ## Reference - [Browser](./docs/browser/reference.md) -- Server +- [Server](./docs/server/reference.md) diff --git a/src/plugins/bfetch/common/batch.ts b/src/plugins/bfetch/common/batch.ts new file mode 100644 index 0000000000000..6fd2c7e35ed91 --- /dev/null +++ b/src/plugins/bfetch/common/batch.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. + */ + +export interface ErrorLike { + message: string; +} + +export interface BatchRequestData { + batch: Item[]; +} + +export interface BatchResponseItem { + id: number; + result?: Result; + error?: Error; +} diff --git a/src/plugins/bfetch/common/buffer/create_batched_function.ts b/src/plugins/bfetch/common/buffer/create_batched_function.ts new file mode 100644 index 0000000000000..24f28659863a7 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/create_batched_function.ts @@ -0,0 +1,49 @@ +/* + * 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 { ItemBufferParams } from './item_buffer'; +import { TimedItemBufferParams, TimedItemBuffer } from './timed_item_buffer'; + +type Fn = (...args: any) => any; + +export interface BatchedFunctionParams { + onCall: (...args: Parameters) => [ReturnType, BatchEntry]; + onBatch: (items: BatchEntry[]) => void; + flushOnMaxItems?: ItemBufferParams['flushOnMaxItems']; + maxItemAge?: TimedItemBufferParams['maxItemAge']; +} + +export const createBatchedFunction = ( + params: BatchedFunctionParams +): [Func, TimedItemBuffer] => { + const { onCall, onBatch, maxItemAge = 10, flushOnMaxItems = 25 } = params; + const buffer = new TimedItemBuffer({ + onFlush: onBatch, + maxItemAge, + flushOnMaxItems, + }); + + const fn: Func = ((...args) => { + const [result, batchEntry] = onCall(...args); + buffer.write(batchEntry); + return result; + }) as Func; + + return [fn, buffer]; +}; diff --git a/src/plugins/bfetch/common/buffer/index.ts b/src/plugins/bfetch/common/buffer/index.ts new file mode 100644 index 0000000000000..33bc52733289b --- /dev/null +++ b/src/plugins/bfetch/common/buffer/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './item_buffer'; +export * from './timed_item_buffer'; +export * from './create_batched_function'; diff --git a/src/plugins/bfetch/common/buffer/item_buffer.ts b/src/plugins/bfetch/common/buffer/item_buffer.ts new file mode 100644 index 0000000000000..663aa5d7b0b7f --- /dev/null +++ b/src/plugins/bfetch/common/buffer/item_buffer.ts @@ -0,0 +1,81 @@ +/* + * 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 interface ItemBufferParams { + /** + * Flushes buffer automatically if number of items in the buffer reaches + * this number. Omit it or set to `Infinity` to never flush on max buffer + * size automatically. + */ + flushOnMaxItems?: number; + + /** + * Callback that is called every time buffer is flushed. It receives a single + * argument which is a list of all buffered items. If `.flush()` is called + * when buffer is empty, `.onflush` is called with empty array. + */ + onFlush: (items: Item[]) => void; +} + +/** + * A simple buffer that collects items. Can be cleared or flushed; and can + * automatically flush when specified number of items is reached. + */ +export class ItemBuffer { + private list: Item[] = []; + + constructor(public readonly params: ItemBufferParams) {} + + /** + * Get current buffer size. + */ + public get length(): number { + return this.list.length; + } + + /** + * Add item to the buffer. + */ + public write(item: Item) { + this.list.push(item); + + const { flushOnMaxItems } = this.params; + if (flushOnMaxItems) { + if (this.list.length >= flushOnMaxItems) { + this.flush(); + } + } + } + + /** + * Remove all items from the buffer. + */ + public clear() { + this.list = []; + } + + /** + * Call `.onflush` method and clear buffer. + */ + public flush() { + let list; + [list, this.list] = [this.list, []]; + this.params.onFlush(list); + } +} diff --git a/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts b/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts new file mode 100644 index 0000000000000..5b145a2523070 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts @@ -0,0 +1,75 @@ +/* + * 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 { createBatchedFunction } from '../create_batched_function'; + +describe('createBatchedFunction', () => { + test('calls onCall every time fn is called, calls onBatch once flushOnMaxItems reached', async () => { + const onBatch = jest.fn(); + const onCall = jest.fn(() => [1, 2] as any); + const [fn] = createBatchedFunction({ + onBatch, + onCall, + flushOnMaxItems: 2, + maxItemAge: 10, + }); + + expect(onCall).toHaveBeenCalledTimes(0); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(123); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onCall).toHaveBeenCalledWith(123); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(456); + + expect(onCall).toHaveBeenCalledTimes(2); + expect(onCall).toHaveBeenCalledWith(456); + expect(onBatch).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledWith([2, 2]); + }); + + test('calls onBatch once timeout is reached', async () => { + const onBatch = jest.fn(); + const onCall = jest.fn(() => [4, 3] as any); + const [fn] = createBatchedFunction({ + onBatch, + onCall, + flushOnMaxItems: 2, + maxItemAge: 10, + }); + + expect(onCall).toHaveBeenCalledTimes(0); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(123); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onCall).toHaveBeenCalledWith(123); + expect(onBatch).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 15)); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledWith([3]); + }); +}); diff --git a/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts b/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts new file mode 100644 index 0000000000000..a921fa8e589a3 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBuffer } from '../item_buffer'; +import { runItemBufferTests } from './run_item_buffer_tests'; + +runItemBufferTests(ItemBuffer); diff --git a/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts b/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts new file mode 100644 index 0000000000000..b3ba9375448dc --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts @@ -0,0 +1,239 @@ +/* + * 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 { ItemBuffer, ItemBufferParams } from '../item_buffer'; + +export const runItemBufferTests = ( + Buffer: new >(params: Params) => ItemBuffer +) => { + describe('ItemBuffer', () => { + test('can create with or without optional "flushOnMaxItems" param', () => { + new Buffer({ + onFlush: () => {}, + }); + + new Buffer({ + onFlush: () => {}, + flushOnMaxItems: 123, + }); + }); + + test('can add items to the buffer', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + }); + + test('returns number of items in the buffer', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.write('b'); + expect(buf.length).toBe(2); + buf.write('c'); + expect(buf.length).toBe(3); + }); + + test('returns correct number of items after .clear() was called', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.clear(); + buf.write('b'); + expect(buf.length).toBe(1); + buf.write('c'); + expect(buf.length).toBe(2); + }); + + test('returns correct number of items after .flush() was called', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.flush(); + buf.write('b'); + expect(buf.length).toBe(1); + buf.write('c'); + expect(buf.length).toBe(2); + }); + + test('can flush buffer and receive items in chronological order', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual(['a', 'b', 'c']); + }); + + test('clears buffer after flush', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual(['a', 'b', 'c']); + + buf.write('d'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(2); + expect(onFlush.mock.calls[1][0]).toEqual(['d']); + }); + + test('can call .flush() any time as many times as needed', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.flush(); + buf.write(123); + buf.flush(); + buf.flush(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(4); + expect(onFlush.mock.calls[0][0]).toEqual([]); + expect(onFlush.mock.calls[1][0]).toEqual([123]); + expect(onFlush.mock.calls[2][0]).toEqual([]); + expect(onFlush.mock.calls[3][0]).toEqual([]); + }); + + test('calling .clear() before .flush() cases to return empty list', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write(1); + buf.write(2); + buf.clear(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual([]); + }); + + test('can call .clear() any time as many times as needed', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.clear(); + buf.flush(); + buf.write(123); + buf.clear(); + buf.flush(); + buf.clear(); + buf.clear(); + buf.flush(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(4); + expect(onFlush.mock.calls[0][0]).toEqual([]); + expect(onFlush.mock.calls[1][0]).toEqual([]); + expect(onFlush.mock.calls[2][0]).toEqual([]); + expect(onFlush.mock.calls[3][0]).toEqual([]); + }); + + describe('when `flushOnMaxItems` is set', () => { + test('does not flush automatically before `flushOnMaxItems` is reached', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + + expect(onFlush).toHaveBeenCalledTimes(0); + }); + + test('automatically flushes buffer when `flushOnMaxItems` is reached', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + buf.write(2); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual([1, 2]); + }); + + test('flushes again when `flushOnMaxItems` limit is reached the second time', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + buf.write(2); + buf.write(3); + buf.write(4); + buf.write(5); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(3); + expect(onFlush.mock.calls[0][0]).toEqual([1, 2]); + expect(onFlush.mock.calls[1][0]).toEqual([3, 4]); + expect(onFlush.mock.calls[2][0]).toEqual([5]); + }); + }); + }); +}; 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 new file mode 100644 index 0000000000000..c1c6a8f187a44 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TimedItemBuffer } from '../timed_item_buffer'; +import { runItemBufferTests } from './run_item_buffer_tests'; + +describe('TimedItemBuffer', () => { + runItemBufferTests(TimedItemBuffer); + + test('does not do unnecessary flushes', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 3, + }); + + expect(onFlush).toHaveBeenCalledTimes(0); + buf.write(0); + expect(onFlush).toHaveBeenCalledTimes(0); + buf.flush(); + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('does not do extra flush after timeout if buffer was flushed during timeout wait', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 10, + }); + + buf.write(0); + await new Promise(r => setTimeout(r, 3)); + buf.flush(); + await new Promise(r => setTimeout(r, 11)); + + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('flushes buffer automatically after timeout reached', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 2, + }); + + buf.write(1); + buf.write(2); + expect(onFlush).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 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 () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + flushOnMaxItems: 2, + maxItemAge: 2, + }); + + buf.write(1); + buf.write(2); + + expect(onFlush).toHaveBeenCalledTimes(1); + await new Promise(r => setTimeout(r, 3)); + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('does not automatically flush if `.clear()` was called', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + flushOnMaxItems: 25, + maxItemAge: 5, + }); + + buf.write(1); + buf.write(2); + await new Promise(r => setImmediate(r)); + buf.clear(); + + expect(onFlush).toHaveBeenCalledTimes(0); + await new Promise(r => setTimeout(r, 6)); + expect(onFlush).toHaveBeenCalledTimes(0); + }); +}); diff --git a/src/plugins/bfetch/common/buffer/timed_item_buffer.ts b/src/plugins/bfetch/common/buffer/timed_item_buffer.ts new file mode 100644 index 0000000000000..8d0f9e4856f8c --- /dev/null +++ b/src/plugins/bfetch/common/buffer/timed_item_buffer.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBuffer, ItemBufferParams } from './item_buffer'; + +export interface TimedItemBufferParams extends ItemBufferParams { + /** + * Flushes buffer when oldest item reaches age specified by this parameter, + * in milliseconds. + */ + maxItemAge?: number; +} + +export class TimedItemBuffer extends ItemBuffer { + private timer: any; + + constructor(public readonly params: TimedItemBufferParams) { + super(params); + } + + public write(item: Item) { + super.write(item); + + if (this.params.maxItemAge && this.length === 1) { + this.timer = setTimeout(this.onTimeout, this.params.maxItemAge); + } + } + + public clear() { + clearTimeout(this.timer); + super.clear(); + } + + public flush() { + clearTimeout(this.timer); + super.flush(); + } + + private onTimeout = () => { + this.flush(); + }; +} diff --git a/src/plugins/bfetch/common/index.ts b/src/plugins/bfetch/common/index.ts index afa73ade80084..085b8e7c58a67 100644 --- a/src/plugins/bfetch/common/index.ts +++ b/src/plugins/bfetch/common/index.ts @@ -19,3 +19,5 @@ export * from './util'; export * from './streaming'; +export * from './buffer'; +export * from './batch'; diff --git a/src/plugins/bfetch/common/streaming/types.ts b/src/plugins/bfetch/common/streaming/types.ts index 1ee92edbc89ff..197ee9a52ff01 100644 --- a/src/plugins/bfetch/common/streaming/types.ts +++ b/src/plugins/bfetch/common/streaming/types.ts @@ -20,5 +20,5 @@ import { Observable } from 'rxjs'; export interface StreamingResponseHandler { - onRequest(payload: Payload): Observable; + getResponseStream(payload: Payload): Observable; } diff --git a/src/plugins/bfetch/common/util/index.ts b/src/plugins/bfetch/common/util/index.ts index 02843af9b4350..b5d1fcabbcd85 100644 --- a/src/plugins/bfetch/common/util/index.ts +++ b/src/plugins/bfetch/common/util/index.ts @@ -17,4 +17,5 @@ * under the License. */ +export * from './normalize_error'; export * from './remove_leading_slash'; diff --git a/src/plugins/bfetch/common/util/normalize_error.ts b/src/plugins/bfetch/common/util/normalize_error.ts new file mode 100644 index 0000000000000..c2ee3d83f5eb5 --- /dev/null +++ b/src/plugins/bfetch/common/util/normalize_error.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 { ErrorLike } from '../batch'; + +export const normalizeError = (err: any): E => { + if (!err) { + return { + message: 'Unknown error.', + } as E; + } + if (err instanceof Error) { + return { message: err.message } as E; + } + if (typeof err === 'object') { + return { + ...err, + message: err.message || 'Unknown error.', + } as E; + } + return { + message: String(err), + } as E; +}; diff --git a/src/plugins/bfetch/docs/browser/reference.md b/src/plugins/bfetch/docs/browser/reference.md index 47a67c08a4c1f..444b1aa08a98e 100644 --- a/src/plugins/bfetch/docs/browser/reference.md +++ b/src/plugins/bfetch/docs/browser/reference.md @@ -1,8 +1,37 @@ # `bfetch` browser reference +- [`batchedFunction`](#batchedFunction) - [`fetchStreaming`](#fetchStreaming) +## `batchedFunction` + +Creates a function that will buffer its calls (until timeout—10ms default— or capacity reached—25 default) +and send all calls in one batch to the specified endpoint. The endpoint is expected +to stream results back in ND-JSON format using `Transfer-Encoding: chunked`, which is +implemented by `addBatchProcessingRoute` server-side method of `bfetch` plugin. + +The created function is expected to be called with a single object argument and will +return a promise that will resolve to an object. + +```ts +const fn = bfetch.batchedFunction({ url: '/my-plugin/something' }); + +const result = await fn({ foo: 'bar' }); +``` + +Options: + +- `url` — URL endpoint that will receive a batch of requests. This endpoint is expected + to receive batch as a serialized JSON array. It should stream responses back + in ND-JSON format using `Transfer-Encoding: chunked` HTTP/1 streaming. +- `fetchStreaming` — The instance of `fetchStreaming` function that will perform ND-JSON handling. + There should be a version of this function available in setup contract of `bfetch` plugin. +- `flushOnMaxItems` — The maximum size of function call buffer before sending the batch request. +- `maxItemAge` — The maximum timeout in milliseconds of the oldest item in the batch + before sending the batch request. + + ## `fetchStreaming` Executes an HTTP request and expects that server streams back results using @@ -12,4 +41,4 @@ HTTP/1 `Transfer-Encoding: chunked`. const { stream } = bfetch.fetchStreaming({ url: 'http://elastic.co' }); stream.subscribe(value => {}); -``` \ No newline at end of file +``` diff --git a/src/plugins/bfetch/docs/server/reference.md b/src/plugins/bfetch/docs/server/reference.md new file mode 100644 index 0000000000000..424532a50b817 --- /dev/null +++ b/src/plugins/bfetch/docs/server/reference.md @@ -0,0 +1,54 @@ +# `bfetch` server reference + +- [`addBatchProcessingRoute`](#addBatchProcessingRoute) +- [`addStreamingResponseRoute`](#addStreamingResponseRoute) + + +## `addBatchProcessingRoute` + +Sets up a server endpoint that expects to work with [`batchedFunction`](../browser/reference.md#batchedFunction). +The endpoint receives a batch of requests, processes each request and streams results +back immediately as they become available. You only need to implement the +processing of each request (`onBatchItem` function), everything else is handled. + +`onBatchItem` function is called for each individual request in the batch. +`onBatchItem` function receives a single object argument which is the payload +of one request; and it must return a promise that resolves to an object, too. +`onBatchItem` function is allowed to throw, in that case the error will be forwarded +to the browser only to the individual request, the rest of the batch will still continue +executing. + +```ts +plugins.bfetch.addBatchProcessingRoute( + '/my-plugin/double', + request => ({ + onBatchItem: async (payload) => { + // ... + return {}; + }, + }) +); +``` + +`request` is the `KibanaRequest` object. `addBatchProcessingRoute` together with `batchedFunction` +ensure that errors are handled and that all items in the batch get executed. + + +## `addStreamingResponseRoute` + +`addStreamingResponseRoute` is a lower-level interface that receives and `payload` +message returns and observable which results are streamed back as ND-JSON messages +until the observable completes. `addStreamingResponseRoute` does not know about the +type of the messages, it does not handle errors, and it does not have a concept of +batch size—observable can stream any number of messages until it completes. + +```ts +plugins.bfetch.addStreamingResponseRoute('/my-plugin/foo', request => ({ + getResponseStream: (payload) => { + const subject = new Subject(); + setTimeout(() => { subject.next('123'); }, 100); + setTimeout(() => { subject.complete(); }, 200); + return subject; + }, +})); +``` diff --git a/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts b/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts new file mode 100644 index 0000000000000..064b791327e69 --- /dev/null +++ b/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts @@ -0,0 +1,521 @@ +/* + * 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 { createStreamingBatchedFunction } from './create_streaming_batched_function'; +import { fetchStreaming as fetchStreamingReal } from '../streaming/fetch_streaming'; +import { defer, of } from '../../../kibana_utils/public'; +import { Subject } from 'rxjs'; + +const getPromiseState = (promise: Promise): Promise<'resolved' | 'rejected' | 'pending'> => + Promise.race<'resolved' | 'rejected' | 'pending'>([ + new Promise(resolve => + promise.then( + () => resolve('resolved'), + () => resolve('rejected') + ) + ), + new Promise<'pending'>(resolve => resolve()).then(() => 'pending'), + ]); + +const isPending = (promise: Promise): Promise => + getPromiseState(promise).then(state => state === 'pending'); + +const setup = () => { + const xhr = ({} as unknown) as XMLHttpRequest; + const { promise, resolve, reject } = defer(); + const stream = new Subject(); + + const fetchStreaming = (jest.fn(() => ({ + xhr, + promise, + stream, + })) as unknown) as jest.SpyInstance & typeof fetchStreamingReal; + + return { + fetchStreaming, + xhr, + promise, + resolve, + reject, + stream, + }; +}; + +describe('createStreamingBatchedFunction()', () => { + test('returns a function', () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + }); + expect(typeof fn).toBe('function'); + }); + + test('returned function is async', () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + }); + const res = fn({}); + expect(typeof res.then).toBe('function'); + }); + + describe('when timeout is reached', () => { + test('dispatches batch', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ foo: 'bar' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ baz: 'quix' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + }); + + test('does nothing is buffer is empty', async () => { + const { fetchStreaming } = setup(); + createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + }); + + test('sends POST request to correct endpoint', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ foo: 'bar' }); + await new Promise(r => setTimeout(r, 6)); + + expect(fetchStreaming.mock.calls[0][0]).toMatchObject({ + url: '/test', + method: 'POST', + }); + }); + + test('collects calls into an array batch ordered by in same order as calls', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ foo: 'bar' }); + fn({ baz: 'quix' }); + + await new Promise(r => setTimeout(r, 6)); + const { body } = fetchStreaming.mock.calls[0][0]; + expect(JSON.parse(body)).toEqual({ + batch: [{ foo: 'bar' }, { baz: 'quix' }], + }); + }); + }); + + describe('when buffer becomes full', () => { + test('dispatches batch request', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ foo: 'bar' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ baz: 'quix' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ full: 'yep' }); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + }); + + test('sends POST request to correct endpoint with items in array batched sorted in call order', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ a: '1' }); + fn({ b: '2' }); + fn({ c: '3' }); + + expect(fetchStreaming.mock.calls[0][0]).toMatchObject({ + url: '/test', + method: 'POST', + }); + const { body } = fetchStreaming.mock.calls[0][0]; + expect(JSON.parse(body)).toEqual({ + batch: [{ a: '1' }, { b: '2' }, { c: '3' }], + }); + }); + + test('dispatches batch on full buffer and also on timeout', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ a: '1' }); + fn({ b: '2' }); + fn({ c: '3' }); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + fn({ d: '4' }); + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(2); + }); + }); + + describe('when receiving results', () => { + test('does not resolve call promises until request finishes', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(true); + }); + + test('resolves only promise of result that was streamed back', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + const promise3 = fn({ c: '3' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(true); + expect(await isPending(promise3)).toBe(true); + + stream.next( + JSON.stringify({ + id: 1, + result: { foo: 'bar' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(true); + + stream.next( + JSON.stringify({ + id: 0, + result: { foo: 'bar 2' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(false); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(true); + }); + + test('resolves each promise with correct data', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + const promise3 = fn({ c: '3' }); + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { foo: 'bar' }, + }) + '\n' + ); + stream.next( + JSON.stringify({ + id: 2, + result: { foo: 'bar 2' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(false); + expect(await promise2).toEqual({ foo: 'bar' }); + expect(await promise3).toEqual({ foo: 'bar 2' }); + }); + + test('rejects promise on error response', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise = fn({ a: '1' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise)).toBe(true); + + stream.next( + JSON.stringify({ + id: 0, + error: { message: 'oops' }, + }) + '\n' + ); + + expect(await isPending(promise)).toBe(false); + const [, error] = await of(promise); + expect(error).toEqual({ + message: 'oops', + }); + }); + + test('resolves successful requests even after rejected ones', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + const promise3 = of(fn({ a: '3' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 2, + result: { b: '3' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + stream.next( + JSON.stringify({ + id: 1, + error: { b: '2' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + stream.next( + JSON.stringify({ + id: 0, + result: { b: '1' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + const [result1] = await promise1; + const [, error2] = await promise2; + const [result3] = await promise3; + + expect(result1).toEqual({ b: '1' }); + expect(error2).toEqual({ b: '2' }); + expect(result3).toEqual({ b: '3' }); + }); + + describe('when stream closes prematurely', () => { + test('rejects pending promises with CONNECTION error code', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.complete(); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [, error2] = await promise2; + expect(error1).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + expect(error2).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + }); + + test('rejects with CONNECTION error only pending promises', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { b: '1' }, + }) + '\n' + ); + stream.complete(); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [result1] = await promise2; + expect(error1).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + expect(result1).toMatchObject({ + b: '1', + }); + }); + }); + + describe('when stream errors', () => { + test('rejects pending promises with STREAM error code', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.error({ + message: 'something went wrong', + }); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [, error2] = await promise2; + expect(error1).toMatchObject({ + message: 'something went wrong', + code: 'STREAM', + }); + expect(error2).toMatchObject({ + message: 'something went wrong', + code: 'STREAM', + }); + }); + + test('rejects with STREAM error only pending promises', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { b: '1' }, + }) + '\n' + ); + stream.error('oops'); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [result1] = await promise2; + expect(error1).toMatchObject({ + message: 'oops', + code: 'STREAM', + }); + expect(result1).toMatchObject({ + b: '1', + }); + }); + }); + }); +}); diff --git a/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts b/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts new file mode 100644 index 0000000000000..07d5724a2520d --- /dev/null +++ b/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts @@ -0,0 +1,140 @@ +/* + * 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 { defer, Defer } from '../../../kibana_utils/public'; +import { + ItemBufferParams, + TimedItemBufferParams, + createBatchedFunction, + BatchResponseItem, + ErrorLike, +} from '../../common'; +import { fetchStreaming, split } from '../streaming'; +import { normalizeError } from '../../common'; + +export interface BatchItem { + payload: Payload; + future: Defer; +} + +export type BatchedFunc = (payload: Payload) => Promise; + +export interface BatchedFunctionProtocolError extends ErrorLike { + code: string; +} + +export interface StreamingBatchedFunctionParams { + /** + * URL endpoint that will receive a batch of requests. This endpoint is expected + * to receive batch as a serialized JSON array. It should stream responses back + * in ND-JSON format using `Transfer-Encoding: chunked` HTTP/1 streaming. + */ + url: string; + + /** + * The instance of `fetchStreaming` function that will perform ND-JSON handling. + * There should be a version of this function available in setup contract of `bfetch` + * plugin. + */ + fetchStreaming?: typeof fetchStreaming; + + /** + * The maximum size of function call buffer before sending the batch request. + */ + flushOnMaxItems?: ItemBufferParams['flushOnMaxItems']; + + /** + * The maximum timeout in milliseconds of the oldest item in the batch + * before sending the batch request. + */ + maxItemAge?: TimedItemBufferParams['maxItemAge']; +} + +/** + * Returns a function that does not execute immediately but buffers the call internally until + * `params.flushOnMaxItems` is reached or after `params.maxItemAge` timeout in milliseconds is reached. Once + * one of those thresholds is reached all buffered calls are sent in one batch to the + * server using `params.fetchStreaming` in a POST request. Responses are streamed back + * and each batch item is resolved once corresponding response is received. + */ +export const createStreamingBatchedFunction = ( + params: StreamingBatchedFunctionParams +): BatchedFunc => { + const { + url, + fetchStreaming: fetchStreamingInjected = fetchStreaming, + flushOnMaxItems = 25, + maxItemAge = 10, + } = params; + const [fn] = createBatchedFunction, BatchItem>({ + onCall: (payload: Payload) => { + const future = defer(); + const entry: BatchItem = { + payload, + future, + }; + return [future.promise, entry]; + }, + onBatch: async items => { + try { + let responsesReceived = 0; + const batch = items.map(({ payload }) => payload); + const { stream } = fetchStreamingInjected({ + url, + body: JSON.stringify({ batch }), + method: 'POST', + }); + stream.pipe(split('\n')).subscribe({ + next: (json: string) => { + const response = JSON.parse(json) as BatchResponseItem; + if (response.error) { + responsesReceived++; + items[response.id].future.reject(response.error); + } else if (response.result) { + responsesReceived++; + items[response.id].future.resolve(response.result); + } + }, + error: error => { + const normalizedError = normalizeError(error); + normalizedError.code = 'STREAM'; + for (const { future } of items) future.reject(normalizedError); + }, + complete: () => { + const streamTerminatedPrematurely = responsesReceived !== items.length; + if (streamTerminatedPrematurely) { + const error: BatchedFunctionProtocolError = { + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }; + for (const { future } of items) future.reject(error); + } + }, + }); + await stream.toPromise(); + } catch (error) { + for (const item of items) item.future.reject(error); + } + }, + flushOnMaxItems, + maxItemAge, + }); + + return fn; +}; diff --git a/src/plugins/bfetch/public/index.ts b/src/plugins/bfetch/public/index.ts index a57dd77fe7e67..8707e5a438159 100644 --- a/src/plugins/bfetch/public/index.ts +++ b/src/plugins/bfetch/public/index.ts @@ -20,7 +20,8 @@ import { PluginInitializerContext } from '../../../core/public'; import { BfetchPublicPlugin } from './plugin'; -export { BfetchPublicSetup, BfetchPublicStart, BfetchPublicApi } from './plugin'; +export { BfetchPublicSetup, BfetchPublicStart, BfetchPublicContract } from './plugin'; +export { split } from './streaming'; export function plugin(initializerContext: PluginInitializerContext) { return new BfetchPublicPlugin(initializerContext); diff --git a/src/plugins/bfetch/public/mocks.ts b/src/plugins/bfetch/public/mocks.ts index e8caf5c9cb739..f457b9ae5d671 100644 --- a/src/plugins/bfetch/public/mocks.ts +++ b/src/plugins/bfetch/public/mocks.ts @@ -27,6 +27,7 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { fetchStreaming: jest.fn(), + batchedFunction: jest.fn(), }; return setupContract; }; @@ -34,6 +35,7 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { fetchStreaming: jest.fn(), + batchedFunction: jest.fn(), }; return startContract; @@ -56,7 +58,7 @@ const createPlugin = async () => { }; }; -export const uiActionsPluginMock = { +export const bfetchPluginMock = { createSetupContract, createStartContract, createPlugin, diff --git a/src/plugins/bfetch/public/plugin.ts b/src/plugins/bfetch/public/plugin.ts index db18a15afa1e7..783c448c567e5 100644 --- a/src/plugins/bfetch/public/plugin.ts +++ b/src/plugins/bfetch/public/plugin.ts @@ -20,6 +20,11 @@ import { CoreStart, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/public'; import { fetchStreaming as fetchStreamingStatic, FetchStreamingParams } from './streaming'; import { removeLeadingSlash } from '../common'; +import { + createStreamingBatchedFunction, + BatchedFunc, + StreamingBatchedFunctionParams, +} from './batching/create_streaming_batched_function'; // eslint-disable-next-line export interface BfetchPublicSetupDependencies {} @@ -27,12 +32,15 @@ export interface BfetchPublicSetupDependencies {} // eslint-disable-next-line export interface BfetchPublicStartDependencies {} -export interface BfetchPublicApi { +export interface BfetchPublicContract { fetchStreaming: (params: FetchStreamingParams) => ReturnType; + batchedFunction: ( + params: StreamingBatchedFunctionParams + ) => BatchedFunc; } -export type BfetchPublicSetup = BfetchPublicApi; -export type BfetchPublicStart = BfetchPublicApi; +export type BfetchPublicSetup = BfetchPublicContract; +export type BfetchPublicStart = BfetchPublicContract; export class BfetchPublicPlugin implements @@ -42,7 +50,7 @@ export class BfetchPublicPlugin BfetchPublicSetupDependencies, BfetchPublicStartDependencies > { - private api!: BfetchPublicApi; + private contract!: BfetchPublicContract; constructor(private readonly initializerContext: PluginInitializerContext) {} @@ -51,16 +59,18 @@ export class BfetchPublicPlugin const basePath = core.http.basePath.get(); const fetchStreaming = this.fetchStreaming(version, basePath); + const batchedFunction = this.batchedFunction(fetchStreaming); - this.api = { + this.contract = { fetchStreaming, + batchedFunction, }; - return this.api; + return this.contract; } public start(core: CoreStart, plugins: BfetchPublicStartDependencies): BfetchPublicStart { - return this.api; + return this.contract; } public stop() {} @@ -78,4 +88,12 @@ export class BfetchPublicPlugin ...(params.headers || {}), }, }); + + private batchedFunction = ( + fetchStreaming: BfetchPublicContract['fetchStreaming'] + ): BfetchPublicContract['batchedFunction'] => params => + createStreamingBatchedFunction({ + ...params, + fetchStreaming: params.fetchStreaming || fetchStreaming, + }); } diff --git a/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts b/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts index e59af71cb76bc..7845616026ea1 100644 --- a/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts +++ b/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts @@ -36,14 +36,6 @@ test('returns XHR request', () => { expect(typeof xhr.readyState).toBe('number'); }); -test('returns promise', () => { - setup(); - const { promise } = fetchStreaming({ - url: 'http://example.com', - }); - expect(typeof promise.then).toBe('function'); -}); - test('returns stream', () => { setup(); const { stream } = fetchStreaming({ @@ -54,12 +46,12 @@ test('returns stream', () => { test('promise resolves when request completes', async () => { const env = setup(); - const { promise } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); let resolved = false; - promise.then(() => (resolved = true)); + stream.toPromise().then(() => (resolved = true)); await tick(); expect(resolved).toBe(false); @@ -142,12 +134,12 @@ test('completes stream observable when request finishes', async () => { test('promise throws when request errors', async () => { const env = setup(); - const { promise } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); const spy = jest.fn(); - promise.catch(spy); + stream.toPromise().catch(spy); await tick(); expect(spy).toHaveBeenCalledTimes(0); @@ -168,12 +160,11 @@ test('promise throws when request errors', async () => { test('stream observable errors when request errors', async () => { const env = setup(); - const { promise, stream } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); const spy = jest.fn(); - promise.catch(() => {}); stream.subscribe({ error: spy, }); diff --git a/src/plugins/bfetch/public/streaming/fetch_streaming.ts b/src/plugins/bfetch/public/streaming/fetch_streaming.ts index 44a3693e7010b..899e8a1824a41 100644 --- a/src/plugins/bfetch/public/streaming/fetch_streaming.ts +++ b/src/plugins/bfetch/public/streaming/fetch_streaming.ts @@ -17,7 +17,6 @@ * under the License. */ -import { defer } from '../../../kibana_utils/common'; import { fromStreamingXhr } from './from_streaming_xhr'; export interface FetchStreamingParams { @@ -38,7 +37,6 @@ export function fetchStreaming({ body = '', }: FetchStreamingParams) { const xhr = new window.XMLHttpRequest(); - const { promise, resolve, reject } = defer(); // Begin the request xhr.open(method, url); @@ -49,17 +47,11 @@ export function fetchStreaming({ const stream = fromStreamingXhr(xhr); - stream.subscribe({ - complete: () => resolve(), - error: error => reject(error), - }); - // Send the payload to the server xhr.send(body); return { xhr, - promise, stream, }; } diff --git a/src/plugins/bfetch/server/index.ts b/src/plugins/bfetch/server/index.ts index f1a3f7fd44cf6..06b7c793c537e 100644 --- a/src/plugins/bfetch/server/index.ts +++ b/src/plugins/bfetch/server/index.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from '../../../core/server'; import { BfetchServerPlugin } from './plugin'; -export { BfetchServerSetup, BfetchServerStart } from './plugin'; +export { BfetchServerSetup, BfetchServerStart, BatchProcessingRouteParams } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new BfetchServerPlugin(initializerContext); diff --git a/src/plugins/bfetch/server/mocks.ts b/src/plugins/bfetch/server/mocks.ts index 8ec68650a60dc..e0a76ba8da325 100644 --- a/src/plugins/bfetch/server/mocks.ts +++ b/src/plugins/bfetch/server/mocks.ts @@ -26,6 +26,7 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { + addBatchProcessingRoute: jest.fn(), addStreamingResponseRoute: jest.fn(), }; return setupContract; @@ -54,7 +55,7 @@ const createPlugin = async () => { }; }; -export const uiActionsPluginMock = { +export const bfetchPluginMock = { createSetupContract, createStartContract, createPlugin, diff --git a/src/plugins/bfetch/server/plugin.ts b/src/plugins/bfetch/server/plugin.ts index 75baeafc17669..fd1fe009e93ae 100644 --- a/src/plugins/bfetch/server/plugin.ts +++ b/src/plugins/bfetch/server/plugin.ts @@ -17,9 +17,24 @@ * under the License. */ -import { CoreStart, PluginInitializerContext, CoreSetup, Plugin, Logger } from 'src/core/server'; +import { + CoreStart, + PluginInitializerContext, + CoreSetup, + Plugin, + Logger, + KibanaRequest, +} from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { StreamingResponseHandler, removeLeadingSlash } from '../common'; +import { Subject } from 'rxjs'; +import { + StreamingResponseHandler, + BatchRequestData, + BatchResponseItem, + ErrorLike, + removeLeadingSlash, + normalizeError, +} from '../common'; import { createNDJSONStream } from './streaming'; // eslint-disable-next-line @@ -28,8 +43,19 @@ export interface BfetchServerSetupDependencies {} // eslint-disable-next-line export interface BfetchServerStartDependencies {} +export interface BatchProcessingRouteParams { + onBatchItem: (data: BatchItemData) => Promise; +} + export interface BfetchServerSetup { - addStreamingResponseRoute: (path: string, handler: StreamingResponseHandler) => void; + addBatchProcessingRoute: ( + path: string, + handler: (request: KibanaRequest) => BatchProcessingRouteParams + ) => void; + addStreamingResponseRoute: ( + path: string, + params: (request: KibanaRequest) => StreamingResponseHandler + ) => void; } // eslint-disable-next-line @@ -49,8 +75,10 @@ export class BfetchServerPlugin const logger = this.initializerContext.logger.get(); const router = core.http.createRouter(); const addStreamingResponseRoute = this.addStreamingResponseRoute({ router, logger }); + const addBatchProcessingRoute = this.addBatchProcessingRoute(addStreamingResponseRoute); return { + addBatchProcessingRoute, addStreamingResponseRoute, }; } @@ -76,17 +104,56 @@ export class BfetchServerPlugin }, }, async (context, request, response) => { + const handlerInstance = handler(request); const data = request.body; + const headers = { + 'Content-Type': 'application/x-ndjson', + Connection: 'keep-alive', + 'Transfer-Encoding': 'chunked', + 'Cache-Control': 'no-cache', + }; return response.ok({ - headers: { - 'Content-Type': 'application/x-ndjson', - Connection: 'keep-alive', - 'Transfer-Encoding': 'chunked', - 'Cache-Control': 'no-cache', - }, - body: createNDJSONStream(data, handler, logger), + headers, + body: createNDJSONStream(data, handlerInstance, logger), }); } ); }; + + private addBatchProcessingRoute = ( + addStreamingResponseRoute: BfetchServerSetup['addStreamingResponseRoute'] + ): BfetchServerSetup['addBatchProcessingRoute'] => < + BatchItemData extends object, + BatchItemResult extends object, + E extends ErrorLike = ErrorLike + >( + path: string, + handler: (request: KibanaRequest) => BatchProcessingRouteParams + ) => { + addStreamingResponseRoute< + BatchRequestData, + BatchResponseItem + >(path, request => { + const handlerInstance = handler(request); + return { + getResponseStream: ({ batch }) => { + const subject = new Subject>(); + let cnt = batch.length; + batch.forEach(async (batchItem, id) => { + try { + const result = await handlerInstance.onBatchItem(batchItem); + subject.next({ id, result }); + } catch (err) { + const error = normalizeError(err); + subject.next({ id, error }); + } finally { + cnt--; + if (!cnt) subject.complete(); + } + }); + return subject; + }, + }; + }); + }; } diff --git a/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts b/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts index b1f39f4acbcb5..82fe31906e8bf 100644 --- a/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts +++ b/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts @@ -29,7 +29,7 @@ export const createNDJSONStream = ( logger: Logger ): Stream => { const stream = new PassThrough(); - const results = handler.onRequest(payload); + const results = handler.getResponseStream(payload); results.subscribe({ next: (message: Response) => { diff --git a/src/plugins/expressions/common/type.ts b/src/plugins/expressions/common/type.ts index de9c43d01a0aa..c9daed9b6785a 100644 --- a/src/plugins/expressions/common/type.ts +++ b/src/plugins/expressions/common/type.ts @@ -30,11 +30,6 @@ export function getType(node: any) { } export function serializeProvider(types: any) { - return { - serialize: provider('serialize'), - deserialize: provider('deserialize'), - }; - function provider(key: any) { return (context: any) => { const type = getType(context); @@ -43,6 +38,11 @@ export function serializeProvider(types: any) { return fn(context); }; } + + return { + serialize: provider('serialize'), + deserialize: provider('deserialize'), + }; } export class Type { diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json index ec87b56f3745e..cba693dd4bc20 100644 --- a/src/plugins/expressions/kibana.json +++ b/src/plugins/expressions/kibana.json @@ -1,9 +1,10 @@ { "id": "expressions", "version": "kibana", - "server": false, + "server": true, "ui": true, "requiredPlugins": [ + "bfetch", "inspector" ] } diff --git a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts b/src/plugins/expressions/public/batched_fetch.test.ts similarity index 97% rename from src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts rename to src/plugins/expressions/public/batched_fetch.test.ts index 3da15cf54cda0..7273be872a725 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts +++ b/src/plugins/expressions/public/batched_fetch.test.ts @@ -18,7 +18,7 @@ */ import { batchedFetch, Request } from './batched_fetch'; -import { defer } from '../../../../../plugins/kibana_utils/public'; +import { defer } from '../../kibana_utils/public'; import { Subject } from 'rxjs'; const serialize = (o: any) => JSON.stringify(o); diff --git a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts b/src/plugins/expressions/public/batched_fetch.ts similarity index 87% rename from src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts rename to src/plugins/expressions/public/batched_fetch.ts index 717a87fc90f9f..6a155b7d42b72 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts +++ b/src/plugins/expressions/public/batched_fetch.ts @@ -20,13 +20,11 @@ import _ from 'lodash'; import { filter, map } from 'rxjs/operators'; // eslint-disable-next-line -import { split } from '../../../../../plugins/bfetch/public/streaming'; -import { BfetchPublicApi } from '../../../../../plugins/bfetch/public'; -import { defer } from '../../../../../plugins/kibana_utils/public'; -import { FUNCTIONS_URL } from './consts'; +import { split, BfetchPublicContract } from '../../bfetch/public'; +import { defer } from '../../kibana_utils/public'; export interface Options { - fetchStreaming: BfetchPublicApi['fetchStreaming']; + fetchStreaming: BfetchPublicContract['fetchStreaming']; serialize: any; ms?: number; } @@ -111,9 +109,9 @@ export function batchedFetch({ fetchStreaming, serialize, ms = 10 }: Options) { * Runs the specified batch of functions on the server, then resolves * the related promises. */ -async function processBatch(fetchStreaming: BfetchPublicApi['fetchStreaming'], batch: Batch) { - const { stream, promise } = fetchStreaming({ - url: FUNCTIONS_URL, +async function processBatch(fetchStreaming: BfetchPublicContract['fetchStreaming'], batch: Batch) { + const { stream } = fetchStreaming({ + url: `/api/interpreter/fns`, body: JSON.stringify({ functions: Object.values(batch).map(({ request }) => request), }), @@ -137,7 +135,7 @@ async function processBatch(fetchStreaming: BfetchPublicApi['fetchStreaming'], b }); try { - await promise; + await stream.toPromise(); } catch (error) { Object.values(batch).forEach(({ future }) => { future.reject(error); diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx index 089c324677712..a3476a24dd7ed 100644 --- a/src/plugins/expressions/public/mocks.tsx +++ b/src/plugins/expressions/public/mocks.tsx @@ -23,6 +23,7 @@ import { ExpressionsSetup, ExpressionsStart, plugin as pluginInitializer } from /* eslint-disable */ import { coreMock } from '../../../core/public/mocks'; import { inspectorPluginMock } from '../../inspector/public/mocks'; +import { bfetchPluginMock } from '../../bfetch/public/mocks'; /* eslint-enable */ export type Setup = jest.Mocked; @@ -48,6 +49,7 @@ const createSetupContract = (): Setup => { interpretAst: () => {}, }, }), + loadLegacyServerFunctionWrappers: () => Promise.resolve(), }, }; return setupContract; @@ -71,6 +73,7 @@ const createPlugin = async () => { const coreStart = coreMock.createStart(); const plugin = pluginInitializer(pluginInitializerContext); const setup = await plugin.setup(coreSetup, { + bfetch: bfetchPluginMock.createSetupContract(), inspector: inspectorPluginMock.createSetupContract(), }); @@ -82,6 +85,7 @@ const createPlugin = async () => { setup, doStart: async () => await plugin.start(coreStart, { + bfetch: bfetchPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), }), }; diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts index 11f804464704e..2ba10be76cd92 100644 --- a/src/plugins/expressions/public/plugin.ts +++ b/src/plugins/expressions/public/plugin.ts @@ -20,6 +20,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; import { ExpressionInterpretWithHandlers, ExpressionExecutor } from './types'; import { FunctionsRegistry, RenderFunctionsRegistry, TypesRegistry } from './registries'; +import { BfetchPublicSetup, BfetchPublicStart } from '../../bfetch/public'; import { Setup as InspectorSetup, Start as InspectorStart } from '../../inspector/public'; import { setCoreStart, @@ -58,12 +59,15 @@ import { ExpressionLoader, loader } from './loader'; import { ExpressionDataHandler, execute } from './execute'; import { render, ExpressionRenderHandler } from './render'; import { AnyExpressionFunction, AnyExpressionType } from '../common/types'; +import { serializeProvider } from '../common'; export interface ExpressionsSetupDeps { + bfetch: BfetchPublicSetup; inspector: InspectorSetup; } export interface ExpressionsStartDeps { + bfetch: BfetchPublicStart; inspector: InspectorStart; } @@ -76,6 +80,7 @@ export interface ExpressionsSetup { renderers: RenderFunctionsRegistry; types: TypesRegistry; getExecutor: () => ExpressionExecutor; + loadLegacyServerFunctionWrappers: () => Promise; }; } @@ -98,7 +103,7 @@ export class ExpressionsPublicPlugin constructor(initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup, { inspector }: ExpressionsSetupDeps): ExpressionsSetup { + public setup(core: CoreSetup, { inspector, bfetch }: ExpressionsSetupDeps): ExpressionsSetup { const { functions, renderers, types } = this; setRenderersRegistry(renderers); @@ -146,6 +151,31 @@ export class ExpressionsPublicPlugin setInterpreter(getExecutor().interpreter); + let cached: Promise | null = null; + const loadLegacyServerFunctionWrappers = async () => { + if (!cached) { + cached = (async () => { + const serverFunctionList = await core.http.get(`/api/interpreter/fns`); + const batchedFunction = bfetch.batchedFunction({ url: `/api/interpreter/fns` }); + const { serialize } = serializeProvider(types.toJS()); + + // For every sever-side function, register a client-side + // function that matches its definition, but which simply + // calls the server-side function endpoint. + Object.keys(serverFunctionList).forEach(functionName => { + const fn = () => ({ + ...serverFunctionList[functionName], + fn: (context: any, args: any) => { + return batchedFunction({ functionName, args, context: serialize(context) }); + }, + }); + registerFunction(fn); + }); + })(); + } + return cached; + }; + const setup: ExpressionsSetup = { registerFunction, registerRenderer: (renderer: any) => { @@ -159,6 +189,7 @@ export class ExpressionsPublicPlugin renderers, types, getExecutor, + loadLegacyServerFunctionWrappers, }, }; diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/index.js b/src/plugins/expressions/server/index.ts similarity index 71% rename from src/legacy/core_plugins/kbn_vislib_vis_types/index.js rename to src/plugins/expressions/server/index.ts index 6e1f17c941ece..6718602ccdef5 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/index.js +++ b/src/plugins/expressions/server/index.ts @@ -17,14 +17,11 @@ * under the License. */ -export default function(kibana) { - return new kibana.Plugin({ - uiExports: { - visTypes: ['plugins/kbn_vislib_vis_types/kbn_vislib_vis_types'], - interpreter: [ - 'plugins/kbn_vislib_vis_types/pie_fn', - 'plugins/kbn_vislib_vis_types/vislib_fn', - ], - }, - }); +import { PluginInitializerContext } from '../../../core/server'; +import { ExpressionsServerPlugin } from './plugin'; + +export { ExpressionsServerSetup, ExpressionsServerStart } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new ExpressionsServerPlugin(initializerContext); } diff --git a/src/plugins/expressions/server/legacy.ts b/src/plugins/expressions/server/legacy.ts new file mode 100644 index 0000000000000..54e2a5a387342 --- /dev/null +++ b/src/plugins/expressions/server/legacy.ts @@ -0,0 +1,135 @@ +/* + * 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 */ + +// TODO: Remove this file once https://github.com/elastic/kibana/issues/46906 is complete. + +// @ts-ignore +import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common'; + +import Boom from 'boom'; +import { schema } from '@kbn/config-schema'; +import { CoreSetup, Logger } from 'src/core/server'; +import { ExpressionsServerSetupDependencies } from './plugin'; +import { typeSpecs as types, Type } from '../common'; +import { serializeProvider } from '../common'; + +export class TypesRegistry extends Registry { + wrapper(obj: any) { + return new (Type as any)(obj); + } +} + +export class FunctionsRegistry extends Registry { + wrapper(obj: any) { + return new Fn(obj); + } +} + +export const registries = { + types: new TypesRegistry(), + serverFunctions: new FunctionsRegistry(), +}; + +export interface LegacyInterpreterServerApi { + registries(): typeof registries; + register(specs: Record): typeof registries; +} + +export const createLegacyServerInterpreterApi = (): LegacyInterpreterServerApi => { + const api = registryFactory(registries); + + register(registries, { + types, + }); + + return api; +}; + +export const createLegacyServerEndpoints = ( + api: LegacyInterpreterServerApi, + logger: Logger, + core: CoreSetup, + plugins: ExpressionsServerSetupDependencies +) => { + const router = core.http.createRouter(); + + /** + * Register the endpoint that returns the list of server-only functions. + */ + router.get( + { + path: `/api/interpreter/fns`, + validate: { + body: schema.any(), + }, + }, + async (context, request, response) => { + const functions = api.registries().serverFunctions.toJS(); + const body = JSON.stringify(functions); + return response.ok({ + body, + }); + } + ); + + /** + * Run a single Canvas function. + * + * @param {*} server - The Kibana server object + * @param {*} handlers - The Canvas handlers + * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` + */ + async function runFunction(handlers: any, fnCall: any) { + const { functionName, args, context } = fnCall; + const { deserialize } = serializeProvider(registries.types.toJS()); + const fnDef = registries.serverFunctions.toJS()[functionName]; + if (!fnDef) throw Boom.notFound(`Function "${functionName}" could not be found.`); + const deserialized = deserialize(context); + const result = fnDef.fn(deserialized, args, handlers); + return result; + } + + /** + * Register an endpoint that executes a batch of functions, and streams the + * results back using ND-JSON. + */ + plugins.bfetch.addBatchProcessingRoute(`/api/interpreter/fns`, request => { + const scopedClient = core.elasticsearch.dataClient.asScoped(request); + const handlers = { + environment: 'server', + elasticsearchClient: async ( + endpoint: string, + clientParams: Record = {}, + options?: any + ) => scopedClient.callAsCurrentUser(endpoint, clientParams, options), + }; + + return { + onBatchItem: async (fnCall: any) => { + const result = await runFunction(handlers, fnCall); + if (typeof result === 'undefined') { + throw new Error(`Function ${fnCall.functionName} did not return anything.`); + } + return result; + }, + }; + }); +}; diff --git a/src/plugins/expressions/server/mocks.ts b/src/plugins/expressions/server/mocks.ts new file mode 100644 index 0000000000000..4510ae6dc0b4a --- /dev/null +++ b/src/plugins/expressions/server/mocks.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ExpressionsServerSetup, ExpressionsServerStart } from '.'; +import { plugin as pluginInitializer } from '.'; +import { coreMock } from '../../../core/server/mocks'; + +/* eslint-disable */ +import { bfetchPluginMock } from '../../bfetch/server/mocks'; +/* eslint-enable */ + +export type Setup = jest.Mocked; +export type Start = jest.Mocked; + +const createSetupContract = (): Setup => { + const setupContract: Setup = { + __LEGACY: { + register: jest.fn(), + registries: jest.fn(), + }, + }; + return setupContract; +}; + +const createStartContract = (): Start => { + const startContract: Start = {}; + + return startContract; +}; + +const createPlugin = async () => { + const pluginInitializerContext = coreMock.createPluginInitializerContext(); + const coreSetup = coreMock.createSetup(); + const coreStart = coreMock.createStart(); + const plugin = pluginInitializer(pluginInitializerContext); + const setup = await plugin.setup(coreSetup, { + bfetch: bfetchPluginMock.createSetupContract(), + }); + + return { + pluginInitializerContext, + coreSetup, + coreStart, + plugin, + setup, + doStart: async () => + await plugin.start(coreStart, { + bfetch: bfetchPluginMock.createStartContract(), + }), + }; +}; + +export const expressionsPluginMock = { + createSetupContract, + createStartContract, + createPlugin, +}; diff --git a/src/plugins/expressions/server/plugin.ts b/src/plugins/expressions/server/plugin.ts new file mode 100644 index 0000000000000..84c780b5ca226 --- /dev/null +++ b/src/plugins/expressions/server/plugin.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreStart, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/server'; +import { BfetchServerSetup, BfetchServerStart } from '../../bfetch/server'; +import { + LegacyInterpreterServerApi, + createLegacyServerInterpreterApi, + createLegacyServerEndpoints, +} from './legacy'; + +// eslint-disable-next-line +export interface ExpressionsServerSetupDependencies { + bfetch: BfetchServerSetup; +} + +// eslint-disable-next-line +export interface ExpressionsServerStartDependencies { + bfetch: BfetchServerStart; +} + +export interface ExpressionsServerSetup { + __LEGACY: LegacyInterpreterServerApi; +} + +// eslint-disable-next-line +export interface ExpressionsServerStart {} + +export class ExpressionsServerPlugin + implements + Plugin< + ExpressionsServerSetup, + ExpressionsServerStart, + ExpressionsServerSetupDependencies, + ExpressionsServerStartDependencies + > { + constructor(private readonly initializerContext: PluginInitializerContext) {} + + public setup( + core: CoreSetup, + plugins: ExpressionsServerSetupDependencies + ): ExpressionsServerSetup { + const logger = this.initializerContext.logger.get(); + + const legacyApi = createLegacyServerInterpreterApi(); + createLegacyServerEndpoints(legacyApi, logger, core, plugins); + + return { + __LEGACY: legacyApi, + }; + } + + public start( + core: CoreStart, + plugins: ExpressionsServerStartDependencies + ): ExpressionsServerStart { + return {}; + } + + public stop() {} +} diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts index eb3bb96c8e874..bfb45b88964d8 100644 --- a/src/plugins/kibana_utils/common/index.ts +++ b/src/plugins/kibana_utils/common/index.ts @@ -18,4 +18,5 @@ */ export * from './defer'; +export * from './of'; export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_with_initial_value'; diff --git a/src/plugins/kibana_utils/common/of.test.ts b/src/plugins/kibana_utils/common/of.test.ts new file mode 100644 index 0000000000000..6c3f0ec1592bd --- /dev/null +++ b/src/plugins/kibana_utils/common/of.test.ts @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { of } from './of'; + +describe('of()', () => { + describe('when promise resolves', () => { + const promise = new Promise(resolve => resolve()).then(() => 123); + + test('first member of 3-tuple is the promise value', async () => { + const [result] = await of(promise); + expect(result).toBe(123); + }); + + test('second member of 3-tuple is undefined', async () => { + const [, error] = await of(promise); + expect(error).toBe(undefined); + }); + + test('third, flag member, of 3-tuple is true', async () => { + const [, , resolved] = await of(promise); + expect(resolved).toBe(true); + }); + }); + + describe('when promise rejects', () => { + const promise = new Promise(resolve => resolve()).then(() => { + // eslint-disable-next-line no-throw-literal + throw 123; + }); + + test('first member of 3-tuple is undefined', async () => { + const [result] = await of(promise); + expect(result).toBe(undefined); + }); + + test('second member of 3-tuple is thrown error', async () => { + const [, error] = await of(promise); + expect(error).toBe(123); + }); + + test('third, flag member, of 3-tuple is false', async () => { + const [, , resolved] = await of(promise); + expect(resolved).toBe(false); + }); + }); +}); diff --git a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts b/src/plugins/kibana_utils/common/of.ts similarity index 56% rename from src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts rename to src/plugins/kibana_utils/common/of.ts index 6e295d0aecaa5..fa0ec8b0ce306 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts +++ b/src/plugins/kibana_utils/common/of.ts @@ -17,16 +17,21 @@ * under the License. */ -export const createHandlers = (request: any, server: any) => { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); - const config = server.config(); - - return { - environment: 'server', - serverUri: - config.has('server.rewriteBasePath') && config.get('server.rewriteBasePath') - ? `${server.info.uri}${config.get('server.basePath')}` - : server.info.uri, - elasticsearchClient: async (...args: any) => callWithRequest(request, ...args), - }; +/** + * Given a promise awaits it and returns a 3-tuple, with the following members: + * + * - First entry is either the resolved value of the promise or `undefined`. + * - Second entry is either the error thrown by promise or `undefined`. + * - Third entry is a boolean, truthy if promise was resolved and falsy if rejected. + * + * @param promise Promise to convert to 3-tuple. + */ +export const of = async ( + promise: Promise +): Promise<[T | undefined, E | undefined, boolean]> => { + try { + return [await promise, undefined, true]; + } catch (error) { + return [undefined, error, false]; + } }; diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index 0ba444c4e9395..fa58a61e51232 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -17,7 +17,7 @@ * under the License. */ -export { defer } from '../common'; +export { defer, Defer, of } from '../common'; export * from './core'; export * from './errors'; export * from './field_mapping'; diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index 96285901289b6..6fd631baa27d7 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -64,8 +64,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { } }); - // FLAKY: https://github.com/elastic/kibana/issues/33468 - it.skip('detect navigate back issues', async () => { + it('detect navigate back issues', async () => { let currUrl; // Detects bug described in issue #31238 - where back navigation would get stuck to URL encoding handling in Angular. // Navigate to home app diff --git a/test/plugin_functional/config.js b/test/plugin_functional/config.js index e9a4f3bcc4b1a..e63054f1b6912 100644 --- a/test/plugin_functional/config.js +++ b/test/plugin_functional/config.js @@ -38,6 +38,7 @@ export default async function({ readConfigFile }) { require.resolve('./test_suites/embeddable_explorer'), require.resolve('./test_suites/core_plugins'), require.resolve('./test_suites/management'), + require.resolve('./test_suites/bfetch_explorer'), ], services: { ...functionalConfig.get('services'), diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json new file mode 100644 index 0000000000000..1acc7df871c94 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "kbn_tp_bfetch_explorer", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["kbn_tp_bfetch_explorer"], + "server": true, + "ui": true, + "requiredPlugins": ["bfetch"], + "optionalPlugins": [] +} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json new file mode 100644 index 0000000000000..e396489a1ffc4 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json @@ -0,0 +1,17 @@ +{ + "name": "kbn_tp_bfetch_explorer", + "version": "1.0.0", + "main": "target/examples/kbn_tp_bfetch_explorer", + "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_bfetch_explorer/public/index.ts b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts new file mode 100644 index 0000000000000..547dfe2aa38d2 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from '../../../../../examples/bfetch_explorer/public'; diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts new file mode 100644 index 0000000000000..b4370eb53311e --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from '../../../../../examples/bfetch_explorer/server'; diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json new file mode 100644 index 0000000000000..994f81e396763 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true, + "types": [ + "node", + "jest", + "react" + ] + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "server/**/*.tsx", + "../../../../typings/**/*", + ], + "exclude": [] +} diff --git a/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts b/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts new file mode 100644 index 0000000000000..cb2a0b41694c2 --- /dev/null +++ b/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts @@ -0,0 +1,93 @@ +/* + * 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 '../../../functional/ftr_provider_context'; + +export default function({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const appsMenu = getService('appsMenu'); + + describe('batchedFunction', () => { + beforeEach(async () => { + await appsMenu.clickLink('bfetch explorer'); + await testSubjects.click('count-until'); + await testSubjects.click('double-integers'); + }); + + it('executes all requests in a batch', async () => { + const form = await testSubjects.find('DoubleIntegers'); + const btn = await form.findByCssSelector('button'); + await btn.click(); + await new Promise(r => setTimeout(r, 4000)); + const pre = await form.findByCssSelector('pre'); + const text = await pre.getVisibleText(); + const json = JSON.parse(text); + + expect(json).to.eql([ + { + num: -1, + error: { + message: 'Invalid number', + }, + }, + { + num: 300, + result: { + num: 600, + }, + }, + { + num: 1000, + result: { + num: 2000, + }, + }, + { + num: 2000, + result: { + num: 4000, + }, + }, + ]); + }); + + it('streams results back', async () => { + const form = await testSubjects.find('DoubleIntegers'); + const btn = await form.findByCssSelector('button'); + await btn.click(); + + await new Promise(r => setTimeout(r, 500)); + const pre = await form.findByCssSelector('pre'); + + const text1 = await pre.getVisibleText(); + const json1 = JSON.parse(text1); + + expect(json1.length > 0).to.be(true); + expect(json1.length < 4).to.be(true); + + await new Promise(r => setTimeout(r, 3500)); + + const text2 = await pre.getVisibleText(); + const json2 = JSON.parse(text2); + + expect(json2.length).to.be(4); + }); + }); +} diff --git a/test/plugin_functional/test_suites/bfetch_explorer/index.ts b/test/plugin_functional/test_suites/bfetch_explorer/index.ts new file mode 100644 index 0000000000000..54f127d6de89a --- /dev/null +++ b/test/plugin_functional/test_suites/bfetch_explorer/index.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +export default function({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const appsMenu = getService('appsMenu'); + const PageObjects = getPageObjects(['common', 'header']); + + describe('bfetch explorer', function() { + before(async () => { + await browser.setWindowSize(1300, 900); + await PageObjects.common.navigateToApp('settings'); + await appsMenu.clickLink('bfetch explorer'); + }); + + loadTestFile(require.resolve('./batched_function')); + }); +} diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx new file mode 100644 index 0000000000000..80281c1a0a8fc --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { storiesOf } from '@storybook/react'; +import React from 'react'; +import { PlatinumLicensePrompt } from './PlatinumLicensePrompt'; +import { + ApmPluginContext, + ApmPluginContextValue +} from '../../../context/ApmPluginContext'; + +storiesOf('app/ServiceMap/PlatinumLicensePrompt', module).add( + 'example', + () => { + const contextMock = ({ + core: { http: { basePath: { prepend: () => {} } } } + } as unknown) as ApmPluginContextValue; + + return ( + + + + ); + }, + { + info: { + source: false + } + } +); diff --git a/x-pack/legacy/plugins/apm/readme.md b/x-pack/legacy/plugins/apm/readme.md index 6b21f08b7695e..2106243d12aea 100644 --- a/x-pack/legacy/plugins/apm/readme.md +++ b/x-pack/legacy/plugins/apm/readme.md @@ -40,7 +40,6 @@ For testing purposes APM uses 3 custom users: **kibana_write_user** Apps: read/write. Indices: None - To create the users with the correct roles run the following script: ```sh @@ -88,6 +87,12 @@ yarn prettier "./x-pack/legacy/plugins/apm/**/*.{tsx,ts,js}" --write yarn eslint ./x-pack/legacy/plugins/apm --fix ``` +#### Storybook + +Start the [Storybook](https://storybook.js.org/) development environment with +`yarn storybook apm`. All files with a .stories.tsx extension will be loaded. +You can access the development environment at http://localhost:9001. + #### Further resources - [Cypress integration tests](cypress/README.md) diff --git a/x-pack/legacy/plugins/apm/scripts/storybook.js b/x-pack/legacy/plugins/apm/scripts/storybook.js new file mode 100644 index 0000000000000..846ee1f301e30 --- /dev/null +++ b/x-pack/legacy/plugins/apm/scripts/storybook.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { join } from 'path'; + +// eslint-disable-next-line +require('@kbn/storybook').runStorybookCli({ + name: 'apm', + storyGlobs: [ + join(__dirname, '..', 'public', 'components', '**', '*.stories.tsx') + ] +}); diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 470fa00734d27..391973f6d909b 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -30,7 +30,7 @@ import 'uiExports/shareContextMenuExtensions'; import _ from 'lodash'; import 'ui/autoload/all'; import 'ui/kbn_top_nav'; -import 'ui/vislib'; +import 'ui/color_maps'; import 'ui/agg_response'; import 'ui/agg_types'; import 'leaflet'; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx index a97e54afbf067..a4e746aa4037d 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx @@ -46,7 +46,15 @@ export const DocumentFieldsHeader = React.memo(({ searchValue, onSearchChange }: } )} value={searchValue} - onChange={e => onSearchChange(e.target.value)} + onChange={e => { + // Temporary fix until EUI fixes the contract + // See my comment https://github.com/elastic/eui/pull/2723/files#r366725059 + if (typeof e === 'string') { + onSearchChange(e); + } else { + onSearchChange(e.target.value); + } + }} aria-label={i18n.translate( 'xpack.idxMgmt.mappingsEditor.documentFields.searchFieldsAriaLabel', { diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx index 9402a64b22dde..a55bd96dce3d0 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx @@ -234,7 +234,7 @@ export const LoadMappingsProvider = ({ onJson, children }: Props) => { mappings, }} diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx index 581b1223b7892..1277568b71bbd 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx @@ -100,14 +100,10 @@ const fielddataFrequencyFilterParam = { }, }, }, - schema: t.intersection([ - t.partial({ - min: t.number, - max: t.number, - min_segment_size: t.number, - }), - t.brand(t.UnknownRecord, (v: any): v is any => !Array.isArray(v), 'Array'), - ]), + schema: t.record( + t.union([t.literal('min'), t.literal('max'), t.literal('min_segment_size')]), + t.number + ), }; const analyzerValidations = [ diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts index 363ccfc2a5fab..e9beee1071597 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts @@ -3,14 +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 { ValidationError, Validation } from 'io-ts'; +import { ValidationError } from 'io-ts'; import { fold } from 'fp-ts/lib/Either'; import { Reporter } from 'io-ts/lib/Reporter'; export type ReporterResult = Array<{ path: string[]; message: string }>; -export const failure = (validation: any): ReporterResult => { - return validation.map((e: ValidationError) => { +const failure = (validation: ValidationError[]): ReporterResult => { + return validation.map(e => { const path: string[] = []; let validationName = ''; @@ -37,6 +37,6 @@ export const failure = (validation: any): ReporterResult => { const empty: never[] = []; const success = () => empty; -export const ErrorReporter: Reporter = { - report: (validation: Validation) => fold(failure, success)(validation as any), +export const errorReporter: Reporter = { + report: fold(failure, success), }; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts index 990d5ec961a6f..fff735da2e758 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { ordString } from 'fp-ts/lib/Ord'; import { toArray } from 'fp-ts/lib/Set'; import { isLeft, isRight } from 'fp-ts/lib/Either'; -import { ErrorReporter } from './error_reporter'; +import { errorReporter } from './error_reporter'; import { ALL_DATA_TYPES, PARAMETERS_DEFINITION } from '../constants'; import { FieldMeta } from '../types'; import { getFieldMeta } from '../lib'; @@ -218,7 +218,7 @@ const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema. const validateMappingsConfiguration = ( mappingsConfiguration: any ): { value: any; errors: MappingsValidationError[] } => { - // Array to keep track of invalid configuration parameters. + // Set to keep track of invalid configuration parameters. const configurationRemoved: Set = new Set(); let copyOfMappingsConfig = { ...mappingsConfiguration }; @@ -228,7 +228,7 @@ const validateMappingsConfiguration = ( /** * To keep the logic simple we will strip out the parameters that contain errors */ - const errors = ErrorReporter.report(result); + const errors = errorReporter.report(result); errors.forEach(error => { const configurationName = error.path[0]; configurationRemoved.add(configurationName); diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index d28f483c9b987..8179a15e441ac 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -17,7 +17,7 @@ import { APP_ID, APP_ICON, createMapPath, MAP_SAVED_OBJECT_TYPE } from './common export function maps(kibana) { return new kibana.Plugin({ // task_manager could be required, but is only used for telemetry - require: ['kibana', 'elasticsearch', 'xpack_main', 'tile_map'], + require: ['kibana', 'elasticsearch', 'xpack_main'], id: APP_ID, configPrefix: 'xpack.maps', publicDir: resolve(__dirname, 'public'), diff --git a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js index b9346516eeea8..ec3a588d3627f 100644 --- a/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js +++ b/x-pack/legacy/plugins/maps/public/embeddable/map_embeddable_factory.js @@ -23,7 +23,6 @@ import { getQueryableUniqueIndexPatternIds } from '../selectors/map_selectors'; import { getInitialLayers } from '../angular/get_initial_layers'; import { mergeInputWithSavedMap } from './merge_input_with_saved_map'; import '../angular/services/gis_map_saved_object_loader'; -import 'ui/vis/map/service_settings'; export class MapEmbeddableFactory extends EmbeddableFactory { type = MAP_SAVED_OBJECT_TYPE; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js index 8ba39fc7bbe26..df212f23cd894 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js @@ -6,7 +6,7 @@ import React from 'react'; -import { vislibColorMaps } from 'ui/vislib/components/color/colormaps'; +import { vislibColorMaps } from 'ui/color_maps'; import { getLegendColors, getColor } from 'ui/vis/map/color_util'; import { ColorGradient } from './components/color_gradient'; import { euiPaletteColorBlind } from '@elastic/eui/lib/services'; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js index 42e88220bd1d9..e80ccb9e144b9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js @@ -227,7 +227,7 @@ export class DynamicColorProperty extends DynamicStyleProperty { } mbStops.push(defaultColor); //last color is default color - return ['match', ['get', this._options.field.name], ...mbStops]; + return ['match', ['to-string', ['get', this._options.field.name]], ...mbStops]; } _getMbOrdinalColorStops() { diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js index b40808d51dd66..206b9e01bab8c 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js @@ -63,9 +63,6 @@ describe('AnomaliesTable', () => { expect(columns).toEqual( expect.arrayContaining([ - expect.objectContaining({ - name: '', - }), expect.objectContaining({ name: 'time', }), diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js index 5454911673fe2..58f1214c11e10 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButtonIcon, EuiLink } from '@elastic/eui'; +import { EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui'; import React from 'react'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { formatHumanReadableDate, @@ -65,7 +66,16 @@ export function getColumns( ) { const columns = [ { - name: '', + name: ( + +

+ +

+
+ ), render: item => ( toggleRow(item)} diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js index 8cbee27bdd9a8..074a584f3a136 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -479,7 +479,6 @@ export const LinksMenu = injectI18n( return ( { describe('Data Frame Analytics: ', () => { test('Minimal initialization', () => { const wrapper = shallow( - + + + ); // Without the jobConfig being loaded, the component will just return empty. expect(wrapper.text()).toMatch(''); diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx index 9691a0706121c..098f8f07bee44 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx @@ -55,6 +55,7 @@ import { SEARCH_SIZE, defaultSearchQuery, } from '../../../../common'; +import { isKeywordAndTextType } from '../../../../common/fields'; import { getOutlierScoreFieldName } from './common'; import { useExploreData, TableItem } from './use_explore_data'; @@ -64,6 +65,10 @@ import { } from '../../../analytics_management/components/analytics_list/common'; import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; import { SavedSearchQuery } from '../../../../../contexts/kibana'; +import { getIndexPatternIdFromName } from '../../../../../util/index_utils'; +import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns'; +import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; +import { useKibanaContext } from '../../../../../contexts/kibana'; const FEATURE_INFLUENCE = 'feature_influence'; @@ -110,6 +115,19 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { const [searchError, setSearchError] = useState(undefined); const [searchString, setSearchString] = useState(undefined); + const kibanaContext = useKibanaContext(); + + const initializeJobCapsService = async () => { + if (jobConfig !== undefined) { + const sourceIndex = jobConfig.source.index[0]; + const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; + const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId); + if (indexPattern !== undefined) { + await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false); + } + } + }; + useEffect(() => { (async function() { const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics( @@ -124,6 +142,10 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { })(); }, []); + useEffect(() => { + initializeJobCapsService(); + }, [jobConfig && jobConfig.id]); + const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]); const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false); @@ -293,10 +315,16 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { 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; - loadExploreData({ field, direction, searchQuery }); + + if (outlierScoreFieldSelected === false) { + requiresKeyword = isKeywordAndTextType(field); + } + + loadExploreData({ field, direction, searchQuery, requiresKeyword }); } }, [JSON.stringify(searchQuery)]); @@ -307,10 +335,16 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { 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; - loadExploreData({ field, direction, searchQuery }); + + if (outlierScoreFieldSelected === false) { + requiresKeyword = isKeywordAndTextType(field); + } + + loadExploreData({ field, direction, searchQuery, requiresKeyword }); return; } }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]); @@ -334,8 +368,17 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { setPageIndex(index); setPageSize(size); - if (sort.field !== sortField || sort.direction !== sortDirection) { - loadExploreData({ ...sort, searchQuery }); + 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 }); } }; } diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts index e76cbaa463f1d..24cc8d000de7e 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts @@ -23,18 +23,12 @@ import { defaultSearchQuery, SearchQuery, } from '../../../../common'; +import { LoadExploreDataArg } from '../../../../common/analytics'; import { getOutlierScoreFieldName } from './common'; -import { SavedSearchQuery } from '../../../../../contexts/kibana'; export type TableItem = Record; -interface LoadExploreDataArg { - field: string; - direction: SortDirection; - searchQuery: SavedSearchQuery; -} - export interface UseExploreDataReturnType { errorMessage: string; loadExploreData: (arg: LoadExploreDataArg) => void; @@ -55,7 +49,12 @@ export const useExploreData = ( const [sortField, setSortField] = useState(''); const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC); - const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => { + const loadExploreData = async ({ + field, + direction, + searchQuery, + requiresKeyword, + }: LoadExploreDataArg) => { if (jobConfig !== undefined) { setErrorMessage(''); setStatus(INDEX_STATUS.LOADING); @@ -70,7 +69,7 @@ export const useExploreData = ( if (field !== undefined) { body.sort = [ { - [field]: { + [`${field}${requiresKeyword ? '.keyword' : ''}`]: { order: direction, }, }, diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx index 1f4ad65bd1879..86f1324cc0377 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx @@ -6,12 +6,14 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiBadge, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiProgress, + EuiScreenReaderOnly, EuiText, EuiToolTip, RIGHT_ALIGNMENT, @@ -142,6 +144,16 @@ export const getColumns = ( // update possible column types to something like (FieldDataColumn | ComputedColumn | ActionsColumn)[] when they have been added to EUI const columns: any[] = [ { + name: ( + +

+ +

+
+ ), align: RIGHT_ALIGNMENT, width: '40px', isExpander: true, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js index 818f1b79b3143..7a6a1c22e39c5 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js @@ -16,8 +16,8 @@ import { JobDescription } from './job_description'; import { JobIcon } from '../../../../components/job_message_icon'; import { getJobIdUrl } from '../utils'; -import { EuiBadge, EuiBasicTable, EuiButtonIcon, EuiLink } from '@elastic/eui'; -import { injectI18n } from '@kbn/i18n/react'; +import { EuiBadge, EuiBasicTable, EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui'; +import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; const PAGE_SIZE = 10; @@ -124,7 +124,16 @@ class JobsListUI extends Component { // be updated if we move to always using props for width. const columns = [ { - name: '', + name: ( + +

+ +

+
+ ), render: item => ( this.toggleRow(item)} @@ -167,7 +176,16 @@ class JobsListUI extends Component { }, { field: 'auditMessage', - name: '', + name: ( + +

+ +

+
+ ), render: item => , }, { @@ -272,7 +290,16 @@ class JobsListUI extends Component { width: '15%', }); columns.push({ - name: '', + name: ( + +

+ +

+
+ ), actions: actionsMenuContent( this.props.showEditJobFlyout, this.props.showDeleteJobModal, diff --git a/x-pack/legacy/plugins/ml/public/application/util/chart_utils.js b/x-pack/legacy/plugins/ml/public/application/util/chart_utils.js index d54b1a9c9ac22..dfa896b3124c6 100644 --- a/x-pack/legacy/plugins/ml/public/application/util/chart_utils.js +++ b/x-pack/legacy/plugins/ml/public/application/util/chart_utils.js @@ -107,7 +107,7 @@ export function drawLineChartDots(data, lineChartGroup, lineChartValuesLine, rad } // this replicates Kibana's filterAxisLabels() behavior -// which can be found in ui/vislib/lib/axis/axis_labels.js +// which can be found in src/legacy/core_plugins/vis_type_vislib/public/vislib/lib/axis/axis_labels.js // axis labels which overflow the chart's boundaries will be removed export function filterAxisLabels(selection, chartWidth) { if (selection === undefined || selection.selectAll === undefined) { diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/helpers.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/helpers.ts new file mode 100644 index 0000000000000..c431d0551b29a --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/helpers.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DEFAULT_TIMEOUT } from '../util/helpers'; + +import { INSPECT_BUTTON_ICON, InspectButtonMetadata } from './selectors'; + +export const openStatsAndTables = (table: InspectButtonMetadata) => { + if (table.tabId) { + cy.get(table.tabId).click({ force: true }); + } + cy.get(table.id, { timeout: DEFAULT_TIMEOUT }); + if (table.altInspectId) { + cy.get(table.altInspectId, { timeout: DEFAULT_TIMEOUT }).trigger('click', { + force: true, + }); + } else { + cy.get(`${table.id} ${INSPECT_BUTTON_ICON}`, { + timeout: DEFAULT_TIMEOUT, + }).trigger('click', { force: true }); + } +}; + +export const closesModal = () => { + cy.get('[data-test-subj="modal-inspect-close"]', { timeout: DEFAULT_TIMEOUT }).click(); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/selectors.ts index 689c98de9598a..a6d4b37be9f00 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/inspect/selectors.ts @@ -4,95 +4,86 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HOSTS_PAGE, HOSTS_PAGE_TAB_URLS, NETWORK_PAGE, NETWORK_TAB_URLS } from '../urls'; - export const INSPECT_BUTTON_ICON = '[data-test-subj="inspect-icon-button"]'; export const INSPECT_MODAL = '[data-test-subj="modal-inspect-euiModal"]'; export const TIMELINE_SETTINGS_ICON = '[data-test-subj="settings-gear"]'; export const TIMELINE_INSPECT_BUTTON = '[data-test-subj="inspect-empty-button"]'; -interface InspectButtonMetadata { +export interface InspectButtonMetadata { altInspectId?: string; id: string; title: string; - url: string; + tabId?: string; } -export const INSPECT_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ +export const INSPECT_HOSTS_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ { id: '[data-test-subj="stat-hosts"]', title: 'Hosts Stat', - url: HOSTS_PAGE, }, { id: '[data-test-subj="stat-authentication"]', title: 'User Authentications Stat', - url: HOSTS_PAGE, }, { id: '[data-test-subj="stat-uniqueIps"]', title: 'Unique IPs Stat', - url: HOSTS_PAGE, }, + { + id: '[data-test-subj="table-allHosts-loading-false"]', + title: 'All Hosts Table', + tabId: '[data-test-subj="navigation-allHosts"]', + }, + { + id: '[data-test-subj="table-authentications-loading-false"]', + title: 'Authentications Table', + tabId: '[data-test-subj="navigation-authentications"]', + }, + { + id: '[data-test-subj="table-uncommonProcesses-loading-false"]', + title: 'Uncommon processes Table', + tabId: '[data-test-subj="navigation-uncommonProcesses"]', + }, + { + altInspectId: `[data-test-subj="events-viewer-panel"] ${INSPECT_BUTTON_ICON}`, + id: '[data-test-subj="events-container-loading-false"]', + title: 'Events Table', + tabId: '[data-test-subj="navigation-events"]', + }, +]; + +export const INSPECT_NETWORK_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ { id: '[data-test-subj="stat-networkEvents"]', title: 'Network events Stat', - url: NETWORK_PAGE, }, { id: '[data-test-subj="stat-dnsQueries"]', title: 'DNS queries Stat', - url: NETWORK_PAGE, }, { id: '[data-test-subj="stat-uniqueFlowId"]', title: 'Unique flow IDs Stat', - url: NETWORK_PAGE, }, { id: '[data-test-subj="stat-tlsHandshakes"]', title: 'TLS handshakes Stat', - url: NETWORK_PAGE, }, { id: '[data-test-subj="stat-UniqueIps"]', title: 'Unique private IPs Stat', - url: NETWORK_PAGE, }, { id: '[data-test-subj="table-topNFlowSource-loading-false"]', title: 'Source IPs Table', - url: NETWORK_PAGE, }, { id: '[data-test-subj="table-topNFlowDestination-loading-false"]', title: 'Destination IPs Table', - url: NETWORK_PAGE, }, { id: '[data-test-subj="table-dns-loading-false"]', title: 'Top DNS Domains Table', - url: NETWORK_TAB_URLS.dns, - }, - { - id: '[data-test-subj="table-allHosts-loading-false"]', - title: 'All Hosts Table', - url: HOSTS_PAGE_TAB_URLS.allHosts, - }, - { - id: '[data-test-subj="table-authentications-loading-false"]', - title: 'Authentications Table', - url: HOSTS_PAGE_TAB_URLS.authentications, - }, - { - id: '[data-test-subj="table-uncommonProcesses-loading-false"]', - title: 'Uncommon processes Table', - url: HOSTS_PAGE_TAB_URLS.uncommonProcesses, - }, - { - altInspectId: `[data-test-subj="events-viewer-panel"] ${INSPECT_BUTTON_ICON}`, - id: '[data-test-subj="events-container-loading-false"]', - title: 'Events Table', - url: HOSTS_PAGE_TAB_URLS.events, + tabId: '[data-test-subj="navigation-dns"]', }, ]; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/helpers.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/helpers.ts index 8fa1a03840e3b..ef2c19bd7e737 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/helpers.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/helpers.ts @@ -7,9 +7,12 @@ import { drag, drop } from '../drag_n_drop/helpers'; import { ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS } from '../hosts/selectors'; import { + CLOSE_TIMELINE_BTN, + CREATE_NEW_TIMELINE, SEARCH_OR_FILTER_CONTAINER, SERVER_SIDE_EVENT_COUNT, TIMELINE_DATA_PROVIDERS, + TIMELINE_SETTINGS, TIMELINE_TOGGLE_BUTTON, TOGGLE_TIMELINE_EXPAND_EVENT, } from './selectors'; @@ -19,12 +22,17 @@ import { DEFAULT_TIMEOUT } from '../util/helpers'; export const toggleTimelineVisibility = () => cy.get(TIMELINE_TOGGLE_BUTTON, { timeout: DEFAULT_TIMEOUT }).click(); +export const createNewTimeline = () => { + cy.get(TIMELINE_SETTINGS).click(); + cy.get(CREATE_NEW_TIMELINE).click(); + cy.get(CLOSE_TIMELINE_BTN).click({ force: true }); +}; + /** Drags and drops a host from the `All Hosts` widget on the `Hosts` page to the timeline */ export const dragFromAllHostsToTimeline = () => { cy.get(ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS) .first() .then(host => drag(host)); - cy.get(TIMELINE_DATA_PROVIDERS).then(dataProvidersDropArea => drop(dataProvidersDropArea)); }; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts index 7dc98072b52f8..0ec0c506cbb1a 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/lib/timeline/selectors.ts @@ -36,3 +36,9 @@ export const TOGGLE_TIMELINE_EXPAND_EVENT = '[data-test-subj="expand-event"]'; /** The body of the timeline flyout */ export const TIMELINE_FLYOUT_BODY = '[data-test-subj="eui-flyout-body"]'; + +export const CLOSE_TIMELINE_BTN = '[data-test-subj="close-timeline"]'; + +export const TIMELINE_SETTINGS = '[data-test-subj="settings-gear"]'; + +export const CREATE_NEW_TIMELINE = '[data-test-subj="timeline-new"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts index ee25705a83989..7b0b10831c4a0 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts @@ -4,34 +4,52 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HOSTS_PAGE } from '../../lib/urls'; +import { HOSTS_PAGE, NETWORK_PAGE } from '../../lib/urls'; import { - INSPECT_BUTTON_ICON, INSPECT_MODAL, - INSPECT_BUTTONS_IN_SIEM, + INSPECT_NETWORK_BUTTONS_IN_SIEM, + INSPECT_HOSTS_BUTTONS_IN_SIEM, TIMELINE_SETTINGS_ICON, TIMELINE_INSPECT_BUTTON, } from '../../lib/inspect/selectors'; import { DEFAULT_TIMEOUT, loginAndWaitForPage } from '../../lib/util/helpers'; import { executeKQL, hostExistsQuery, toggleTimelineVisibility } from '../../lib/timeline/helpers'; +import { closesModal, openStatsAndTables } from '../../lib/inspect/helpers'; describe('Inspect', () => { - describe('Hosts and network stats and tables', () => { - INSPECT_BUTTONS_IN_SIEM.map(table => + context('Hosts stats and tables', () => { + before(() => { + loginAndWaitForPage(HOSTS_PAGE); + }); + afterEach(() => { + closesModal(); + }); + + INSPECT_HOSTS_BUTTONS_IN_SIEM.forEach(table => + it(`inspects the ${table.title}`, () => { + openStatsAndTables(table); + cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('be.visible'); + }) + ); + }); + + context('Network stats and tables', () => { + before(() => { + loginAndWaitForPage(NETWORK_PAGE); + }); + afterEach(() => { + closesModal(); + }); + + INSPECT_NETWORK_BUTTONS_IN_SIEM.forEach(table => it(`inspects the ${table.title}`, () => { - loginAndWaitForPage(table.url); - cy.get(table.id, { timeout: DEFAULT_TIMEOUT }); - if (table.altInspectId) { - cy.get(table.altInspectId).trigger('click', { force: true }); - } else { - cy.get(`${table.id} ${INSPECT_BUTTON_ICON}`).trigger('click', { force: true }); - } + openStatsAndTables(table); cy.get(INSPECT_MODAL, { timeout: DEFAULT_TIMEOUT }).should('be.visible'); }) ); }); - describe('Timeline', () => { + context('Timeline', () => { it('inspects the timeline', () => { loginAndWaitForPage(HOSTS_PAGE); toggleTimelineVisibility(); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts index 824e403185238..24c1974cf8343 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts @@ -9,7 +9,11 @@ import { TIMELINE_DROPPED_DATA_PROVIDERS, TIMELINE_DATA_PROVIDERS_EMPTY, } from '../../lib/timeline/selectors'; -import { dragFromAllHostsToTimeline, toggleTimelineVisibility } from '../../lib/timeline/helpers'; +import { + createNewTimeline, + dragFromAllHostsToTimeline, + toggleTimelineVisibility, +} from '../../lib/timeline/helpers'; import { ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS } from '../../lib/hosts/selectors'; import { HOSTS_PAGE } from '../../lib/urls'; import { waitForAllHostsWidget } from '../../lib/hosts/helpers'; @@ -17,15 +21,20 @@ import { DEFAULT_TIMEOUT, loginAndWaitForPage } from '../../lib/util/helpers'; import { drag, dragWithoutDrop } from '../../lib/drag_n_drop/helpers'; describe('timeline data providers', () => { - beforeEach(() => { + before(() => { loginAndWaitForPage(HOSTS_PAGE); - }); - - it('renders the data provider of a host dragged from the All Hosts widget on the hosts page', () => { waitForAllHostsWidget(); + }); + beforeEach(() => { toggleTimelineVisibility(); + }); + + afterEach(() => { + createNewTimeline(); + }); + it('renders the data provider of a host dragged from the All Hosts widget on the hosts page', () => { dragFromAllHostsToTimeline(); cy.get(TIMELINE_DROPPED_DATA_PROVIDERS, { @@ -45,10 +54,6 @@ describe('timeline data providers', () => { }); it('sets the background to euiColorSuccess with a 10% alpha channel when the user starts dragging a host, but is not hovering over the data providers', () => { - waitForAllHostsWidget(); - - toggleTimelineVisibility(); - cy.get(ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS) .first() .then(host => drag(host)); @@ -61,10 +66,6 @@ describe('timeline data providers', () => { }); it('sets the background to euiColorSuccess with a 20% alpha channel when the user starts dragging a host AND is hovering over the data providers', () => { - waitForAllHostsWidget(); - - toggleTimelineVisibility(); - cy.get(ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS) .first() .then(host => drag(host)); @@ -81,10 +82,6 @@ describe('timeline data providers', () => { }); it('renders the dashed border color as euiColorSuccess when hovering over the data providers', () => { - waitForAllHostsWidget(); - - toggleTimelineVisibility(); - cy.get(ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS) .first() .then(host => drag(host)); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts index 5b0ac03ae87dc..63fe56371a4cd 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts @@ -13,13 +13,23 @@ import { HOSTS_PAGE } from '../../lib/urls'; import { waitForAllHostsWidget } from '../../lib/hosts/helpers'; import { loginAndWaitForPage } from '../../lib/util/helpers'; import { drag } from '../../lib/drag_n_drop/helpers'; -import { toggleTimelineVisibility } from '../../lib/timeline/helpers'; +import { createNewTimeline, toggleTimelineVisibility } from '../../lib/timeline/helpers'; describe('timeline flyout button', () => { - beforeEach(() => { + before(() => { loginAndWaitForPage(HOSTS_PAGE); }); + afterEach(() => { + cy.get('[data-test-subj="kibanaChrome"]').then($page => { + if ($page.find('[data-test-subj="flyoutOverlay"]').length === 1) { + toggleTimelineVisibility(); + } + }); + + createNewTimeline(); + }); + it('toggles open the timeline', () => { toggleTimelineVisibility(); diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts index 9a915b0e77d44..fbf75e8a854c6 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts @@ -6,15 +6,19 @@ import { drag, drop } from '../../lib/drag_n_drop/helpers'; import { populateTimeline } from '../../lib/fields_browser/helpers'; -import { toggleFirstTimelineEventDetails } from '../../lib/timeline/helpers'; +import { createNewTimeline, toggleFirstTimelineEventDetails } from '../../lib/timeline/helpers'; import { HOSTS_PAGE } from '../../lib/urls'; import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../lib/util/helpers'; describe('toggle column in timeline', () => { - beforeEach(() => { + before(() => { loginAndWaitForPage(HOSTS_PAGE); }); + afterEach(() => { + createNewTimeline(); + }); + const timestampField = '@timestamp'; const idField = '_id'; diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx index 32dce0e2e5576..56ebbb06f3eb9 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect, useCallback, useMemo } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { ScaleType } from '@elastic/charts'; import darkTheme from '@elastic/eui/dist/eui_theme_dark.json'; @@ -26,14 +26,12 @@ import { HistogramAggregation, MatrixHistogramQueryProps, } from './types'; -import { generateTablePaginationOptions } from '../paginated_table/helpers'; import { ChartSeriesData } from '../charts/common'; import { InspectButtonContainer } from '../inspect'; export const MatrixHistogramComponent: React.FC = ({ activePage, - dataKey, defaultStackByOption, endDate, @@ -45,12 +43,10 @@ export const MatrixHistogramComponent: React.FC - activePage != null && limit != null - ? generateTablePaginationOptions(activePage, limit) - : undefined; const { data, loading, inspect, totalCount, refetch = noop } = useQuery<{}, HistogramAggregation>( { @@ -118,16 +110,13 @@ export const MatrixHistogramComponent: React.FC getPagination(), [activePage, limit]), stackByField: selectedStackByOption.value, } ); @@ -179,7 +168,7 @@ export const MatrixHistogramComponent: React.FC - {stackByOptions && ( + {stackByOptions?.length > 1 && ( void; - isEventsType?: boolean; errorMessage: string; headerChildren?: React.ReactNode; hideHistogramIfEmpty?: boolean; + isAlertsHistogram?: boolean; + isAnomaliesHistogram?: boolean; + isAuthenticationsHistogram?: boolean; id: string; + isDnsHistogram?: boolean; + isEventsHistogram?: boolean; legendPosition?: Position; mapping?: MatrixHistogramMappingTypes; query: Maybe; setQuery: SetQuery; + showLegend?: boolean; sourceId: string; stackByOptions: MatrixHistogramOption[]; subtitle?: string | GetSubTitle; diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts index 1fc1fedae9f88..9cda9d8f6115f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts @@ -16,7 +16,7 @@ import { useUiSetting$ } from '../../lib/kibana'; import { createFilter } from '../helpers'; import { useApolloClient } from '../../utils/apollo_context'; import { inputsModel } from '../../store'; -import { GetMatrixHistogramQuery, GetNetworkDnsQuery } from '../../graphql/types'; +import { GetMatrixHistogramQuery } from '../../graphql/types'; export const useQuery = ({ dataKey, @@ -26,15 +26,12 @@ export const useQuery = ({ isAlertsHistogram = false, isAnomaliesHistogram = false, isAuthenticationsHistogram = false, - isEventsType = false, - isDNSHistogram, - isPtrIncluded, + isEventsHistogram = false, + isDnsHistogram = false, isInspected, query, stackByField, startDate, - sort, - pagination, }: MatrixHistogramQueryProps) => { const [defaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); const [, dispatchToaster] = useStateToaster(); @@ -45,21 +42,7 @@ export const useQuery = ({ const [totalCount, setTotalCount] = useState(-1); const apolloClient = useApolloClient(); - const isDNSQuery = ( - variable: Pick< - MatrixHistogramQueryProps, - 'isDNSHistogram' | 'isPtrIncluded' | 'sort' | 'pagination' - > - ): variable is GetNetworkDnsQuery.Variables => { - return ( - !!isDNSHistogram && - variable.isDNSHistogram !== undefined && - variable.isPtrIncluded !== undefined && - variable.sort !== undefined && - variable.pagination !== undefined - ); - }; - const basicVariables = { + const matrixHistogramVariables: GetMatrixHistogramQuery.Variables = { filterQuery: createFilter(filterQuery), sourceId: 'default', timerange: { @@ -70,20 +53,11 @@ export const useQuery = ({ defaultIndex, inspect: isInspected, stackByField, - }; - const dnsVariables = { - ...basicVariables, - isDNSHistogram, - isPtrIncluded, - sort, - pagination, - }; - const matrixHistogramVariables: GetMatrixHistogramQuery.Variables = { - ...basicVariables, isAlertsHistogram, isAnomaliesHistogram, isAuthenticationsHistogram, - isEventsType, + isDnsHistogram, + isEventsHistogram, }; useEffect(() => { @@ -92,16 +66,13 @@ export const useQuery = ({ const abortSignal = abortCtrl.signal; async function fetchData() { - if (!apolloClient || (pagination != null && pagination.querySize < 0)) return null; + if (!apolloClient) return null; setLoading(true); return apolloClient - .query< - GetMatrixHistogramQuery.Query | GetNetworkDnsQuery.Query, - GetMatrixHistogramQuery.Variables | GetNetworkDnsQuery.Variables - >({ + .query({ query, fetchPolicy: 'cache-first', - variables: isDNSQuery(dnsVariables) ? dnsVariables : matrixHistogramVariables, + variables: matrixHistogramVariables, context: { fetchOptions: { abortSignal, @@ -145,11 +116,8 @@ export const useQuery = ({ query, filterQuery, isInspected, - isDNSHistogram, + isDnsHistogram, stackByField, - sort, - isPtrIncluded, - pagination, startDate, endDate, ]); diff --git a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts index 9d82705e9524b..a81d112fa4c50 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.gql_query.ts @@ -11,7 +11,6 @@ export const networkDnsQuery = gql` $defaultIndex: [String!]! $filterQuery: String $inspect: Boolean! - $isDNSHistogram: Boolean! $isPtrIncluded: Boolean! $pagination: PaginationInputPaginated! $sort: NetworkDnsSortField! @@ -31,7 +30,7 @@ export const networkDnsQuery = gql` stackByField: $stackByField ) { totalCount - edges @skip(if: $isDNSHistogram) { + edges { node { _id dnsBytesIn @@ -44,7 +43,7 @@ export const networkDnsQuery = gql` value } } - pageInfo @skip(if: $isDNSHistogram) { + pageInfo { activePage fakeTotalCount showMorePagesIndicator @@ -53,11 +52,6 @@ export const networkDnsQuery = gql` dsl response } - histogram @include(if: $isDNSHistogram) { - x - y - g - } } } } diff --git a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx index 5c5552edcc4ba..04c8783c30a0f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_dns/index.tsx @@ -26,7 +26,7 @@ import { generateTablePaginationOptions } from '../../components/paginated_table import { createFilter, getDefaultFetchPolicy } from '../helpers'; import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; import { networkDnsQuery } from './index.gql_query'; -import { DEFAULT_TABLE_ACTIVE_PAGE } from '../../store/constants'; +import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../../store/constants'; import { MatrixHistogram } from '../../components/matrix_histogram'; import { MatrixHistogramOption, GetSubTitle } from '../../components/matrix_histogram/types'; import { UpdateDateRange } from '../../components/charts/common'; @@ -57,8 +57,7 @@ interface DnsHistogramOwnProps extends QueryTemplatePaginatedProps { dataKey: string | string[]; defaultStackByOption: MatrixHistogramOption; errorMessage: string; - isDNSHistogram?: boolean; - limit: number; + isDnsHistogram?: boolean; query: DocumentNode; scaleType: ScaleType; setQuery: SetQuery; @@ -105,7 +104,6 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated< const variables: GetNetworkDnsQuery.Variables = { defaultIndex: kibana.services.uiSettings.get(DEFAULT_INDEX_KEY), filterQuery: createFilter(filterQuery), - isDNSHistogram: false, inspect: isInspected, isPtrIncluded, pagination: generateTablePaginationOptions(activePage, limit), @@ -186,12 +184,12 @@ const makeMapStateToProps = () => { const makeMapHistogramStateToProps = () => { const getNetworkDnsSelector = networkSelectors.dnsSelector(); const getQuery = inputsSelectors.globalQueryByIdSelector(); - const mapStateToProps = (state: State, { id = HISTOGRAM_ID, limit }: DnsHistogramOwnProps) => { + const mapStateToProps = (state: State, { id = HISTOGRAM_ID }: DnsHistogramOwnProps) => { const { isInspected } = getQuery(state, id); return { ...getNetworkDnsSelector(state), activePage: DEFAULT_TABLE_ACTIVE_PAGE, - limit, + limit: DEFAULT_TABLE_LIMIT, isInspected, id, }; diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json index d73755fb92185..7b9842fa2c2bc 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json @@ -1901,6 +1901,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "NetworkDnsHistogram", + "description": "", + "args": [ + { + "name": "filterQuery", + "description": "", + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "defaultValue": null + }, + { + "name": "defaultIndex", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + } + }, + "defaultValue": null + }, + { + "name": "timerange", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "stackByField", + "description": "", + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "OBJECT", "name": "NetworkDsOverTimeData", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "NetworkHttp", "description": "", @@ -8744,6 +8797,61 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "NetworkDsOverTimeData", + "description": "", + "fields": [ + { + "name": "inspect", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "matrixHistogramData", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "MatrixOverTimeHistogramData", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "totalCount", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "NetworkHttpSortField", diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts index 73049e26f1581..b13e295a8e168 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts @@ -499,6 +499,8 @@ export interface Source { NetworkDns: NetworkDnsData; + NetworkDnsHistogram: NetworkDsOverTimeData; + NetworkHttp: NetworkHttpData; OverviewNetwork?: Maybe; @@ -1752,6 +1754,14 @@ export interface MatrixOverOrdinalHistogramData { g: string; } +export interface NetworkDsOverTimeData { + inspect?: Maybe; + + matrixHistogramData: MatrixOverTimeHistogramData[]; + + totalCount: number; +} + export interface NetworkHttpData { edges: NetworkHttpEdges[]; @@ -2430,6 +2440,15 @@ export interface NetworkDnsSourceArgs { defaultIndex: string[]; } +export interface NetworkDnsHistogramSourceArgs { + filterQuery?: Maybe; + + defaultIndex: string[]; + + timerange: TimerangeInput; + + stackByField?: Maybe; +} export interface NetworkHttpSourceArgs { id?: Maybe; @@ -3306,8 +3325,9 @@ export namespace GetMatrixHistogramQuery { isAlertsHistogram: boolean; isAnomaliesHistogram: boolean; isAuthenticationsHistogram: boolean; + isDnsHistogram: boolean; defaultIndex: string[]; - isEventsType: boolean; + isEventsHistogram: boolean; filterQuery?: Maybe; inspect: boolean; sourceId: string; @@ -3333,6 +3353,8 @@ export namespace GetMatrixHistogramQuery { AuthenticationsHistogram: AuthenticationsHistogram; EventsHistogram: EventsHistogram; + + NetworkDnsHistogram: NetworkDnsHistogram; }; export type AlertsHistogram = { @@ -3446,6 +3468,34 @@ export namespace GetMatrixHistogramQuery { response: string[]; }; + + export type NetworkDnsHistogram = { + __typename?: 'NetworkDsOverTimeData'; + + matrixHistogramData: ____MatrixHistogramData[]; + + totalCount: number; + + inspect: Maybe<____Inspect>; + }; + + export type ____MatrixHistogramData = { + __typename?: 'MatrixOverTimeHistogramData'; + + x: number; + + y: number; + + g: string; + }; + + export type ____Inspect = { + __typename?: 'Inspect'; + + dsl: string[]; + + response: string[]; + }; } export namespace GetNetworkDnsQuery { @@ -3453,7 +3503,6 @@ export namespace GetNetworkDnsQuery { defaultIndex: string[]; filterQuery?: Maybe; inspect: boolean; - isDNSHistogram: boolean; isPtrIncluded: boolean; pagination: PaginationInputPaginated; sort: NetworkDnsSortField; @@ -3486,8 +3535,6 @@ export namespace GetNetworkDnsQuery { pageInfo: PageInfo; inspect: Maybe; - - histogram: Maybe; }; export type Edges = { @@ -3537,16 +3584,6 @@ export namespace GetNetworkDnsQuery { response: string[]; }; - - export type Histogram = { - __typename?: 'MatrixOverOrdinalHistogramData'; - - x: string; - - y: number; - - g: string; - }; } export namespace GetNetworkHttpQuery { diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx index df83ad056943a..a07cbc8484a1b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx @@ -52,7 +52,7 @@ export const EventsQueryTabBody = ({ defaultStackByOption={eventsStackByOptions[0]} deleteQuery={deleteQuery} endDate={endDate} - isEventsType={true} + isEventsHistogram={true} errorMessage={i18n.ERROR_FETCHING_EVENTS_DATA} filterQuery={filterQuery} query={MatrixHistogramGqlQuery} diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/dns_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/dns_query_tab_body.tsx index 53d68e44f7843..35d6eb15416c9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/dns_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/dns_query_tab_body.tsx @@ -4,31 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { getOr } from 'lodash/fp'; import { EuiSpacer } from '@elastic/eui'; -import { ScaleType } from '@elastic/charts'; import { NetworkDnsTable } from '../../../components/page/network/network_dns_table'; -import { - NetworkDnsQuery, - NetworkDnsHistogramQuery, - HISTOGRAM_ID, -} from '../../../containers/network_dns'; +import { NetworkDnsQuery, HISTOGRAM_ID } from '../../../containers/network_dns'; import { manageQuery } from '../../../components/page/manage_query'; import { NetworkComponentQueryProps } from './types'; import { networkModel } from '../../../store'; + import { MatrixHistogramOption } from '../../../components/matrix_histogram/types'; -import { networkDnsQuery } from '../../../containers/network_dns/index.gql_query'; import * as i18n from '../translations'; -import { useFormatBytes } from '../../../components/formatted_bytes'; +import { MatrixHistogramGqlQuery } from '../../../containers/matrix_histogram/index.gql_query'; +import { MatrixHistogramContainer } from '../../../containers/matrix_histogram'; const NetworkDnsTableManage = manageQuery(NetworkDnsTable); const dnsStackByOptions: MatrixHistogramOption[] = [ { - text: i18n.NAVIGATION_DNS_STACK_BY_DOMAIN, + text: i18n.STACK_BY_DOMAIN, value: 'dns.question.registered_domain', }, ]; @@ -50,50 +46,52 @@ export const DnsQueryTabBody = ({ } }; }, [deleteQuery]); - const formatBytes = useFormatBytes(); + + const getTitle = useCallback( + (option: MatrixHistogramOption) => i18n.DOMAINS_COUNT_BY(option.text), + [] + ); return ( - - {({ - totalCount, - loading, - networkDns, - pageInfo, - loadPage, - id, - inspect, - isInspected, - refetch, - }) => ( - <> - - + <> + + + + {({ + totalCount, + loading, + networkDns, + pageInfo, + loadPage, + id, + inspect, + isInspected, + refetch, + }) => ( - - )} - + )} + + ); }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts index 00adce9b7ad8a..6446cde26796e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/translations.ts @@ -22,12 +22,9 @@ export const NAVIGATION_DNS_TITLE = i18n.translate('xpack.siem.network.navigatio defaultMessage: 'DNS', }); -export const NAVIGATION_DNS_STACK_BY_DOMAIN = i18n.translate( - 'xpack.siem.hosts.navigation.dns.stackByDomain', - { - defaultMessage: 'domain', - } -); +export const STACK_BY_DOMAIN = i18n.translate('xpack.siem.hosts.dns.stackByDomain', { + defaultMessage: 'unique domains', +}); export const ERROR_FETCHING_DNS_DATA = i18n.translate( 'xpack.siem.hosts.navigation.dns.histogram.errorFetchingDnsData', @@ -54,3 +51,9 @@ export const NAVIGATION_ANOMALIES_TITLE = i18n.translate( export const NAVIGATION_ALERTS_TITLE = i18n.translate('xpack.siem.network.navigation.alertsTitle', { defaultMessage: 'Alerts', }); + +export const DOMAINS_COUNT_BY = (groupByField: string) => + i18n.translate('xpack.siem.network.dns.stackByUniqueSubdomain', { + values: { groupByField }, + defaultMessage: 'Top domains by {groupByField}', + }); diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx index b4f945c802e56..52084c4bfc280 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx @@ -108,7 +108,7 @@ export const EventsByDataset = React.memo( })} headerChildren={eventsCountViewEventsButton} id={ID} - isEventsType={true} + isEventsHistogram={true} legendPosition={'right'} query={MatrixHistogramGqlQuery} setQuery={setQuery} diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts index 2dabd51c198f7..06d6b8c516d8b 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts @@ -7,7 +7,7 @@ import { SourceResolvers } from '../../graphql/types'; import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { Network } from '../../lib/network'; -import { createOptionsPaginated } from '../../utils/build_query/create_options'; +import { createOptionsPaginated, createOptions } from '../../utils/build_query/create_options'; import { QuerySourceResolver } from '../sources/resolvers'; type QueryNetworkTopCountriesResolver = ChildResolverOf< @@ -30,6 +30,10 @@ type QueryDnsResolver = ChildResolverOf< QuerySourceResolver >; +type QueryDnsHistogramResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver +>; export interface NetworkResolversDeps { network: Network; } @@ -42,6 +46,7 @@ export const createNetworkResolvers = ( NetworkTopCountries: QueryNetworkTopCountriesResolver; NetworkTopNFlow: QueryNetworkTopNFlowResolver; NetworkDns: QueryDnsResolver; + NetworkDnsHistogram: QueryDnsHistogramResolver; }; } => ({ Source: { @@ -76,9 +81,15 @@ export const createNetworkResolvers = ( ...createOptionsPaginated(source, args, info), networkDnsSortField: args.sort, isPtrIncluded: args.isPtrIncluded, - stackByField: args.stackByField, }; return libs.network.getNetworkDns(req, options); }, + async NetworkDnsHistogram(source, args, { req }, info) { + const options = { + ...createOptions(source, args, info), + stackByField: args.stackByField, + }; + return libs.network.getNetworkDnsHistogramData(req, options); + }, }, }); diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts index a5bca68fb30b9..15e2d832a73c9 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts @@ -196,6 +196,12 @@ export const networkSchema = gql` inspect: Inspect } + type NetworkDsOverTimeData { + inspect: Inspect + matrixHistogramData: [MatrixOverTimeHistogramData!]! + totalCount: Float! + } + extend type Source { NetworkTopCountries( id: String @@ -227,6 +233,12 @@ export const networkSchema = gql` timerange: TimerangeInput! defaultIndex: [String!]! ): NetworkDnsData! + NetworkDnsHistogram( + filterQuery: String + defaultIndex: [String!]! + timerange: TimerangeInput! + stackByField: String + ): NetworkDsOverTimeData! NetworkHttp( id: String filterQuery: String diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index 48ca32874dda2..4a2119b6f7631 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -501,6 +501,8 @@ export interface Source { NetworkDns: NetworkDnsData; + NetworkDnsHistogram: NetworkDsOverTimeData; + NetworkHttp: NetworkHttpData; OverviewNetwork?: Maybe; @@ -1754,6 +1756,14 @@ export interface MatrixOverOrdinalHistogramData { g: string; } +export interface NetworkDsOverTimeData { + inspect?: Maybe; + + matrixHistogramData: MatrixOverTimeHistogramData[]; + + totalCount: number; +} + export interface NetworkHttpData { edges: NetworkHttpEdges[]; @@ -2432,6 +2442,15 @@ export interface NetworkDnsSourceArgs { defaultIndex: string[]; } +export interface NetworkDnsHistogramSourceArgs { + filterQuery?: Maybe; + + defaultIndex: string[]; + + timerange: TimerangeInput; + + stackByField?: Maybe; +} export interface NetworkHttpSourceArgs { id?: Maybe; @@ -2930,6 +2949,8 @@ export namespace SourceResolvers { NetworkDns?: NetworkDnsResolver; + NetworkDnsHistogram?: NetworkDnsHistogramResolver; + NetworkHttp?: NetworkHttpResolver; OverviewNetwork?: OverviewNetworkResolver, TypeParent, TContext>; @@ -3281,6 +3302,21 @@ export namespace SourceResolvers { defaultIndex: string[]; } + export type NetworkDnsHistogramResolver< + R = NetworkDsOverTimeData, + Parent = Source, + TContext = SiemContext + > = Resolver; + export interface NetworkDnsHistogramArgs { + filterQuery?: Maybe; + + defaultIndex: string[]; + + timerange: TimerangeInput; + + stackByField?: Maybe; + } + export type NetworkHttpResolver< R = NetworkHttpData, Parent = Source, @@ -7547,6 +7583,36 @@ export namespace MatrixOverOrdinalHistogramDataResolvers { > = Resolver; } +export namespace NetworkDsOverTimeDataResolvers { + export interface Resolvers { + inspect?: InspectResolver, TypeParent, TContext>; + + matrixHistogramData?: MatrixHistogramDataResolver< + MatrixOverTimeHistogramData[], + TypeParent, + TContext + >; + + totalCount?: TotalCountResolver; + } + + export type InspectResolver< + R = Maybe, + Parent = NetworkDsOverTimeData, + TContext = SiemContext + > = Resolver; + export type MatrixHistogramDataResolver< + R = MatrixOverTimeHistogramData[], + Parent = NetworkDsOverTimeData, + TContext = SiemContext + > = Resolver; + export type TotalCountResolver< + R = number, + Parent = NetworkDsOverTimeData, + TContext = SiemContext + > = Resolver; +} + export namespace NetworkHttpDataResolvers { export interface Resolvers { edges?: EdgesResolver; @@ -9227,6 +9293,7 @@ export type IResolvers = { NetworkDnsEdges?: NetworkDnsEdgesResolvers.Resolvers; NetworkDnsItem?: NetworkDnsItemResolvers.Resolvers; MatrixOverOrdinalHistogramData?: MatrixOverOrdinalHistogramDataResolvers.Resolvers; + NetworkDsOverTimeData?: NetworkDsOverTimeDataResolvers.Resolvers; NetworkHttpData?: NetworkHttpDataResolvers.Resolvers; NetworkHttpEdges?: NetworkHttpEdgesResolvers.Resolvers; NetworkHttpItem?: NetworkHttpItemResolvers.Resolvers; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts index 07b748024743c..4bd980fd2ff80 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts @@ -18,10 +18,16 @@ import { NetworkHttpData, NetworkHttpEdges, NetworkTopNFlowEdges, - MatrixOverOrdinalHistogramData, + NetworkDsOverTimeData, + MatrixOverTimeHistogramData, } from '../../graphql/types'; import { inspectStringifyObject } from '../../utils/build_query'; -import { DatabaseSearchResponse, FrameworkAdapter, FrameworkRequest } from '../framework'; +import { + DatabaseSearchResponse, + FrameworkAdapter, + FrameworkRequest, + MatrixHistogramRequestOptions, +} from '../framework'; import { TermAggregation } from '../types'; import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants'; @@ -32,6 +38,7 @@ import { NetworkTopNFlowRequestOptions, } from './index'; import { buildDnsQuery } from './query_dns.dsl'; +import { buildDnsHistogramQuery } from './query_dns_histogram.dsl'; import { buildTopNFlowQuery, getOppositeField } from './query_top_n_flow.dsl'; import { buildHttpQuery } from './query_http.dsl'; import { buildTopCountriesQuery } from './query_top_countries.dsl'; @@ -41,7 +48,9 @@ import { NetworkTopCountriesBuckets, NetworkHttpBuckets, NetworkTopNFlowBuckets, + DnsHistogramGroupData, } from './types'; +import { EventHit } from '../events/types'; export class ElasticsearchNetworkAdapter implements NetworkAdapter { constructor(private readonly framework: FrameworkAdapter) {} @@ -141,7 +150,6 @@ export class ElasticsearchNetworkAdapter implements NetworkAdapter { ); const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount; const edges = networkDnsEdges.splice(cursorStart, querySize - cursorStart); - const histogram = getHistogramData(edges); const inspect = { dsl: [inspectStringifyObject(dsl)], response: [inspectStringifyObject(response)], @@ -156,7 +164,6 @@ export class ElasticsearchNetworkAdapter implements NetworkAdapter { showMorePagesIndicator, }, totalCount, - histogram, }; } @@ -195,29 +202,36 @@ export class ElasticsearchNetworkAdapter implements NetworkAdapter { totalCount, }; } + + public async getNetworkDnsHistogramData( + request: FrameworkRequest, + options: MatrixHistogramRequestOptions + ): Promise { + const dsl = buildDnsHistogramQuery(options); + const response = await this.framework.callWithRequest( + request, + 'search', + dsl + ); + const totalCount = getOr(0, 'hits.total.value', response); + const matrixHistogramData = getOr([], 'aggregations.NetworkDns.buckets', response); + const inspect = { + dsl: [inspectStringifyObject(dsl)], + response: [inspectStringifyObject(response)], + }; + return { + inspect, + matrixHistogramData: getHistogramData(matrixHistogramData), + totalCount, + }; + } } -const getHistogramData = ( - data: NetworkDnsEdges[] -): MatrixOverOrdinalHistogramData[] | undefined => { - if (!Array.isArray(data)) return undefined; +const getHistogramData = (data: DnsHistogramGroupData[]): MatrixOverTimeHistogramData[] => { return data.reduce( - (acc: MatrixOverOrdinalHistogramData[], { node: { dnsBytesOut, dnsBytesIn, _id } }) => { - if (_id != null && dnsBytesOut != null && dnsBytesIn != null) - return [ - ...acc, - { - x: _id, - y: dnsBytesOut, - g: 'DNS Bytes Out', - }, - { - x: _id, - y: dnsBytesIn, - g: 'DNS Bytes In', - }, - ]; - return acc; + (acc: MatrixOverTimeHistogramData[], { key: time, histogram: { buckets } }) => { + const temp = buckets.map(({ key, doc_count }) => ({ x: time, y: doc_count, g: key })); + return [...acc, ...temp]; }, [] ); diff --git a/x-pack/legacy/plugins/siem/server/lib/network/index.ts b/x-pack/legacy/plugins/siem/server/lib/network/index.ts index 42ce9f0726ddb..cbcd33b753d8a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/index.ts @@ -14,8 +14,13 @@ import { NetworkTopCountriesData, NetworkTopNFlowData, NetworkTopTablesSortField, + NetworkDsOverTimeData, } from '../../graphql/types'; -import { FrameworkRequest, RequestOptionsPaginated } from '../framework'; +import { + FrameworkRequest, + RequestOptionsPaginated, + MatrixHistogramRequestOptions, +} from '../framework'; export * from './elasticsearch_adapter'; import { NetworkAdapter } from './types'; @@ -68,6 +73,13 @@ export class Network { return this.adapter.getNetworkDns(req, options); } + public async getNetworkDnsHistogramData( + req: FrameworkRequest, + options: MatrixHistogramRequestOptions + ): Promise { + return this.adapter.getNetworkDnsHistogramData(req, options); + } + public async getNetworkHttp( req: FrameworkRequest, options: NetworkHttpRequestOptions diff --git a/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts new file mode 100644 index 0000000000000..67457ab4840ac --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/network/query_dns_histogram.dsl.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query'; +import { MatrixHistogramRequestOptions } from '../framework'; + +export const buildDnsHistogramQuery = ({ + filterQuery, + timerange: { from, to }, + defaultIndex, + sourceConfiguration: { + fields: { timestamp }, + }, + stackByField, +}: MatrixHistogramRequestOptions) => { + const filter = [ + ...createQueryFilterClauses(filterQuery), + { + range: { + [timestamp]: { + gte: from, + lte: to, + }, + }, + }, + ]; + + const getHistogramAggregation = () => { + const interval = calculateTimeseriesInterval(from, to); + const histogramTimestampField = '@timestamp'; + const dateHistogram = { + date_histogram: { + field: histogramTimestampField, + fixed_interval: `${interval}s`, + }, + }; + + return { + NetworkDns: { + ...dateHistogram, + aggs: { + histogram: { + terms: { + field: stackByField, + order: { + orderAgg: 'desc', + }, + size: 10, + }, + aggs: { + orderAgg: { + cardinality: { + field: 'dns.question.name', + }, + }, + }, + }, + }, + }, + }; + }; + + const dslQuery = { + index: defaultIndex, + allowNoIndices: true, + ignoreUnavailable: true, + body: { + aggregations: getHistogramAggregation(), + query: { + bool: { + filter, + }, + }, + size: 0, + track_total_hits: true, + }, + }; + + return dslQuery; +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/types.ts b/x-pack/legacy/plugins/siem/server/lib/network/types.ts index 960fbe425b002..b5563f9a2fef1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/types.ts @@ -9,8 +9,13 @@ import { NetworkHttpData, NetworkTopCountriesData, NetworkTopNFlowData, + NetworkDsOverTimeData, } from '../../graphql/types'; -import { FrameworkRequest, RequestOptionsPaginated } from '../framework'; +import { + FrameworkRequest, + RequestOptionsPaginated, + MatrixHistogramRequestOptions, +} from '../framework'; import { TotalValue } from '../types'; import { NetworkDnsRequestOptions } from '.'; @@ -24,6 +29,10 @@ export interface NetworkAdapter { options: RequestOptionsPaginated ): Promise; getNetworkDns(req: FrameworkRequest, options: NetworkDnsRequestOptions): Promise; + getNetworkDnsHistogramData( + request: FrameworkRequest, + options: MatrixHistogramRequestOptions + ): Promise; getNetworkHttp(req: FrameworkRequest, options: RequestOptionsPaginated): Promise; } @@ -143,3 +152,23 @@ export interface NetworkHttpBuckets { buckets: GenericBuckets[]; }; } + +interface DnsHistogramSubBucket { + key: string; + doc_count: number; + orderAgg: { + value: number; + }; +} +interface DnsHistogramBucket { + doc_count_error_upper_bound: number; + sum_other_doc_count: number; + buckets: DnsHistogramSubBucket[]; +} + +export interface DnsHistogramGroupData { + key: number; + doc_count: number; + key_as_string: string; + histogram: DnsHistogramBucket; +} diff --git a/x-pack/legacy/plugins/task_manager/server/legacy.ts b/x-pack/legacy/plugins/task_manager/server/legacy.ts index 772309d67c334..f5e81bfd90169 100644 --- a/x-pack/legacy/plugins/task_manager/server/legacy.ts +++ b/x-pack/legacy/plugins/task_manager/server/legacy.ts @@ -17,7 +17,7 @@ import { TaskInstanceWithId, TaskDefinition, } from '../../../../plugins/task_manager/server/task.js'; -import { FetchOpts } from '../../../../plugins/task_manager/server/task_store.js'; +import { SearchOpts } from '../../../../plugins/task_manager/server/task_store.js'; // Once all plugins are migrated to NP and we can remove Legacy TaskManager in version 8.0.0, // this can be removed @@ -46,7 +46,7 @@ export function createLegacyApi(legacyTaskManager: Promise): Legacy registerTaskDefinitions: (taskDefinitions: TaskDictionary) => { legacyTaskManager.then((tm: TaskManager) => tm.registerTaskDefinitions(taskDefinitions)); }, - fetch: (opts: FetchOpts) => legacyTaskManager.then((tm: TaskManager) => tm.fetch(opts)), + fetch: (opts: SearchOpts) => legacyTaskManager.then((tm: TaskManager) => tm.fetch(opts)), remove: (id: string) => legacyTaskManager.then((tm: TaskManager) => tm.remove(id)), schedule: (taskInstance: TaskInstanceWithDeprecatedFields, options?: any) => legacyTaskManager.then((tm: TaskManager) => tm.schedule(taskInstance, options)), diff --git a/x-pack/legacy/plugins/tilemap/index.js b/x-pack/legacy/plugins/tilemap/index.js index b5f7839c7c7f7..767a0fe72985e 100644 --- a/x-pack/legacy/plugins/tilemap/index.js +++ b/x-pack/legacy/plugins/tilemap/index.js @@ -12,7 +12,7 @@ export const tilemap = kibana => { return new kibana.Plugin({ id: 'tilemap', configPrefix: 'xpack.tilemap', - require: ['xpack_main', 'kbn_vislib_vis_types'], + require: ['xpack_main', 'vis_type_vislib'], publicDir: resolve(__dirname, 'public'), uiExports: { visTypeEnhancers: ['plugins/tilemap/vis_type_enhancers/update_tilemap_settings'], diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx index ebe4f7efda055..e2f92e0acd645 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx @@ -6,12 +6,14 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiBadge, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiProgress, + EuiScreenReaderOnly, EuiText, EuiToolTip, RIGHT_ALIGNMENT, @@ -98,6 +100,16 @@ export const getColumns = ( ActionsColumnType ] = [ { + name: ( + +

+ +

+
+ ), align: RIGHT_ALIGNMENT, width: '40px', isExpander: true, 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 63a054c0c4889..98780d23c5a62 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 @@ -45,7 +45,7 @@ const EmbeddedPanel = styled.div` } `; -export const EmbeddedMap = ({ upPoints, downPoints }: EmbeddedMapProps) => { +export const EmbeddedMap = React.memo(({ upPoints, downPoints }: EmbeddedMapProps) => { const { colors } = useContext(UptimeThemeContext); const [embeddable, setEmbeddable] = useState(); const embeddableRoot: React.RefObject = useRef(null); @@ -55,10 +55,6 @@ export const EmbeddedMap = ({ upPoints, downPoints }: EmbeddedMapProps) => { id: uuid.v4(), filters: [], hidePanelTitles: true, - query: { - query: '', - language: 'kuery', - }, refreshConfig: { value: 0, pause: false, @@ -116,6 +112,6 @@ export const EmbeddedMap = ({ upPoints, downPoints }: EmbeddedMapProps) => {
); -}; +}); EmbeddedMap.displayName = 'EmbeddedMap'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx index bb87497d335ef..63abb6fc4823c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import { LocationMap } from '../location_map'; import { MonitorStatusBar } from './monitor_status_bar'; +import { UptimeRefreshContext } from '../../../contexts'; interface MonitorStatusBarProps { monitorId: string; @@ -29,6 +30,27 @@ export const MonitorStatusDetailsComponent = ({ useEffect(() => { loadMonitorLocations(monitorId); }, [loadMonitorLocations, monitorId, dateStart, dateEnd]); + const { refreshApp } = useContext(UptimeRefreshContext); + + const [isTabActive] = useState(document.visibilityState); + const onTabActive = () => { + if (document.visibilityState === 'visible' && isTabActive === 'hidden') { + refreshApp(); + } + }; + + // Refreshing application state after Tab becomes active to render latest map state + // If application renders in when tab is not in focus it gives some unexpected behaviors + // Where map is not visible on change + useEffect(() => { + document.addEventListener('visibilitychange', onTabActive); + return () => { + document.removeEventListener('visibilitychange', onTabActive); + }; + + // we want this effect to execute exactly once after the component mounts + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( diff --git a/x-pack/package.json b/x-pack/package.json index 84f15d3d38828..bd43d19135aab 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -252,7 +252,7 @@ "immer": "^1.5.0", "inline-style": "^2.0.0", "intl": "^1.2.5", - "io-ts": "^2.0.1", + "io-ts": "^2.0.5", "isbinaryfile": "4.0.2", "joi": "^13.5.2", "jquery": "^3.4.1", diff --git a/x-pack/plugins/task_manager/server/config.ts b/x-pack/plugins/task_manager/server/config.ts index 06e6ad3e62282..e2752f80ad6c4 100644 --- a/x-pack/plugins/task_manager/server/config.ts +++ b/x-pack/plugins/task_manager/server/config.ts @@ -6,6 +6,9 @@ import { schema, TypeOf } from '@kbn/config-schema'; +export const DEFAULT_MAX_WORKERS = 10; +export const DEFAULT_POLL_INTERVAL = 3000; + export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), /* The maximum number of times a task will be attempted before being abandoned as failed */ @@ -15,7 +18,7 @@ export const configSchema = schema.object({ }), /* How often, in milliseconds, the task manager will look for more work. */ poll_interval: schema.number({ - defaultValue: 3000, + defaultValue: DEFAULT_POLL_INTERVAL, min: 100, }), /* How many requests can Task Manager buffer before it rejects new requests. */ @@ -35,7 +38,7 @@ export const configSchema = schema.object({ }), /* The maximum number of tasks that this Kibana instance will run simultaneously. */ max_workers: schema.number({ - defaultValue: 10, + defaultValue: DEFAULT_MAX_WORKERS, // disable the task manager rather than trying to specify it with 0 workers min: 1, }), diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts index 93a8187b673be..ac98fbbda5aa2 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts @@ -9,9 +9,9 @@ import { asUpdateByQuery, shouldBeOneOf, mustBeAllOf, - ExistsBoolClause, - TermBoolClause, - RangeBoolClause, + ExistsFilter, + TermFilter, + RangeFilter, } from './query_clauses'; import { @@ -51,7 +51,7 @@ describe('mark_available_tasks_as_claimed', () => { // status running or claiming with a retryAt <= now. shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt), // Either task has an schedule or the attempts < the maximum configured - shouldBeOneOf( + shouldBeOneOf( TaskWithSchedule, ...Object.entries(definitions).map(([type, { maxAttempts }]) => taskWithLessThanMaxAttempts(type, maxAttempts || defaultMaxAttempts) diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts index 6691b31a546bc..b0d9dc61c9667 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -3,24 +3,24 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { defaultsDeep } from 'lodash'; import { - BoolClause, - IDsClause, SortClause, ScriptClause, - ExistsBoolClause, - TermBoolClause, - RangeBoolClause, + ExistsFilter, + TermFilter, + RangeFilter, + mustBeAllOf, + MustCondition, + MustNotCondition, } from './query_clauses'; -export const TaskWithSchedule: ExistsBoolClause = { +export const TaskWithSchedule: ExistsFilter = { exists: { field: 'task.schedule' }, }; export function taskWithLessThanMaxAttempts( type: string, maxAttempts: number -): BoolClause { +): MustCondition { return { bool: { must: [ @@ -37,34 +37,37 @@ export function taskWithLessThanMaxAttempts( }; } -export const IdleTaskWithExpiredRunAt: BoolClause = { +export function tasksClaimedByOwner(taskManagerId: string) { + return mustBeAllOf( + { + term: { + 'task.ownerId': taskManagerId, + }, + }, + { term: { 'task.status': 'claiming' } } + ); +} + +export const IdleTaskWithExpiredRunAt: MustCondition = { bool: { must: [{ term: { 'task.status': 'idle' } }, { range: { 'task.runAt': { lte: 'now' } } }], }, }; -export const taskWithIDsAndRunnableStatus = ( - claimTasksById: string[] -): BoolClause => ({ +export const InactiveTasks: MustNotCondition = { bool: { - must: [ + must_not: [ { bool: { - should: [{ term: { 'task.status': 'idle' } }, { term: { 'task.status': 'failed' } }], - }, - }, - { - ids: { - values: claimTasksById, + should: [{ term: { 'task.status': 'running' } }, { term: { 'task.status': 'claiming' } }], }, }, + { range: { 'task.retryAt': { gt: 'now' } } }, ], }, -}); +}; -export const RunningOrClaimingTaskWithExpiredRetryAt: BoolClause< - TermBoolClause | RangeBoolClause -> = { +export const RunningOrClaimingTaskWithExpiredRetryAt: MustCondition = { bool: { must: [ { @@ -95,31 +98,6 @@ if (doc['task.runAt'].size()!=0) { }, }; -const SORT_VALUE_TO_BE_FIRST = 0; -export const sortByIdsThenByScheduling = (claimTasksById: string[]): SortClause => { - const { - _script: { - script: { source }, - }, - } = SortByRunAtAndRetryAt; - return defaultsDeep( - { - _script: { - script: { - source: ` -if(params.ids.contains(doc['_id'].value)){ - return ${SORT_VALUE_TO_BE_FIRST}; -} -${source} -`, - params: { ids: claimTasksById }, - }, - }, - }, - SortByRunAtAndRetryAt - ); -}; - export const updateFields = (fieldUpdates: { [field: string]: string | number | Date; }): ScriptClause => ({ diff --git a/x-pack/plugins/task_manager/server/queries/query_clauses.test.ts b/x-pack/plugins/task_manager/server/queries/query_clauses.test.ts new file mode 100644 index 0000000000000..beb8f864bd754 --- /dev/null +++ b/x-pack/plugins/task_manager/server/queries/query_clauses.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { + MustCondition, + shouldBeOneOf, + mustBeAllOf, + ExistsFilter, + TermFilter, + RangeFilter, + matchesClauses, +} from './query_clauses'; + +describe('matchesClauses', () => { + test('merges multiple types of Bool Clauses into one', () => { + const TaskWithSchedule: ExistsFilter = { + exists: { field: 'task.schedule' }, + }; + + const IdleTaskWithExpiredRunAt: MustCondition = { + bool: { + must: [{ term: { 'task.status': 'idle' } }, { range: { 'task.runAt': { lte: 'now' } } }], + }, + }; + + const RunningTask: MustCondition = { + bool: { + must: [{ term: { 'task.status': 'running' } }], + }, + }; + + expect( + matchesClauses( + mustBeAllOf(TaskWithSchedule), + shouldBeOneOf( + RunningTask, + IdleTaskWithExpiredRunAt + ) + ) + ).toMatchObject({ + bool: { + must: [TaskWithSchedule], + should: [RunningTask, IdleTaskWithExpiredRunAt], + }, + }); + }); +}); diff --git a/x-pack/plugins/task_manager/server/queries/query_clauses.ts b/x-pack/plugins/task_manager/server/queries/query_clauses.ts index 1f76ce99e600a..de7e3b085ba2d 100644 --- a/x-pack/plugins/task_manager/server/queries/query_clauses.ts +++ b/x-pack/plugins/task_manager/server/queries/query_clauses.ts @@ -4,30 +4,150 @@ * you may not use this file except in compliance with the Elastic License. */ -export interface TermBoolClause { +/** + * Terminology + * =========== + * The terms for the differenct clauses in an Elasticsearch query can be confusing, here are some + * clarifications that might help you understand the Typescript types we use here. + * + * Given the following Query: + * { + * "query": { (1) + * "bool": { (2) + * "must": + * [ + * (3) { "term" : { "tag" : "wow" } }, + * { "term" : { "tag" : "elasticsearch" } }, + * { + * "must" : { "term" : { "user" : "kimchy" } } + * } + * ] + * } + * } + * } + * + * These are referred to as: + * (1). BoolClause / BoolClauseWithAnyCondition + * (2). BoolCondition / AnyBoolCondition + * (3). BoolClauseFilter + * + */ + +export interface TermFilter { term: { [field: string]: string | string[] }; } -export interface RangeBoolClause { - range: { [field: string]: { lte: string | number } | { lt: string | number } }; +export interface RangeFilter { + range: { + [field: string]: { lte: string | number } | { lt: string | number } | { gt: string | number }; + }; } -export interface ExistsBoolClause { +export interface ExistsFilter { exists: { field: string }; } -export interface IDsClause { - ids: { - values: string[]; - }; -} -export interface ShouldClause { - should: Array | IDsClause | T>; +type BoolClauseFilter = TermFilter | RangeFilter | ExistsFilter; +type BoolClauseFiltering = + | BoolClauseWithAnyCondition + | PinnedQuery + | T; + +enum Conditions { + Should = 'should', + Must = 'must', + MustNot = 'must_not', + Filter = 'filter', } -export interface MustClause { - must: Array | IDsClause | T>; + +/** + * Describe a specific BoolClause Condition with a BoolClauseFilter on it, such as: + * ``` + * { + * must : [ + * T, ... + * ] + * } + * ``` + */ +type BoolCondition = { + [c in C]: Array>; +}; + +/** + * Describe a Bool clause with a specific Condition, such as: + * ``` + * { + * // described by BoolClause + * bool: { + * // described by BoolCondition + * must: [ + * T, ... + * ] + * } + * } + * ``` + */ +interface BoolClause { + bool: BoolCondition; } -export interface BoolClause { - bool: MustClause | ShouldClause; + +/** + * Describe a Bool clause with mixed Conditions, such as: + * ``` + * { + * // described by BoolClause<...> + * bool: { + * // described by BoolCondition + * must : { + * ... + * }, + * // described by BoolCondition + * should : { + * ... + * } + * } + * } + * ``` + */ +type AnyBoolCondition = { + [Condition in Conditions]?: Array>; +}; + +/** + * Describe a Bool Condition with any Condition on it, so it can handle both: + * ``` + * { + * bool: { + * must : { + * ... + * } + * } + * } + * ``` + * + * and: + * + * ``` + * { + * bool: { + * must_not : { + * ... + * } + * } + * } + * ``` + */ +export interface BoolClauseWithAnyCondition { + bool: AnyBoolCondition; } + +/** + * Describe the various Bool Clause Conditions we support, as specified in the Conditions enum + */ +export type ShouldCondition = BoolClause; +export type MustCondition = BoolClause; +export type MustNotCondition = BoolClause; +export type FilterCondition = BoolClause; + export interface SortClause { _script: { type: string; @@ -39,6 +159,8 @@ export interface SortClause { }; }; } +export type SortOptions = string | SortClause | Array; + export interface ScriptClause { source: string; lang: string; @@ -46,18 +168,34 @@ export interface ScriptClause { [field: string]: string | number | Date; }; } -export interface UpdateByQuery { - query: BoolClause; - sort: SortClause; + +export interface UpdateByQuery { + query: PinnedQuery | BoolClauseWithAnyCondition; + sort: SortOptions; seq_no_primary_term: true; script: ScriptClause; } -export function shouldBeOneOf( - ...should: Array | IDsClause | T> -): { - bool: ShouldClause; -} { +export interface PinnedQuery { + pinned: PinnedClause; +} + +export interface PinnedClause { + ids: string[]; + organic: BoolClauseWithAnyCondition; +} + +export function matchesClauses( + ...clauses: Array> +): BoolClauseWithAnyCondition { + return { + bool: Object.assign({}, ...clauses.map(clause => clause.bool)), + }; +} + +export function shouldBeOneOf( + ...should: Array> +): ShouldCondition { return { bool: { should, @@ -65,11 +203,9 @@ export function shouldBeOneOf( }; } -export function mustBeAllOf( - ...must: Array | IDsClause | T> -): { - bool: MustClause; -} { +export function mustBeAllOf( + ...must: Array> +): MustCondition { return { bool: { must, @@ -77,14 +213,36 @@ export function mustBeAllOf( }; } -export function asUpdateByQuery({ +export function filterDownBy( + ...filter: Array> +): FilterCondition { + return { + bool: { + filter, + }, + }; +} + +export function asPinnedQuery( + ids: PinnedClause['ids'], + organic: PinnedClause['organic'] +): PinnedQuery { + return { + pinned: { + ids, + organic, + }, + }; +} + +export function asUpdateByQuery({ query, update, sort, }: { - query: BoolClause; - update: ScriptClause; - sort: SortClause; + query: UpdateByQuery['query']; + update: UpdateByQuery['script']; + sort: UpdateByQuery['sort']; }): UpdateByQuery { return { query, diff --git a/x-pack/plugins/task_manager/server/task_manager.ts b/x-pack/plugins/task_manager/server/task_manager.ts index c0baed3708a0a..93e98f33a30b0 100644 --- a/x-pack/plugins/task_manager/server/task_manager.ts +++ b/x-pack/plugins/task_manager/server/task_manager.ts @@ -48,11 +48,11 @@ import { createTaskPoller, PollingError, PollingErrorType } from './task_poller' import { TaskPool } from './task_pool'; import { TaskManagerRunner, TaskRunner } from './task_runner'; import { - FetchOpts, FetchResult, TaskStore, OwnershipClaimingOpts, ClaimOwnershipResult, + SearchOpts, } from './task_store'; import { identifyEsError } from './lib/identify_es_error'; import { ensureDeprecatedFieldsAreCorrected } from './lib/correct_deprecated_fields'; @@ -323,12 +323,12 @@ export class TaskManager { } /** - * Fetches a paginatable list of scheduled tasks. + * Fetches a list of scheduled tasks. * * @param opts - The query options used to filter tasks * @returns {Promise} */ - public async fetch(opts: FetchOpts): Promise { + public async fetch(opts: SearchOpts): Promise { await this.waitUntilStarted(); return this.store.fetch(opts); } diff --git a/x-pack/plugins/task_manager/server/task_store.test.ts b/x-pack/plugins/task_manager/server/task_store.test.ts index f47cc41c2d045..e6cce7a664d91 100644 --- a/x-pack/plugins/task_manager/server/task_store.test.ts +++ b/x-pack/plugins/task_manager/server/task_store.test.ts @@ -16,7 +16,7 @@ import { TaskStatus, TaskLifecycleResult, } from './task'; -import { FetchOpts, StoreOpts, OwnershipClaimingOpts, TaskStore } from './task_store'; +import { StoreOpts, OwnershipClaimingOpts, TaskStore, SearchOpts } from './task_store'; import { savedObjectsRepositoryMock } from '../../../../src/core/server/mocks'; import { SavedObjectsSerializer, @@ -175,7 +175,7 @@ describe('TaskStore', () => { }); describe('fetch', () => { - async function testFetch(opts?: FetchOpts, hits: any[] = []) { + async function testFetch(opts?: SearchOpts, hits: any[] = []) { const callCluster = sinon.spy(async (name: string, params?: any) => ({ hits: { hits } })); const store = new TaskStore({ index: 'tasky', @@ -203,7 +203,7 @@ describe('TaskStore', () => { expect(args).toMatchObject({ index: 'tasky', body: { - sort: [{ 'task.runAt': 'asc' }, { _id: 'desc' }], + sort: [{ 'task.runAt': 'asc' }], query: { term: { type: 'task' } }, }, }); @@ -226,122 +226,6 @@ describe('TaskStore', () => { }, }); }); - - test('sorts by id if custom sort does not have an id sort in it', async () => { - const { args } = await testFetch({ - sort: [{ 'task.taskType': 'desc' }], - }); - - expect(args).toMatchObject({ - body: { - sort: [{ 'task.taskType': 'desc' }, { _id: 'desc' }], - }, - }); - }); - - test('allows custom sort by id', async () => { - const { args } = await testFetch({ - sort: [{ _id: 'asc' }], - }); - - expect(args).toMatchObject({ - body: { - sort: [{ _id: 'asc' }], - }, - }); - }); - - test('allows specifying pagination', async () => { - const now = new Date(); - const searchAfter = [now, '143243sdafa32']; - const { args } = await testFetch({ - searchAfter, - }); - - expect(args).toMatchObject({ - body: { - search_after: searchAfter, - }, - }); - }); - - test('returns paginated tasks', async () => { - const runAt = new Date(); - const { result } = await testFetch(undefined, [ - { - _id: 'aaa', - _source: { - type: 'task', - task: { - runAt, - taskType: 'foo', - schedule: undefined, - attempts: 0, - status: 'idle', - params: '{ "hello": "world" }', - state: '{ "baby": "Henhen" }', - user: 'jimbo', - scope: ['reporting'], - }, - }, - sort: ['a', 1], - }, - { - _id: 'bbb', - _source: { - type: 'task', - task: { - runAt, - taskType: 'bar', - schedule: { interval: '5m' }, - attempts: 2, - status: 'running', - params: '{ "shazm": 1 }', - state: '{ "henry": "The 8th" }', - user: 'dabo', - scope: ['reporting', 'ceo'], - }, - }, - sort: ['b', 2], - }, - ]); - - expect(result).toEqual({ - docs: [ - { - attempts: 0, - id: 'aaa', - schedule: undefined, - params: { hello: 'world' }, - runAt, - scheduledAt: mockedDate, - scope: ['reporting'], - state: { baby: 'Henhen' }, - status: 'idle', - taskType: 'foo', - user: 'jimbo', - retryAt: undefined, - startedAt: undefined, - }, - { - attempts: 2, - id: 'bbb', - schedule: { interval: '5m' }, - params: { shazm: 1 }, - runAt, - scheduledAt: mockedDate, - scope: ['reporting', 'ceo'], - state: { henry: 'The 8th' }, - status: 'running', - taskType: 'bar', - user: 'dabo', - retryAt: undefined, - startedAt: undefined, - }, - ], - searchAfter: ['b', 2], - }); - }); }); describe('claimAvailableTasks', () => { @@ -450,65 +334,88 @@ describe('TaskStore', () => { must: [ { bool: { - should: [ + must: [ { bool: { - must: [ - { term: { 'task.status': 'idle' } }, - { range: { 'task.runAt': { lte: 'now' } } }, + should: [ + { + bool: { + must: [ + { term: { 'task.status': 'idle' } }, + { range: { 'task.runAt': { lte: 'now' } } }, + ], + }, + }, + { + bool: { + must: [ + { + bool: { + should: [ + { term: { 'task.status': 'running' } }, + { term: { 'task.status': 'claiming' } }, + ], + }, + }, + { range: { 'task.retryAt': { lte: 'now' } } }, + ], + }, + }, ], }, }, { bool: { - must: [ + should: [ + { exists: { field: 'task.schedule' } }, + { + bool: { + must: [ + { term: { 'task.taskType': 'foo' } }, + { + range: { + 'task.attempts': { + lt: maxAttempts, + }, + }, + }, + ], + }, + }, { bool: { - should: [ - { term: { 'task.status': 'running' } }, - { term: { 'task.status': 'claiming' } }, + must: [ + { term: { 'task.taskType': 'bar' } }, + { + range: { + 'task.attempts': { + lt: customMaxAttempts, + }, + }, + }, ], }, }, - { range: { 'task.retryAt': { lte: 'now' } } }, ], }, }, ], }, }, + ], + filter: [ { bool: { - should: [ - { exists: { field: 'task.schedule' } }, - { - bool: { - must: [ - { term: { 'task.taskType': 'foo' } }, - { - range: { - 'task.attempts': { - lt: maxAttempts, - }, - }, - }, - ], - }, - }, + must_not: [ { bool: { - must: [ - { term: { 'task.taskType': 'bar' } }, - { - range: { - 'task.attempts': { - lt: customMaxAttempts, - }, - }, - }, + should: [ + { term: { 'task.status': 'running' } }, + { term: { 'task.status': 'claiming' } }, ], }, }, + { range: { 'task.retryAt': { gt: 'now' } } }, ], }, }, @@ -562,96 +469,99 @@ describe('TaskStore', () => { { term: { type: 'task' } }, { bool: { - should: [ + must: [ { - bool: { - must: [ - { - bool: { - should: [ - { - bool: { - must: [ - { term: { 'task.status': 'idle' } }, - { range: { 'task.runAt': { lte: 'now' } } }, - ], - }, - }, - { - bool: { - must: [ - { - bool: { - should: [ - { term: { 'task.status': 'running' } }, - { term: { 'task.status': 'claiming' } }, - ], - }, + pinned: { + ids: [ + 'task:33c6977a-ed6d-43bd-98d9-3f827f7b7cd8', + 'task:a208b22c-14ec-4fb4-995f-d2ff7a3b03b8', + ], + organic: { + bool: { + must: [ + { + bool: { + should: [ + { + bool: { + must: [ + { term: { 'task.status': 'idle' } }, + { range: { 'task.runAt': { lte: 'now' } } }, + ], }, - { range: { 'task.retryAt': { lte: 'now' } } }, - ], - }, - }, - ], - }, - }, - { - bool: { - should: [ - { exists: { field: 'task.schedule' } }, - { - bool: { - must: [ - { term: { 'task.taskType': 'foo' } }, - { - range: { - 'task.attempts': { - lt: maxAttempts, + }, + { + bool: { + must: [ + { + bool: { + should: [ + { term: { 'task.status': 'running' } }, + { term: { 'task.status': 'claiming' } }, + ], + }, }, - }, + { range: { 'task.retryAt': { lte: 'now' } } }, + ], }, - ], - }, + }, + ], }, - { - bool: { - must: [ - { term: { 'task.taskType': 'bar' } }, - { - range: { - 'task.attempts': { - lt: customMaxAttempts, + }, + { + bool: { + should: [ + { exists: { field: 'task.schedule' } }, + { + bool: { + must: [ + { term: { 'task.taskType': 'foo' } }, + { + range: { + 'task.attempts': { + lt: maxAttempts, + }, + }, }, - }, + ], }, - ], - }, + }, + { + bool: { + must: [ + { term: { 'task.taskType': 'bar' } }, + { + range: { + 'task.attempts': { + lt: customMaxAttempts, + }, + }, + }, + ], + }, + }, + ], }, - ], - }, + }, + ], }, - ], + }, }, }, + ], + filter: [ { bool: { - must: [ + must_not: [ { bool: { should: [ - { term: { 'task.status': 'idle' } }, - { term: { 'task.status': 'failed' } }, - ], - }, - }, - { - ids: { - values: [ - 'task:33c6977a-ed6d-43bd-98d9-3f827f7b7cd8', - 'task:a208b22c-14ec-4fb4-995f-d2ff7a3b03b8', + { term: { 'task.status': 'running' } }, + { term: { 'task.status': 'claiming' } }, ], }, }, + { range: { 'task.retryAt': { gt: 'now' } } }, ], }, }, @@ -662,34 +572,26 @@ describe('TaskStore', () => { }, }); - expect(sort).toMatchObject({ - _script: { - type: 'number', - order: 'asc', - script: { - lang: 'painless', - source: ` -if(params.ids.contains(doc['_id'].value)){ - return 0; -} - + expect(sort).toMatchObject([ + '_score', + { + _script: { + type: 'number', + order: 'asc', + script: { + lang: 'painless', + source: ` if (doc['task.retryAt'].size()!=0) { return doc['task.retryAt'].value.toInstant().toEpochMilli(); } if (doc['task.runAt'].size()!=0) { return doc['task.runAt'].value.toInstant().toEpochMilli(); } - -`, - params: { - ids: [ - 'task:33c6977a-ed6d-43bd-98d9-3f827f7b7cd8', - 'task:a208b22c-14ec-4fb4-995f-d2ff7a3b03b8', - ], + `, }, }, }, - }); + ]); }); test('it claims tasks by setting their ownerId, status and retryAt', async () => { diff --git a/x-pack/plugins/task_manager/server/task_store.ts b/x-pack/plugins/task_manager/server/task_store.ts index f4695b152237a..4f2e97704941f 100644 --- a/x-pack/plugins/task_manager/server/task_store.ts +++ b/x-pack/plugins/task_manager/server/task_store.ts @@ -36,22 +36,23 @@ import { asUpdateByQuery, shouldBeOneOf, mustBeAllOf, - ExistsBoolClause, - TermBoolClause, - RangeBoolClause, - BoolClause, - IDsClause, + filterDownBy, + ExistsFilter, + TermFilter, + RangeFilter, + asPinnedQuery, + matchesClauses, } from './queries/query_clauses'; import { updateFields, IdleTaskWithExpiredRunAt, + InactiveTasks, RunningOrClaimingTaskWithExpiredRetryAt, TaskWithSchedule, taskWithLessThanMaxAttempts, SortByRunAtAndRetryAt, - taskWithIDsAndRunnableStatus, - sortByIdsThenByScheduling, + tasksClaimedByOwner, } from './queries/mark_available_tasks_as_claimed'; export interface StoreOpts { @@ -65,18 +66,13 @@ export interface StoreOpts { } export interface SearchOpts { - searchAfter?: any[]; - sort?: object | object[]; + sort?: string | object | object[]; query?: object; size?: number; seq_no_primary_term?: boolean; search_after?: any[]; } -export interface FetchOpts extends SearchOpts { - sort?: object[]; -} - export interface UpdateByQuerySearchOpts extends SearchOpts { script?: object; } @@ -92,7 +88,6 @@ export interface OwnershipClaimingOpts { } export interface FetchResult { - searchAfter: any[]; docs: ConcreteTaskInstance[]; } @@ -152,8 +147,8 @@ export class TaskStore { return this.events$; } - private emitEvent = (event: TaskClaim) => { - this.events$.next(event); + private emitEvents = (events: TaskClaim[]) => { + events.forEach(event => this.events$.next(event)); }; /** @@ -180,16 +175,16 @@ export class TaskStore { } /** - * Fetches a paginatable list of scheduled tasks. + * Fetches a list of scheduled tasks with default sorting. * * @param opts - The query options used to filter tasks */ - public async fetch(opts: FetchOpts = {}): Promise { - const sort = paginatableSort(opts.sort); + public async fetch({ sort = [{ 'task.runAt': 'asc' }], ...opts }: SearchOpts = {}): Promise< + FetchResult + > { return this.search({ + ...opts, sort, - search_after: opts.searchAfter, - query: opts.query, }); } @@ -211,28 +206,30 @@ export class TaskStore { this.serializer.generateRawId(undefined, 'task', id) ); - const claimedTasks = await this.markAvailableTasksAsClaimed( + const numberOfTasksClaimed = await this.markAvailableTasksAsClaimed( claimOwnershipUntil, claimTasksByIdWithRawIds, size ); const docs = - claimedTasks > 0 ? await this.sweepForClaimedTasks(claimTasksByIdWithRawIds, size) : []; + numberOfTasksClaimed > 0 + ? await this.sweepForClaimedTasks(claimTasksByIdWithRawIds, size) + : []; // emit success/fail events for claimed tasks by id if (claimTasksById && claimTasksById.length) { - docs.map(doc => asTaskClaimEvent(doc.id, asOk(doc))).forEach(this.emitEvent); + this.emitEvents(docs.map(doc => asTaskClaimEvent(doc.id, asOk(doc)))); - difference( - claimTasksById, - docs.map(doc => doc.id) - ) - .map(id => asTaskClaimEvent(id, asErr(new Error(`failed to claim task '${id}'`)))) - .forEach(this.emitEvent); + this.emitEvents( + difference( + claimTasksById, + docs.map(doc => doc.id) + ).map(id => asTaskClaimEvent(id, asErr(new Error(`failed to claim task '${id}'`)))) + ); } return { - claimedTasks, + claimedTasks: numberOfTasksClaimed, docs, }; }; @@ -247,7 +244,7 @@ export class TaskStore { // status running or claiming with a retryAt <= now. shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt), // Either task has a schedule or the attempts < the maximum configured - shouldBeOneOf( + shouldBeOneOf( TaskWithSchedule, ...Object.entries(this.definitions).map(([type, { maxAttempts }]) => taskWithLessThanMaxAttempts(type, maxAttempts || this.maxAttempts) @@ -255,36 +252,33 @@ export class TaskStore { ) ); - const { query, sort } = - claimTasksById && claimTasksById.length - ? { - query: shouldBeOneOf< - | ExistsBoolClause - | TermBoolClause - | RangeBoolClause - | BoolClause - >(queryForScheduledTasks, taskWithIDsAndRunnableStatus(claimTasksById)), - sort: sortByIdsThenByScheduling(claimTasksById), - } - : { - query: queryForScheduledTasks, - sort: SortByRunAtAndRetryAt, - }; - const { updated } = await this.updateByQuery( asUpdateByQuery({ - query, + query: matchesClauses( + mustBeAllOf( + claimTasksById && claimTasksById.length + ? asPinnedQuery(claimTasksById, queryForScheduledTasks) + : queryForScheduledTasks + ), + filterDownBy(InactiveTasks) + ), update: updateFields({ ownerId: this.taskManagerId, status: 'claiming', retryAt: claimOwnershipUntil, }), - sort, + sort: [ + // sort by score first, so the "pinned" Tasks are first + '_score', + // the nsort by other fields + SortByRunAtAndRetryAt, + ], }), { max_docs: size, } ); + return updated; } @@ -295,24 +289,14 @@ export class TaskStore { claimTasksById: OwnershipClaimingOpts['claimTasksById'], size: OwnershipClaimingOpts['size'] ): Promise { + const claimedTasksQuery = tasksClaimedByOwner(this.taskManagerId); const { docs } = await this.search({ - query: { - bool: { - must: [ - { - term: { - 'task.ownerId': this.taskManagerId, - }, - }, - { term: { 'task.status': 'claiming' } }, - ], - }, - }, - size, - sort: + query: claimTasksById && claimTasksById.length - ? sortByIdsThenByScheduling(claimTasksById) - : SortByRunAtAndRetryAt, + ? asPinnedQuery(claimTasksById, claimedTasksQuery) + : claimedTasksQuery, + size, + sort: SortByRunAtAndRetryAt, seq_no_primary_term: true, }); @@ -397,7 +381,6 @@ export class TaskStore { .map(doc => this.serializer.rawToSavedObject(doc)) .map(doc => omit(doc, 'namespace') as SavedObject) .map(savedObjectToConcreteTaskInstance), - searchAfter: (rawDocs.length && rawDocs[rawDocs.length - 1].sort) || [], }; } @@ -427,20 +410,6 @@ export class TaskStore { } } -function paginatableSort(sort: any[] = []) { - const sortById = { _id: 'desc' }; - - if (!sort.length) { - return [{ 'task.runAt': 'asc' }, sortById]; - } - - if (sort.find(({ _id }) => !!_id)) { - return sort; - } - - return [...sort, sortById]; -} - function taskInstanceToAttributes(doc: TaskInstance): SavedObjectAttributes { return { ...omit(doc, 'id', 'version'), diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b1aabe44433c4..8402092695590 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -530,7 +530,6 @@ "common.ui.vislib.colormaps.greysText": "グレー", "common.ui.vislib.colormaps.redsText": "赤", "common.ui.vislib.colormaps.yellowToRedText": "黄色から赤", - "common.ui.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます ({nr}).構成されている最高値は {max} です。", "common.ui.visualize.queryGeohashBounds.unableToGetBoundErrorTitle": "バウンドを取得できませんでした", "console.autocomplete.addMethodMetaText": "メソド", "console.consoleDisplayName": "コンソール", @@ -2591,6 +2590,7 @@ "kbnVislibVisTypes.editors.heatmap.basicSettingsTitle": "基本設定", "kbnVislibVisTypes.editors.heatmap.heatmapSettingsTitle": "ヒートマップ設定", "kbnVislibVisTypes.editors.heatmap.highlightLabel": "ハイライト範囲", + "kbnVislibVisTypes.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます ({nr}).構成されている最高値は {max} です。", "kbnVislibVisTypes.editors.heatmap.highlightLabelTooltip": "チャートのカーソルを当てた部分と凡例の対応するラベルをハイライトします。", "kbnVislibVisTypes.editors.pie.donutLabel": "ドーナッツ", "kbnVislibVisTypes.editors.pie.labelsSettingsTitle": "ラベル設定", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 5521e414c4270..f3af5ec10338c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -530,7 +530,6 @@ "common.ui.vislib.colormaps.greysText": "灰色", "common.ui.vislib.colormaps.redsText": "红色", "common.ui.vislib.colormaps.yellowToRedText": "黄到红", - "common.ui.vislib.heatmap.maxBucketsText": "定义了过多的序列 ({nr})。配置的最大值为 {max}。", "common.ui.visualize.queryGeohashBounds.unableToGetBoundErrorTitle": "无法获取边界", "console.autocomplete.addMethodMetaText": "方法", "console.consoleDisplayName": "控制台", @@ -2591,6 +2590,7 @@ "kbnVislibVisTypes.editors.heatmap.basicSettingsTitle": "基本设置", "kbnVislibVisTypes.editors.heatmap.heatmapSettingsTitle": "热图设置", "kbnVislibVisTypes.editors.heatmap.highlightLabel": "高亮范围", + "kbnVislibVisTypes.vislib.heatmap.maxBucketsText": "定义了过多的序列 ({nr})。配置的最大值为 {max}。", "kbnVislibVisTypes.editors.heatmap.highlightLabelTooltip": "高亮显示图表中鼠标悬停的范围以及图例中对应的标签。", "kbnVislibVisTypes.editors.pie.donutLabel": "圆环图", "kbnVislibVisTypes.editors.pie.labelsSettingsTitle": "标签设置", diff --git a/x-pack/test/api_integration/apis/siem/network_dns.ts b/x-pack/test/api_integration/apis/siem/network_dns.ts index 5de7ea3a67087..13e98f09d072b 100644 --- a/x-pack/test/api_integration/apis/siem/network_dns.ts +++ b/x-pack/test/api_integration/apis/siem/network_dns.ts @@ -30,7 +30,6 @@ export default function({ getService }: FtrProviderContext) { query: networkDnsQuery, variables: { defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - isDNSHistogram: false, inspect: false, isPtrIncluded: false, pagination: { @@ -66,7 +65,7 @@ export default function({ getService }: FtrProviderContext) { query: networkDnsQuery, variables: { defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - isDNSHistogram: false, + isDnsHistogram: false, inspect: false, isPtrIncluded: false, pagination: { diff --git a/x-pack/test/plugin_api_integration/plugins/task_manager/index.js b/x-pack/test/plugin_api_integration/plugins/task_manager/index.js index 50fb9571c2687..e5b645367b8b7 100644 --- a/x-pack/test/plugin_api_integration/plugins/task_manager/index.js +++ b/x-pack/test/plugin_api_integration/plugins/task_manager/index.js @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +const { DEFAULT_MAX_WORKERS } = require('../../../../plugins/task_manager/server/config.ts'); const { EventEmitter } = require('events'); import { initRoutes } from './init_routes'; @@ -16,6 +17,7 @@ const once = function(emitter, event) { export default function TaskTestingAPI(kibana) { const taskTestingEvents = new EventEmitter(); + taskTestingEvents.setMaxListeners(DEFAULT_MAX_WORKERS * 2); return new kibana.Plugin({ name: 'sampleTask', diff --git a/x-pack/test/plugin_api_integration/plugins/task_manager/init_routes.js b/x-pack/test/plugin_api_integration/plugins/task_manager/init_routes.js index c0dcd99525915..9e818f050c929 100644 --- a/x-pack/test/plugin_api_integration/plugins/task_manager/init_routes.js +++ b/x-pack/test/plugin_api_integration/plugins/task_manager/init_routes.js @@ -193,15 +193,44 @@ export function initRoutes(server, taskManager, legacyTaskManager, taskTestingEv }, }); + server.route({ + path: '/api/sample_tasks/task/{taskId}', + method: 'GET', + async handler(request) { + try { + return taskManager.fetch({ + query: { + bool: { + must: [ + { + ids: { + values: [`task:${request.params.taskId}`], + }, + }, + ], + }, + }, + }); + } catch (err) { + return err; + } + }, + }); + server.route({ path: '/api/sample_tasks', method: 'DELETE', async handler() { try { - const { docs: tasks } = await taskManager.fetch({ - query: taskManagerQuery, - }); - return Promise.all(tasks.map(task => taskManager.remove(task.id))); + let tasksFound = 0; + do { + const { docs: tasks } = await taskManager.fetch({ + query: taskManagerQuery, + }); + tasksFound = tasks.length; + await Promise.all(tasks.map(task => taskManager.remove(task.id))); + } while (tasksFound > 0); + return 'OK'; } catch (err) { return err; } diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js index 0b1c1cbb5af29..7ec0e9b5efa5b 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_manager_integration.js @@ -13,6 +13,13 @@ const { task: { properties: taskManagerIndexMapping }, } = require('../../../../legacy/plugins/task_manager/server/mappings.json'); +const { + DEFAULT_MAX_WORKERS, + DEFAULT_POLL_INTERVAL, +} = require('../../../../plugins/task_manager/server/config.ts'); + +const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); + export default function({ getService }) { const es = getService('legacyEs'); const log = getService('log'); @@ -22,11 +29,12 @@ export default function({ getService }) { const supertest = supertestAsPromised(url.format(config.get('servers.kibana'))); describe('scheduling and running tasks', () => { - beforeEach(() => - supertest - .delete('/api/sample_tasks') - .set('kbn-xsrf', 'xxx') - .expect(200) + beforeEach( + async () => + await supertest + .delete('/api/sample_tasks') + .set('kbn-xsrf', 'xxx') + .expect(200) ); beforeEach(async () => { @@ -56,11 +64,19 @@ export default function({ getService }) { .then(response => response.body); } - function historyDocs() { + function currentTask(task) { + return supertest + .get(`/api/sample_tasks/task/${task}`) + .send({ task }) + .expect(200) + .then(response => response.body.docs[0]); + } + + function historyDocs(taskId) { return es .search({ index: testHistoryIndex, - q: 'type:task', + q: taskId ? `taskId:${taskId}` : 'type:task', }) .then(result => result.hits.hits); } @@ -223,7 +239,7 @@ export default function({ getService }) { }); await retry.try(async () => { - expect((await historyDocs()).length).to.eql(1); + expect((await historyDocs(originalTask.id)).length).to.eql(1); const [task] = (await currentTasks()).docs; expect(task.attempts).to.eql(0); @@ -318,6 +334,81 @@ export default function({ getService }) { }); }); + it('should prioritize tasks which are called using runNow', async () => { + const originalTask = await scheduleTask({ + taskType: 'sampleTask', + schedule: { interval: `30m` }, + params: {}, + }); + + await retry.try(async () => { + const docs = await historyDocs(originalTask.id); + expect(docs.length).to.eql(1); + + const task = await currentTask(originalTask.id); + + expect(task.state.count).to.eql(1); + + // ensure this task shouldnt run for another half hour + expectReschedule(Date.parse(originalTask.runAt), task, 30 * 60000); + }); + + const taskToBeReleased = await scheduleTask({ + taskType: 'sampleTask', + params: { waitForEvent: 'releaseSingleTask' }, + }); + + await retry.try(async () => { + // wait for taskToBeReleased to stall + expect((await historyDocs(taskToBeReleased.id)).length).to.eql(1); + }); + + // schedule multiple tasks that should force + // Task Manager to use up its worker capacity + // causing tasks to pile up + await Promise.all( + _.times(DEFAULT_MAX_WORKERS + _.random(1, DEFAULT_MAX_WORKERS), () => + scheduleTask({ + taskType: 'sampleTask', + params: { + waitForEvent: 'releaseTheOthers', + }, + }) + ) + ); + + // we need to ensure that TM has a chance to fill its queue with the stalling tasks + await delay(DEFAULT_POLL_INTERVAL); + + // call runNow for our task + const runNowResult = runTaskNow({ + id: originalTask.id, + }); + + // we need to ensure that TM has a chance to push the runNow task into the queue + // before we release the stalled task, so lets give it a chance + await delay(DEFAULT_POLL_INTERVAL); + + // and release only one slot in our worker queue + await releaseTasksWaitingForEventToComplete('releaseSingleTask'); + + expect(await runNowResult).to.eql({ id: originalTask.id }); + + await retry.try(async () => { + const task = await currentTask(originalTask.id); + expect(task.state.count).to.eql(2); + }); + + // drain tasks, othrwise they'll keep Task Manager stalled + await retry.try(async () => { + await releaseTasksWaitingForEventToComplete('releaseTheOthers'); + const tasks = (await currentTasks()).docs.filter( + task => task.params.originalParams.waitForEvent === 'releaseTheOthers' + ); + expect(tasks.length).to.eql(0); + }); + }); + it('should return a task run error result when running a task now fails', async () => { const originalTask = await scheduleTask({ taskType: 'sampleTask', @@ -329,10 +420,7 @@ export default function({ getService }) { const docs = await historyDocs(); expect(docs.filter(taskDoc => taskDoc._source.taskId === originalTask.id).length).to.eql(1); - const [task] = (await currentTasks()).docs.filter( - taskDoc => taskDoc.id === originalTask.id - ); - + const task = await currentTask(originalTask.id); expect(task.state.count).to.eql(1); // ensure this task shouldnt run for another half hour @@ -364,9 +452,7 @@ export default function({ getService }) { (await historyDocs()).filter(taskDoc => taskDoc._source.taskId === originalTask.id).length ).to.eql(2); - const [task] = (await currentTasks()).docs.filter( - taskDoc => taskDoc.id === originalTask.id - ); + const task = await currentTask(originalTask.id); expect(task.attempts).to.eql(1); }); }); diff --git a/yarn.lock b/yarn.lock index 587af6ba2e99d..ce222e727d08e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16849,10 +16849,10 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -io-ts@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.0.1.tgz#1261c12f915c2f48d16393a36966636b48a45aa1" - integrity sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ== +io-ts@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.0.5.tgz#e6e3db9df8b047f9cbd6b69e7d2ad3e6437a0b13" + integrity sha512-pL7uUptryanI5Glv+GUv7xh+aLBjxGEDmLwmEYNSx0yOD3djK0Nw5Bt0N6BAkv9LadOUU7QKpRsLcqnTh3UlLA== ip-regex@^2.1.0: version "2.1.0"