;
```
Returns:
diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.md
index 7d9d47df544d06..c179e089d7cfd0 100644
--- a/docs/development/core/public/kibana-plugin-core-public.chromestart.md
+++ b/docs/development/core/public/kibana-plugin-core-public.chromestart.md
@@ -56,7 +56,7 @@ core.chrome.setHelpExtension(elem => {
| [getBrand$()](./kibana-plugin-core-public.chromestart.getbrand_.md) | Get an observable of the current brand information. |
| [getBreadcrumbs$()](./kibana-plugin-core-public.chromestart.getbreadcrumbs_.md) | Get an observable of the current list of breadcrumbs |
| [getHelpExtension$()](./kibana-plugin-core-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent |
-| [getIsCollapsed$()](./kibana-plugin-core-public.chromestart.getiscollapsed_.md) | Get an observable of the current collapsed state of the chrome. |
+| [getIsNavDrawerLocked$()](./kibana-plugin-core-public.chromestart.getisnavdrawerlocked_.md) | Get an observable of the current locked state of the nav drawer. |
| [getIsVisible$()](./kibana-plugin-core-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. |
| [removeApplicationClass(className)](./kibana-plugin-core-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass()
. If className is unknown it is ignored. |
| [setAppTitle(appTitle)](./kibana-plugin-core-public.chromestart.setapptitle.md) | Sets the current app's title |
@@ -65,6 +65,5 @@ core.chrome.setHelpExtension(elem => {
| [setBreadcrumbs(newBreadcrumbs)](./kibana-plugin-core-public.chromestart.setbreadcrumbs.md) | Override the current set of breadcrumbs |
| [setHelpExtension(helpExtension)](./kibana-plugin-core-public.chromestart.sethelpextension.md) | Override the current set of custom help content |
| [setHelpSupportUrl(url)](./kibana-plugin-core-public.chromestart.sethelpsupporturl.md) | Override the default support URL shown in the help menu |
-| [setIsCollapsed(isCollapsed)](./kibana-plugin-core-public.chromestart.setiscollapsed.md) | Set the collapsed state of the chrome navigation. |
| [setIsVisible(isVisible)](./kibana-plugin-core-public.chromestart.setisvisible.md) | Set the temporary visibility for the chrome. This does nothing if the chrome is hidden by default and should be used to hide the chrome for things like full-screen modes with an exit button. |
diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.setiscollapsed.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.setiscollapsed.md
deleted file mode 100644
index b1843ef326d961..00000000000000
--- a/docs/development/core/public/kibana-plugin-core-public.chromestart.setiscollapsed.md
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeStart](./kibana-plugin-core-public.chromestart.md) > [setIsCollapsed](./kibana-plugin-core-public.chromestart.setiscollapsed.md)
-
-## ChromeStart.setIsCollapsed() method
-
-Set the collapsed state of the chrome navigation.
-
-Signature:
-
-```typescript
-setIsCollapsed(isCollapsed: boolean): void;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| isCollapsed | boolean
| |
-
-Returns:
-
-`void`
-
diff --git a/docs/development/core/server/kibana-plugin-core-server.routeconfig.validate.md b/docs/development/core/server/kibana-plugin-core-server.routeconfig.validate.md
index 204d8a786fedef..3bbabc04f25000 100644
--- a/docs/development/core/server/kibana-plugin-core-server.routeconfig.validate.md
+++ b/docs/development/core/server/kibana-plugin-core-server.routeconfig.validate.md
@@ -14,7 +14,7 @@ validate: RouteValidatorFullConfig | false;
## Remarks
-You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { allowUnknowns: true })`;
+You \*must\* specify a validation schema to be able to read: - url path segments - request query - request body To opt out of validating the request, specify `validate: false`. In this case request params, query, and body will be \*\*empty\*\* objects and have no access to raw values. In some cases you may want to use another validation library. To do this, you need to instruct the `@kbn/config-schema` library to output \*\*non-validated values\*\* with setting schema as `schema.object({}, { unknowns: 'allow' })`;
## Example
@@ -49,7 +49,7 @@ router.get({
path: 'path/{id}',
validate: {
// handler has access to raw non-validated params in runtime
- params: schema.object({}, { allowUnknowns: true })
+ params: schema.object({}, { unknowns: 'allow' })
},
},
(context, req, res,) {
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
index e03072f9a41c36..7fd65e5db35f36 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md
@@ -44,8 +44,8 @@ esFilters: {
getPhraseFilterField: (filter: import("../common").PhraseFilter) => string;
getPhraseFilterValue: (filter: import("../common").PhraseFilter) => string | number | boolean;
getDisplayValueFromFilter: typeof getDisplayValueFromFilter;
- compareFilters: (first: import("../common").Filter | import("../common").Filter[], second: import("../common").Filter | import("../common").Filter[], comparatorOptions?: import("./query/filter_manager/lib/compare_filters").FilterCompareOptions) => boolean;
- COMPARE_ALL_OPTIONS: import("./query/filter_manager/lib/compare_filters").FilterCompareOptions;
+ compareFilters: (first: import("../common").Filter | import("../common").Filter[], second: import("../common").Filter | import("../common").Filter[], comparatorOptions?: import("../common").FilterCompareOptions) => boolean;
+ COMPARE_ALL_OPTIONS: import("../common").FilterCompareOptions;
generateFilters: typeof generateFilters;
onlyDisabledFiltersChanged: (newFilters?: import("../common").Filter[] | undefined, oldFilters?: import("../common").Filter[] | undefined) => boolean;
changeTimeFilter: typeof changeTimeFilter;
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.icancel.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.icancel.md
deleted file mode 100644
index 27141c68ae1a7c..00000000000000
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.icancel.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ICancel](./kibana-plugin-plugins-data-server.icancel.md)
-
-## ICancel type
-
-Signature:
-
-```typescript
-export declare type ICancel = (id: string) => Promise;
-```
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchcancel.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchcancel.md
new file mode 100644
index 00000000000000..99c30515e8da6a
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchcancel.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchCancel](./kibana-plugin-plugins-data-server.isearchcancel.md)
+
+## ISearchCancel type
+
+Signature:
+
+```typescript
+export declare type ISearchCancel = (id: string) => Promise;
+```
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
index 12d53f1a35ea0f..d179b9d9dcd824 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
@@ -60,16 +60,14 @@
| [esQuery](./kibana-plugin-plugins-data-server.esquery.md) | |
| [fieldFormats](./kibana-plugin-plugins-data-server.fieldformats.md) | |
| [indexPatterns](./kibana-plugin-plugins-data-server.indexpatterns.md) | |
-| [search](./kibana-plugin-plugins-data-server.search.md) | |
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md) | |
-| [ICancel](./kibana-plugin-plugins-data-server.icancel.md) | |
| [IFieldFormatsRegistry](./kibana-plugin-plugins-data-server.ifieldformatsregistry.md) | |
| [ISearch](./kibana-plugin-plugins-data-server.isearch.md) | |
-| [ParsedInterval](./kibana-plugin-plugins-data-server.parsedinterval.md) | |
+| [ISearchCancel](./kibana-plugin-plugins-data-server.isearchcancel.md) | |
| [TSearchStrategyProvider](./kibana-plugin-plugins-data-server.tsearchstrategyprovider.md) | Search strategy provider creates an instance of a search strategy with the request handler context bound to it. This way every search strategy can use whatever information they require from the request context. |
diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc
index 8586d26e9a07ad..6645f49029a516 100644
--- a/docs/settings/monitoring-settings.asciidoc
+++ b/docs/settings/monitoring-settings.asciidoc
@@ -20,9 +20,7 @@ which support the same values as <>.
To control how data is collected from your {es} nodes, you configure
{ref}/monitoring-settings.html[`xpack.monitoring.collection`
settings] in `elasticsearch.yml`. To control how monitoring data is collected
-from Logstash, you configure
-{logstash-ref}/monitoring-internal-collection.html#monitoring-settings[`xpack.monitoring` settings]
-in `logstash.yml`.
+from Logstash, configure monitoring settings in `logstash.yml`.
For more information, see
{ref}/monitor-elasticsearch-cluster.html[Monitor a cluster].
diff --git a/examples/alerting_example/README.md b/examples/alerting_example/README.md
new file mode 100644
index 00000000000000..bf963c64586d30
--- /dev/null
+++ b/examples/alerting_example/README.md
@@ -0,0 +1,5 @@
+## Alerting Example
+
+This example plugin shows you how to create a custom Alert Type, create alerts based on that type and corresponding UI for viewing the details of all the alerts within the custom plugin.
+
+To run this example, use the command `yarn start --run-examples`.
\ No newline at end of file
diff --git a/examples/alerting_example/common/constants.ts b/examples/alerting_example/common/constants.ts
new file mode 100644
index 00000000000000..5884eb32205195
--- /dev/null
+++ b/examples/alerting_example/common/constants.ts
@@ -0,0 +1,34 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export const ALERTING_EXAMPLE_APP_ID = 'AlertingExample';
+
+// always firing
+export const DEFAULT_INSTANCES_TO_GENERATE = 5;
+
+// Astros
+export enum Craft {
+ OuterSpace = 'Outer Space',
+ ISS = 'ISS',
+}
+export enum Operator {
+ AreAbove = 'Are above',
+ AreBelow = 'Are below',
+ AreExactly = 'Are exactly',
+}
diff --git a/examples/alerting_example/kibana.json b/examples/alerting_example/kibana.json
new file mode 100644
index 00000000000000..bcdb7c2f14a9c9
--- /dev/null
+++ b/examples/alerting_example/kibana.json
@@ -0,0 +1,10 @@
+{
+ "id": "alertingExample",
+ "version": "0.0.1",
+ "kibanaVersion": "kibana",
+ "configPath": ["alerting_example"],
+ "server": true,
+ "ui": true,
+ "requiredPlugins": ["triggers_actions_ui", "charts", "data", "alerting", "actions"],
+ "optionalPlugins": []
+}
diff --git a/examples/alerting_example/package.json b/examples/alerting_example/package.json
new file mode 100644
index 00000000000000..96187d847c1c41
--- /dev/null
+++ b/examples/alerting_example/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "alerting_example",
+ "version": "1.0.0",
+ "main": "target/examples/alerting_example",
+ "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/examples/alerting_example/public/alert_types/always_firing.tsx b/examples/alerting_example/public/alert_types/always_firing.tsx
new file mode 100644
index 00000000000000..a62a24365ea3f9
--- /dev/null
+++ b/examples/alerting_example/public/alert_types/always_firing.tsx
@@ -0,0 +1,82 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { Fragment } from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiFieldNumber, EuiFormRow } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { AlertTypeModel } from '../../../../x-pack/plugins/triggers_actions_ui/public';
+import { DEFAULT_INSTANCES_TO_GENERATE } from '../../common/constants';
+
+interface AlwaysFiringParamsProps {
+ alertParams: { instances?: number };
+ setAlertParams: (property: string, value: any) => void;
+ errors: { [key: string]: string[] };
+}
+
+export function getAlertType(): AlertTypeModel {
+ return {
+ id: 'example.always-firing',
+ name: 'Always Fires',
+ iconClass: 'bolt',
+ alertParamsExpression: AlwaysFiringExpression,
+ validate: (alertParams: AlwaysFiringParamsProps['alertParams']) => {
+ const { instances } = alertParams;
+ const validationResult = {
+ errors: {
+ instances: new Array(),
+ },
+ };
+ if (instances && instances < 0) {
+ validationResult.errors.instances.push(
+ i18n.translate('AlertingExample.addAlert.error.invalidRandomInstances', {
+ defaultMessage: 'instances must be equal or greater than zero.',
+ })
+ );
+ }
+ return validationResult;
+ },
+ };
+}
+
+export const AlwaysFiringExpression: React.FunctionComponent = ({
+ alertParams,
+ setAlertParams,
+}) => {
+ const { instances = DEFAULT_INSTANCES_TO_GENERATE } = alertParams;
+ return (
+
+
+
+
+ {
+ setAlertParams('instances', event.target.valueAsNumber);
+ }}
+ />
+
+
+
+
+ );
+};
diff --git a/examples/alerting_example/public/alert_types/astros.tsx b/examples/alerting_example/public/alert_types/astros.tsx
new file mode 100644
index 00000000000000..9bda7da6f140dd
--- /dev/null
+++ b/examples/alerting_example/public/alert_types/astros.tsx
@@ -0,0 +1,277 @@
+/*
+ * 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, useEffect, Fragment } from 'react';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPopover,
+ EuiFieldNumber,
+ EuiPopoverTitle,
+ EuiSelect,
+ EuiCallOut,
+ EuiExpression,
+ EuiTextColor,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { flatten } from 'lodash';
+import { ALERTING_EXAMPLE_APP_ID, Craft, Operator } from '../../common/constants';
+import { SanitizedAlert } from '../../../../x-pack/plugins/alerting/common';
+import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerting/public';
+import { AlertTypeModel } from '../../../../x-pack/plugins/triggers_actions_ui/public';
+
+export function registerNavigation(alerting: AlertingSetup) {
+ alerting.registerNavigation(
+ ALERTING_EXAMPLE_APP_ID,
+ 'example.people-in-space',
+ (alert: SanitizedAlert) => `/astros/${alert.id}`
+ );
+}
+
+interface PeopleinSpaceParamsProps {
+ alertParams: { outerSpaceCapacity?: number; craft?: string; op?: string };
+ setAlertParams: (property: string, value: any) => void;
+ errors: { [key: string]: string[] };
+}
+
+function isValueInEnum(enumeratin: Record, value: any): boolean {
+ return !!Object.values(enumeratin).find(enumVal => enumVal === value);
+}
+
+export function getAlertType(): AlertTypeModel {
+ return {
+ id: 'example.people-in-space',
+ name: 'People Are In Space Right Now',
+ iconClass: 'globe',
+ alertParamsExpression: PeopleinSpaceExpression,
+ validate: (alertParams: PeopleinSpaceParamsProps['alertParams']) => {
+ const { outerSpaceCapacity, craft, op } = alertParams;
+
+ const validationResult = {
+ errors: {
+ outerSpaceCapacity: new Array(),
+ craft: new Array(),
+ },
+ };
+ if (!isValueInEnum(Craft, craft)) {
+ validationResult.errors.craft.push(
+ i18n.translate('AlertingExample.addAlert.error.invalidCraft', {
+ defaultMessage: 'You must choose one of the following Craft: {crafts}',
+ values: {
+ crafts: Object.values(Craft).join(', '),
+ },
+ })
+ );
+ }
+ if (!(typeof outerSpaceCapacity === 'number' && outerSpaceCapacity >= 0)) {
+ validationResult.errors.outerSpaceCapacity.push(
+ i18n.translate('AlertingExample.addAlert.error.invalidOuterSpaceCapacity', {
+ defaultMessage: 'outerSpaceCapacity must be a number greater than or equal to zero.',
+ })
+ );
+ }
+ if (!isValueInEnum(Operator, op)) {
+ validationResult.errors.outerSpaceCapacity.push(
+ i18n.translate('AlertingExample.addAlert.error.invalidCraft', {
+ defaultMessage: 'You must choose one of the following Operator: {crafts}',
+ values: {
+ crafts: Object.values(Operator).join(', '),
+ },
+ })
+ );
+ }
+
+ return validationResult;
+ },
+ };
+}
+
+export const PeopleinSpaceExpression: React.FunctionComponent = ({
+ alertParams,
+ setAlertParams,
+ errors,
+}) => {
+ const { outerSpaceCapacity = 0, craft = Craft.OuterSpace, op = Operator.AreAbove } = alertParams;
+
+ // store defaults
+ useEffect(() => {
+ if (outerSpaceCapacity !== alertParams.outerSpaceCapacity) {
+ setAlertParams('outerSpaceCapacity', outerSpaceCapacity);
+ }
+ if (craft !== alertParams.craft) {
+ setAlertParams('craft', craft);
+ }
+ if (op !== alertParams.op) {
+ setAlertParams('op', op);
+ }
+ }, [alertParams, craft, op, outerSpaceCapacity, setAlertParams]);
+
+ const [craftTrigger, setCraftTrigger] = useState<{ craft: string; isOpen: boolean }>({
+ craft,
+ isOpen: false,
+ });
+ const [outerSpaceCapacityTrigger, setOuterSpaceCapacity] = useState<{
+ outerSpaceCapacity: number;
+ op: string;
+ isOpen: boolean;
+ }>({
+ outerSpaceCapacity,
+ op,
+ isOpen: false,
+ });
+
+ const errorsCallout = flatten(
+ Object.entries(errors).map(([field, errs]: [string, string[]]) =>
+ errs.map(e => (
+
+ {field}: `: ${errs}`
+
+ ))
+ )
+ );
+
+ return (
+
+ {errorsCallout.length ? (
+
+ {errorsCallout}
+
+ ) : (
+
+ )}
+
+
+ {
+ setCraftTrigger({
+ ...craftTrigger,
+ isOpen: true,
+ });
+ }}
+ />
+ }
+ isOpen={craftTrigger.isOpen}
+ closePopover={() => {
+ setCraftTrigger({
+ ...craftTrigger,
+ isOpen: false,
+ });
+ }}
+ ownFocus
+ panelPaddingSize="s"
+ anchorPosition="downLeft"
+ >
+
+ When the People in
+ {
+ setAlertParams('craft', event.target.value);
+ setCraftTrigger({
+ craft: event.target.value,
+ isOpen: false,
+ });
+ }}
+ options={[
+ { value: Craft.OuterSpace, text: 'Outer Space' },
+ { value: Craft.ISS, text: 'the International Space Station' },
+ ]}
+ />
+
+
+
+
+
+ {
+ setOuterSpaceCapacity({
+ ...outerSpaceCapacityTrigger,
+ isOpen: true,
+ });
+ }}
+ />
+ }
+ isOpen={outerSpaceCapacityTrigger.isOpen}
+ closePopover={() => {
+ setOuterSpaceCapacity({
+ ...outerSpaceCapacityTrigger,
+ isOpen: false,
+ });
+ }}
+ ownFocus
+ panelPaddingSize="s"
+ anchorPosition="downLeft"
+ >
+
+
+
+ {
+ setAlertParams('op', event.target.value);
+ setOuterSpaceCapacity({
+ ...outerSpaceCapacityTrigger,
+ op: event.target.value,
+ isOpen: false,
+ });
+ }}
+ options={[
+ { value: Operator.AreAbove, text: 'Are above' },
+ { value: Operator.AreBelow, text: 'Are below' },
+ { value: Operator.AreExactly, text: 'Are exactly' },
+ ]}
+ />
+
+
+
+ {
+ setAlertParams('outerSpaceCapacity', event.target.valueAsNumber);
+ setOuterSpaceCapacity({
+ ...outerSpaceCapacityTrigger,
+ outerSpaceCapacity: event.target.valueAsNumber,
+ isOpen: false,
+ });
+ }}
+ />
+
+
+
+
+
+
+
+ );
+};
diff --git a/examples/alerting_example/public/alert_types/index.ts b/examples/alerting_example/public/alert_types/index.ts
new file mode 100644
index 00000000000000..96d9c09d15836f
--- /dev/null
+++ b/examples/alerting_example/public/alert_types/index.ts
@@ -0,0 +1,33 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { registerNavigation as registerPeopleInSpaceNavigation } from './astros';
+import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
+import { SanitizedAlert } from '../../../../x-pack/plugins/alerting/common';
+import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerting/public';
+
+export function registerNavigation(alerting: AlertingSetup) {
+ // register default navigation
+ alerting.registerDefaultNavigation(
+ ALERTING_EXAMPLE_APP_ID,
+ (alert: SanitizedAlert) => `/alert/${alert.id}`
+ );
+
+ registerPeopleInSpaceNavigation(alerting);
+}
diff --git a/examples/alerting_example/public/application.tsx b/examples/alerting_example/public/application.tsx
new file mode 100644
index 00000000000000..d71db92d3d421a
--- /dev/null
+++ b/examples/alerting_example/public/application.tsx
@@ -0,0 +1,108 @@
+/*
+ * 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 ReactDOM from 'react-dom';
+import { BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom';
+import { EuiPage } from '@elastic/eui';
+import {
+ AppMountParameters,
+ CoreStart,
+ IUiSettingsClient,
+ ToastsSetup,
+} from '../../../src/core/public';
+import { DataPublicPluginStart } from '../../../src/plugins/data/public';
+import { ChartsPluginStart } from '../../../src/plugins/charts/public';
+
+import { Page } from './components/page';
+import { DocumentationPage } from './components/documentation';
+import { ViewAlertPage } from './components/view_alert';
+import { TriggersAndActionsUIPublicPluginStart } from '../../../x-pack/plugins/triggers_actions_ui/public';
+import { AlertingExamplePublicStartDeps } from './plugin';
+import { ViewPeopleInSpaceAlertPage } from './components/view_astros_alert';
+
+export interface AlertingExampleComponentParams {
+ application: CoreStart['application'];
+ http: CoreStart['http'];
+ basename: string;
+ triggers_actions_ui: TriggersAndActionsUIPublicPluginStart;
+ data: DataPublicPluginStart;
+ charts: ChartsPluginStart;
+ uiSettings: IUiSettingsClient;
+ toastNotifications: ToastsSetup;
+}
+
+const AlertingExampleApp = (deps: AlertingExampleComponentParams) => {
+ const { basename, http } = deps;
+ return (
+
+
+ (
+
+
+
+ )}
+ />
+ ) => {
+ return (
+
+
+
+ );
+ }}
+ />
+ ) => {
+ return (
+
+
+
+ );
+ }}
+ />
+
+
+ );
+};
+
+export const renderApp = (
+ { application, notifications, http, uiSettings }: CoreStart,
+ deps: AlertingExamplePublicStartDeps,
+ { appBasePath, element }: AppMountParameters
+) => {
+ ReactDOM.render(
+ ,
+ element
+ );
+
+ return () => ReactDOM.unmountComponentAtNode(element);
+};
diff --git a/examples/alerting_example/public/components/create_alert.tsx b/examples/alerting_example/public/components/create_alert.tsx
new file mode 100644
index 00000000000000..65b8a9412dcda6
--- /dev/null
+++ b/examples/alerting_example/public/components/create_alert.tsx
@@ -0,0 +1,72 @@
+/*
+ * 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 { EuiIcon, EuiFlexItem, EuiCard, EuiFlexGroup } from '@elastic/eui';
+
+import {
+ AlertsContextProvider,
+ AlertAdd,
+} from '../../../../x-pack/plugins/triggers_actions_ui/public';
+import { AlertingExampleComponentParams } from '../application';
+import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
+
+export const CreateAlert = ({
+ http,
+ triggers_actions_ui,
+ charts,
+ uiSettings,
+ data,
+ toastNotifications,
+}: AlertingExampleComponentParams) => {
+ const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState(false);
+
+ return (
+
+
+ }
+ title={`Create Alert`}
+ description="Create an new Alert based on one of our example Alert Types ."
+ onClick={() => setAlertFlyoutVisibility(true)}
+ />
+
+
+
+
+
+
+
+ );
+};
diff --git a/examples/alerting_example/public/components/documentation.tsx b/examples/alerting_example/public/components/documentation.tsx
new file mode 100644
index 00000000000000..17cc34959b0108
--- /dev/null
+++ b/examples/alerting_example/public/components/documentation.tsx
@@ -0,0 +1,67 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React from 'react';
+
+import {
+ EuiText,
+ EuiPageBody,
+ EuiPageContent,
+ EuiPageContentBody,
+ EuiPageContentHeader,
+ EuiPageContentHeaderSection,
+ EuiPageHeader,
+ EuiPageHeaderSection,
+ EuiTitle,
+ EuiSpacer,
+} from '@elastic/eui';
+import { CreateAlert } from './create_alert';
+import { AlertingExampleComponentParams } from '../application';
+
+export const DocumentationPage = (deps: AlertingExampleComponentParams) => (
+
+
+
+
+ Welcome to the Alerting plugin example
+
+
+
+
+
+
+
+ Documentation links
+
+
+
+
+
+ Plugin Structure
+
+ This example solution has both `server` and a `public` plugins. The `server` handles
+ registration of example the AlertTypes, while the `public` handles creation of, and
+ navigation for, these alert types.
+
+
+
+
+
+
+
+);
diff --git a/examples/alerting_example/public/components/page.tsx b/examples/alerting_example/public/components/page.tsx
new file mode 100644
index 00000000000000..99076c7ddcedf5
--- /dev/null
+++ b/examples/alerting_example/public/components/page.tsx
@@ -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 React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import {
+ EuiPageBody,
+ EuiPageContent,
+ EuiPageContentBody,
+ EuiPageHeader,
+ EuiPageHeaderSection,
+ EuiTitle,
+ EuiBreadcrumbs,
+ EuiSpacer,
+} from '@elastic/eui';
+
+type PageProps = RouteComponentProps & {
+ title: string;
+ children: React.ReactNode;
+ crumb?: string;
+ isHome?: boolean;
+};
+
+export const Page = withRouter(({ title, crumb, children, isHome = false, history }: PageProps) => {
+ const breadcrumbs: Array<{
+ text: string;
+ onClick?: () => void;
+ }> = [
+ {
+ text: crumb ?? title,
+ },
+ ];
+ if (!isHome) {
+ breadcrumbs.splice(0, 0, {
+ text: 'Home',
+ onClick: () => {
+ history.push(`/`);
+ },
+ });
+ }
+ return (
+
+
+
+
+ {title}
+
+
+
+
+
+
+ {children}
+
+
+ );
+});
diff --git a/examples/alerting_example/public/components/view_alert.tsx b/examples/alerting_example/public/components/view_alert.tsx
new file mode 100644
index 00000000000000..c1b65eb92edc59
--- /dev/null
+++ b/examples/alerting_example/public/components/view_alert.tsx
@@ -0,0 +1,116 @@
+/*
+ * 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, useEffect, Fragment } from 'react';
+
+import {
+ EuiText,
+ EuiLoadingKibana,
+ EuiCallOut,
+ EuiTextColor,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ EuiCodeBlock,
+ EuiSpacer,
+} from '@elastic/eui';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+import { CoreStart } from 'kibana/public';
+import { isEmpty } from 'lodash';
+import { Alert, AlertTaskState } from '../../../../x-pack/plugins/alerting/common';
+import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
+
+type Props = RouteComponentProps & {
+ http: CoreStart['http'];
+ id: string;
+};
+export const ViewAlertPage = withRouter(({ http, id }: Props) => {
+ const [alert, setAlert] = useState(null);
+ const [alertState, setAlertState] = useState(null);
+
+ useEffect(() => {
+ if (!alert) {
+ http.get(`/api/alert/${id}`).then(setAlert);
+ }
+ if (!alertState) {
+ http.get(`/api/alert/${id}/state`).then(setAlertState);
+ }
+ }, [alert, alertState, http, id]);
+
+ return alert && alertState ? (
+
+
+
+ This is a generic view for all Alerts created by the
+ {ALERTING_EXAMPLE_APP_ID}
+ plugin.
+
+
+ You are now viewing the {`${alert.name}`}
+ Alert, whose ID is {`${alert.id}`} .
+
+
+ Its AlertType is {`${alert.alertTypeId}`} and
+ its scheduled to run at an interval of
+ {`${alert.schedule.interval}`} .
+
+
+
+
+ Alert Instances
+
+ {isEmpty(alertState.alertInstances) ? (
+
+ This Alert doesn't have any active alert instances at the moment.
+
+ ) : (
+
+
+
+ Bellow are the active Alert Instances which were activated on the alerts last run.
+
+ For each instance id you can see its current state in JSON format.
+
+
+
+
+ {Object.entries(alertState.alertInstances ?? {}).map(([instance, { state }]) => (
+
+ {instance}
+
+
+ {`${JSON.stringify(state)}`}
+
+
+
+ ))}
+
+
+ )}
+
+ ) : (
+
+ );
+});
diff --git a/examples/alerting_example/public/components/view_astros_alert.tsx b/examples/alerting_example/public/components/view_astros_alert.tsx
new file mode 100644
index 00000000000000..db93d8f54924dc
--- /dev/null
+++ b/examples/alerting_example/public/components/view_astros_alert.tsx
@@ -0,0 +1,123 @@
+/*
+ * 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, useEffect, Fragment } from 'react';
+
+import {
+ EuiText,
+ EuiLoadingKibana,
+ EuiCallOut,
+ EuiTextColor,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ EuiSpacer,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiStat,
+} from '@elastic/eui';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+import { CoreStart } from 'kibana/public';
+import { isEmpty } from 'lodash';
+import { Alert, AlertTaskState } from '../../../../x-pack/plugins/alerting/common';
+import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
+
+type Props = RouteComponentProps & {
+ http: CoreStart['http'];
+ id: string;
+};
+
+function hasCraft(state: any): state is { craft: string } {
+ return state && state.craft;
+}
+export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
+ const [alert, setAlert] = useState(null);
+ const [alertState, setAlertState] = useState(null);
+
+ useEffect(() => {
+ if (!alert) {
+ http.get(`/api/alert/${id}`).then(setAlert);
+ }
+ if (!alertState) {
+ http.get(`/api/alert/${id}/state`).then(setAlertState);
+ }
+ }, [alert, alertState, http, id]);
+
+ return alert && alertState ? (
+
+
+
+ This is a specific view for all
+ example.people-in-space Alerts created by
+ the
+ {ALERTING_EXAMPLE_APP_ID}
+ plugin.
+
+
+
+
+ Alert Instances
+
+ {isEmpty(alertState.alertInstances) ? (
+
+
+ The people in {alert.params.craft} at the moment are not {alert.params.op}{' '}
+ {alert.params.outerSpaceCapacity}
+
+
+ ) : (
+
+
+
+ The alert has been triggered because the people in {alert.params.craft} at the moment{' '}
+ {alert.params.op} {alert.params.outerSpaceCapacity}
+
+
+
+
+
+
+
+
+
+
+ {Object.entries(alertState.alertInstances ?? {}).map(
+ ([instance, { state }], index) => (
+
+ {instance}
+
+ {hasCraft(state) ? state.craft : 'Unknown Craft'}
+
+
+ )
+ )}
+
+
+
+
+
+ )}
+
+ ) : (
+
+ );
+});
diff --git a/src/legacy/ui/public/indices/index.js b/examples/alerting_example/public/index.ts
similarity index 81%
rename from src/legacy/ui/public/indices/index.js
rename to examples/alerting_example/public/index.ts
index c1646bd66e3678..4a2bfc79903c33 100644
--- a/src/legacy/ui/public/indices/index.js
+++ b/examples/alerting_example/public/index.ts
@@ -17,10 +17,6 @@
* under the License.
*/
-export { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from './constants';
+import { AlertingExamplePlugin } from './plugin';
-export {
- indexNameBeginsWithPeriod,
- findIllegalCharactersInIndexName,
- indexNameContainsSpaces,
-} from './validate';
+export const plugin = () => new AlertingExamplePlugin();
diff --git a/examples/alerting_example/public/plugin.tsx b/examples/alerting_example/public/plugin.tsx
new file mode 100644
index 00000000000000..299806d393446e
--- /dev/null
+++ b/examples/alerting_example/public/plugin.tsx
@@ -0,0 +1,70 @@
+/*
+ * 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, AppMountParameters, CoreStart } from 'kibana/public';
+import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerting/public';
+import { ChartsPluginStart } from '../../../src/plugins/charts/public';
+import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public';
+import { DataPublicPluginStart } from '../../../src/plugins/data/public';
+import { getAlertType as getAlwaysFiringAlertType } from './alert_types/always_firing';
+import { getAlertType as getPeopleInSpaceAlertType } from './alert_types/astros';
+import { registerNavigation } from './alert_types';
+
+export type Setup = void;
+export type Start = void;
+
+export interface AlertingExamplePublicSetupDeps {
+ alerting: AlertingSetup;
+ triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
+}
+
+export interface AlertingExamplePublicStartDeps {
+ alerting: AlertingSetup;
+ triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
+ charts: ChartsPluginStart;
+ data: DataPublicPluginStart;
+}
+
+export class AlertingExamplePlugin implements Plugin {
+ public setup(
+ core: CoreSetup,
+ { alerting, triggers_actions_ui }: AlertingExamplePublicSetupDeps
+ ) {
+ core.application.register({
+ id: 'AlertingExample',
+ title: 'Alerting Example',
+ async mount(params: AppMountParameters) {
+ const [coreStart, depsStart]: [
+ CoreStart,
+ AlertingExamplePublicStartDeps
+ ] = await core.getStartServices();
+ const { renderApp } = await import('./application');
+ return renderApp(coreStart, depsStart, params);
+ },
+ });
+
+ triggers_actions_ui.alertTypeRegistry.register(getAlwaysFiringAlertType());
+ triggers_actions_ui.alertTypeRegistry.register(getPeopleInSpaceAlertType());
+
+ registerNavigation(alerting);
+ }
+
+ public start() {}
+ public stop() {}
+}
diff --git a/examples/alerting_example/server/alert_types/always_firing.ts b/examples/alerting_example/server/alert_types/always_firing.ts
new file mode 100644
index 00000000000000..f0553ad5ebebd1
--- /dev/null
+++ b/examples/alerting_example/server/alert_types/always_firing.ts
@@ -0,0 +1,46 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import uuid from 'uuid';
+import { range } from 'lodash';
+import { AlertType } from '../../../../x-pack/plugins/alerting/server';
+import { DEFAULT_INSTANCES_TO_GENERATE } from '../../common/constants';
+
+export const alertType: AlertType = {
+ id: 'example.always-firing',
+ name: 'Always firing',
+ actionGroups: [{ id: 'default', name: 'default' }],
+ defaultActionGroupId: 'default',
+ async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE }, state }) {
+ const count = (state.count ?? 0) + 1;
+
+ range(instances)
+ .map(() => ({ id: uuid.v4() }))
+ .forEach((instance: { id: string }) => {
+ services
+ .alertInstanceFactory(instance.id)
+ .replaceState({ triggerdOnCycle: count })
+ .scheduleActions('default');
+ });
+
+ return {
+ count,
+ };
+ },
+};
diff --git a/examples/alerting_example/server/alert_types/astros.ts b/examples/alerting_example/server/alert_types/astros.ts
new file mode 100644
index 00000000000000..3a53f85e6a266b
--- /dev/null
+++ b/examples/alerting_example/server/alert_types/astros.ts
@@ -0,0 +1,82 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import axios from 'axios';
+import { AlertType } from '../../../../x-pack/plugins/alerting/server';
+import { Operator, Craft } from '../../common/constants';
+
+interface PeopleInSpace {
+ people: Array<{
+ craft: string;
+ name: string;
+ }>;
+ number: number;
+}
+
+function getOperator(op: string) {
+ switch (op) {
+ case Operator.AreAbove:
+ return (left: number, right: number) => left > right;
+ case Operator.AreBelow:
+ return (left: number, right: number) => left < right;
+ case Operator.AreExactly:
+ return (left: number, right: number) => left === right;
+ default:
+ return () => {
+ throw new Error(
+ `Invalid Operator "${op}" [${Operator.AreAbove},${Operator.AreBelow},${Operator.AreExactly}]`
+ );
+ };
+ }
+}
+
+function getCraftFilter(craft: string) {
+ return (person: { craft: string; name: string }) =>
+ craft === Craft.OuterSpace ? true : craft === person.craft;
+}
+
+export const alertType: AlertType = {
+ id: 'example.people-in-space',
+ name: 'People In Space Right Now',
+ actionGroups: [{ id: 'default', name: 'default' }],
+ defaultActionGroupId: 'default',
+ async executor({ services, params }) {
+ const { outerSpaceCapacity, craft: craftToTriggerBy, op } = params;
+
+ const response = await axios.get('http://api.open-notify.org/astros.json');
+ const {
+ data: { number: peopleInSpace, people = [] },
+ } = response;
+
+ const peopleInCraft = people.filter(getCraftFilter(craftToTriggerBy));
+
+ if (getOperator(op)(peopleInCraft.length, outerSpaceCapacity)) {
+ peopleInCraft.forEach(({ craft, name }) => {
+ services
+ .alertInstanceFactory(name)
+ .replaceState({ craft })
+ .scheduleActions('default');
+ });
+ }
+
+ return {
+ peopleInSpace,
+ };
+ },
+};
diff --git a/examples/alerting_example/server/index.ts b/examples/alerting_example/server/index.ts
new file mode 100644
index 00000000000000..32e9b181ebb544
--- /dev/null
+++ b/examples/alerting_example/server/index.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 { PluginInitializer } from 'kibana/server';
+import { AlertingExamplePlugin } from './plugin';
+
+export const plugin: PluginInitializer = () => new AlertingExamplePlugin();
diff --git a/src/legacy/ui/public/chrome/services/global_nav_state.js b/examples/alerting_example/server/plugin.ts
similarity index 53%
rename from src/legacy/ui/public/chrome/services/global_nav_state.js
rename to examples/alerting_example/server/plugin.ts
index 5a67806852fe81..b5dabe51e86854 100644
--- a/src/legacy/ui/public/chrome/services/global_nav_state.js
+++ b/examples/alerting_example/server/plugin.ts
@@ -17,29 +17,23 @@
* under the License.
*/
-import { distinctUntilChanged } from 'rxjs/operators';
-import { npStart } from 'ui/new_platform';
-import { uiModules } from '../../modules';
+import { Plugin, CoreSetup } from 'kibana/server';
+import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerting/server';
-const newPlatformChrome = npStart.core.chrome;
+import { alertType as alwaysFiringAlert } from './alert_types/always_firing';
+import { alertType as peopleInSpaceAlert } from './alert_types/astros';
-uiModules.get('kibana').service('globalNavState', $rootScope => {
- let isOpen = false;
- newPlatformChrome
- .getIsCollapsed$()
- .pipe(distinctUntilChanged())
- .subscribe(isCollapsed => {
- $rootScope.$evalAsync(() => {
- isOpen = !isCollapsed;
- $rootScope.$broadcast('globalNavState:change');
- });
- });
+// this plugin's dependendencies
+export interface AlertingExampleDeps {
+ alerting: AlertingSetup;
+}
- return {
- isOpen: () => isOpen,
+export class AlertingExamplePlugin implements Plugin {
+ public setup(core: CoreSetup, { alerting }: AlertingExampleDeps) {
+ alerting.registerType(alwaysFiringAlert);
+ alerting.registerType(peopleInSpaceAlert);
+ }
- setOpen: newValue => {
- newPlatformChrome.setIsCollapsed(!newValue);
- },
- };
-});
+ public start() {}
+ public stop() {}
+}
diff --git a/examples/alerting_example/tsconfig.json b/examples/alerting_example/tsconfig.json
new file mode 100644
index 00000000000000..078522b36cb125
--- /dev/null
+++ b/examples/alerting_example/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "skipLibCheck": true,
+ "resolveJsonModule": true
+ },
+ "include": [
+ "index.ts",
+ "public/**/*.ts",
+ "public/**/*.tsx",
+ "server/**/*.ts",
+ "common/**/*.ts",
+ "../../typings/**/*",
+ ],
+ "exclude": []
+}
diff --git a/package.json b/package.json
index b3dcfb2aa3b0a7..70d064fa2a8eb7 100644
--- a/package.json
+++ b/package.json
@@ -77,7 +77,7 @@
"url": "https://github.com/elastic/kibana.git"
},
"resolutions": {
- "**/@types/node": "10.12.27",
+ "**/@types/node": ">=10.17.17 <10.20.0",
"**/@types/react": "^16.9.19",
"**/@types/react-router": "^5.1.3",
"**/@types/hapi": "^17.0.18",
@@ -103,7 +103,8 @@
"x-pack/legacy/plugins/*",
"examples/*",
"test/plugin_functional/plugins/*",
- "test/interpreter_functional/plugins/*"
+ "test/interpreter_functional/plugins/*",
+ "x-pack/test/functional_with_es_ssl/fixtures/plugins/*"
],
"nohoist": [
"**/@types/*",
@@ -119,7 +120,7 @@
"@elastic/apm-rum": "^4.6.0",
"@elastic/charts": "^17.1.1",
"@elastic/datemath": "5.0.2",
- "@elastic/ems-client": "7.6.0",
+ "@elastic/ems-client": "7.7.0",
"@elastic/eui": "20.0.2",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "8.1.1-kibana2",
@@ -171,7 +172,7 @@
"elastic-apm-node": "^3.2.0",
"elasticsearch": "^16.5.0",
"elasticsearch-browser": "^16.5.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"expiry-js": "0.1.7",
"fast-deep-equal": "^3.1.1",
"file-loader": "4.2.0",
@@ -239,7 +240,7 @@
"react-resize-detector": "^4.2.0",
"react-router-dom": "^5.1.2",
"react-sizeme": "^2.3.6",
- "react-use": "^13.13.0",
+ "react-use": "^13.27.0",
"reactcss": "1.2.3",
"redux": "^4.0.5",
"redux-actions": "^2.6.5",
@@ -314,6 +315,7 @@
"@types/cheerio": "^0.22.10",
"@types/chromedriver": "^2.38.0",
"@types/classnames": "^2.2.9",
+ "@types/color": "^3.0.0",
"@types/d3": "^3.5.43",
"@types/dedent": "^0.7.0",
"@types/deep-freeze-strict": "^1.1.0",
@@ -349,7 +351,7 @@
"@types/mocha": "^5.2.7",
"@types/moment-timezone": "^0.5.12",
"@types/mustache": "^0.8.31",
- "@types/node": "^10.12.27",
+ "@types/node": ">=10.17.17 <10.20.0",
"@types/node-forge": "^0.9.0",
"@types/normalize-path": "^3.0.0",
"@types/numeral": "^0.0.26",
@@ -459,7 +461,7 @@
"multistream": "^2.1.1",
"murmurhash3js": "3.0.1",
"mutation-observer": "^1.0.3",
- "nock": "10.0.6",
+ "nock": "12.0.3",
"node-sass": "^4.13.1",
"normalize-path": "^3.0.0",
"nyc": "^14.1.1",
diff --git a/packages/kbn-config-schema/README.md b/packages/kbn-config-schema/README.md
index 8719a2ae558abe..a4f2c1f6458cfa 100644
--- a/packages/kbn-config-schema/README.md
+++ b/packages/kbn-config-schema/README.md
@@ -239,7 +239,7 @@ __Output type:__ `{ [K in keyof TProps]: TypeOf } as TObject`
__Options:__
* `defaultValue: TObject | Reference | (() => TObject)` - defines a default value, see [Default values](#default-values) section for more details.
* `validate: (value: TObject) => string | void` - defines a custom validator function, see [Custom validation](#custom-validation) section for more details.
- * `allowUnknowns: boolean` - indicates whether unknown object properties should be allowed. It's `false` by default.
+ * `unknowns: 'allow' | 'ignore' | 'forbid'` - indicates whether unknown object properties should be allowed, ignored, or forbidden. It's `forbid` by default.
__Usage:__
```typescript
@@ -250,7 +250,7 @@ const valueSchema = schema.object({
```
__Notes:__
-* Using `allowUnknowns` is discouraged and should only be used in exceptional circumstances. Consider using `schema.recordOf()` instead.
+* Using `unknowns: 'allow'` is discouraged and should only be used in exceptional circumstances. Consider using `schema.recordOf()` instead.
* Currently `schema.object()` always has a default value of `{}`, but this may change in the near future. Try to not rely on this behaviour and specify default value explicitly or use `schema.maybe()` if the value is optional.
* `schema.object()` also supports a json string as input if it can be safely parsed using `JSON.parse` and if the resulting value is a plain object.
diff --git a/packages/kbn-config-schema/src/internals/index.ts b/packages/kbn-config-schema/src/internals/index.ts
index 8f5d09e5b8b499..f84e14d2f741db 100644
--- a/packages/kbn-config-schema/src/internals/index.ts
+++ b/packages/kbn-config-schema/src/internals/index.ts
@@ -314,7 +314,8 @@ export const internals = Joi.extend([
for (const [entryKey, entryValue] of value) {
const { value: validatedEntryKey, error: keyError } = Joi.validate(
entryKey,
- params.key
+ params.key,
+ { presence: 'required' }
);
if (keyError) {
@@ -323,7 +324,8 @@ export const internals = Joi.extend([
const { value: validatedEntryValue, error: valueError } = Joi.validate(
entryValue,
- params.value
+ params.value,
+ { presence: 'required' }
);
if (valueError) {
@@ -374,7 +376,8 @@ export const internals = Joi.extend([
for (const [entryKey, entryValue] of Object.entries(value)) {
const { value: validatedEntryKey, error: keyError } = Joi.validate(
entryKey,
- params.key
+ params.key,
+ { presence: 'required' }
);
if (keyError) {
@@ -383,7 +386,8 @@ export const internals = Joi.extend([
const { value: validatedEntryValue, error: valueError } = Joi.validate(
entryValue,
- params.value
+ params.value,
+ { presence: 'required' }
);
if (valueError) {
diff --git a/packages/kbn-config-schema/src/types/map_of_type.test.ts b/packages/kbn-config-schema/src/types/map_of_type.test.ts
index b015f51bdc8ad9..1c5a227ef0fac4 100644
--- a/packages/kbn-config-schema/src/types/map_of_type.test.ts
+++ b/packages/kbn-config-schema/src/types/map_of_type.test.ts
@@ -159,6 +159,24 @@ test('object within mapOf', () => {
expect(type.validate(value)).toEqual(expected);
});
+test('enforces required object fields within mapOf', () => {
+ const type = schema.mapOf(
+ schema.string(),
+ schema.object({
+ bar: schema.object({
+ baz: schema.number(),
+ }),
+ })
+ );
+ const value = {
+ foo: {},
+ };
+
+ expect(() => type.validate(value)).toThrowErrorMatchingInlineSnapshot(
+ `"[foo.bar.baz]: expected value of type [number] but got [undefined]"`
+ );
+});
+
test('error preserves full path', () => {
const type = schema.object({
grandParentKey: schema.object({
diff --git a/packages/kbn-config-schema/src/types/map_type.ts b/packages/kbn-config-schema/src/types/map_type.ts
index 231c3726ae9d57..6da664bf956164 100644
--- a/packages/kbn-config-schema/src/types/map_type.ts
+++ b/packages/kbn-config-schema/src/types/map_type.ts
@@ -57,7 +57,10 @@ export class MapOfType extends Type> {
path.length,
0,
// If `key` validation failed, let's stress that to make error more obvious.
- type === 'map.key' ? `key("${entryKey}")` : entryKey.toString()
+ type === 'map.key' ? `key("${entryKey}")` : entryKey.toString(),
+ // Error could have happened deep inside value/key schema and error message should
+ // include full path.
+ ...(reason instanceof SchemaTypeError ? reason.path : [])
);
return reason instanceof SchemaTypesError
diff --git a/packages/kbn-config-schema/src/types/object_type.test.ts b/packages/kbn-config-schema/src/types/object_type.test.ts
index 29e341983fde9d..47a0f5f7a5491c 100644
--- a/packages/kbn-config-schema/src/types/object_type.test.ts
+++ b/packages/kbn-config-schema/src/types/object_type.test.ts
@@ -276,10 +276,10 @@ test('individual keys can validated', () => {
);
});
-test('allow unknown keys when allowUnknowns = true', () => {
+test('allow unknown keys when unknowns = `allow`', () => {
const type = schema.object(
{ foo: schema.string({ defaultValue: 'test' }) },
- { allowUnknowns: true }
+ { unknowns: 'allow' }
);
expect(
@@ -292,10 +292,10 @@ test('allow unknown keys when allowUnknowns = true', () => {
});
});
-test('allowUnknowns = true affects only own keys', () => {
+test('unknowns = `allow` affects only own keys', () => {
const type = schema.object(
{ foo: schema.object({ bar: schema.string() }) },
- { allowUnknowns: true }
+ { unknowns: 'allow' }
);
expect(() =>
@@ -308,10 +308,10 @@ test('allowUnknowns = true affects only own keys', () => {
).toThrowErrorMatchingInlineSnapshot(`"[foo.baz]: definition for this key is missing"`);
});
-test('does not allow unknown keys when allowUnknowns = false', () => {
+test('does not allow unknown keys when unknowns = `forbid`', () => {
const type = schema.object(
{ foo: schema.string({ defaultValue: 'test' }) },
- { allowUnknowns: false }
+ { unknowns: 'forbid' }
);
expect(() =>
type.validate({
@@ -319,3 +319,34 @@ test('does not allow unknown keys when allowUnknowns = false', () => {
})
).toThrowErrorMatchingInlineSnapshot(`"[bar]: definition for this key is missing"`);
});
+
+test('allow and remove unknown keys when unknowns = `ignore`', () => {
+ const type = schema.object(
+ { foo: schema.string({ defaultValue: 'test' }) },
+ { unknowns: 'ignore' }
+ );
+
+ expect(
+ type.validate({
+ bar: 'baz',
+ })
+ ).toEqual({
+ foo: 'test',
+ });
+});
+
+test('unknowns = `ignore` affects only own keys', () => {
+ const type = schema.object(
+ { foo: schema.object({ bar: schema.string() }) },
+ { unknowns: 'ignore' }
+ );
+
+ expect(() =>
+ type.validate({
+ foo: {
+ bar: 'bar',
+ baz: 'baz',
+ },
+ })
+ ).toThrowErrorMatchingInlineSnapshot(`"[foo.baz]: definition for this key is missing"`);
+});
diff --git a/packages/kbn-config-schema/src/types/object_type.ts b/packages/kbn-config-schema/src/types/object_type.ts
index f34acd0d2ce656..5a50e714a59311 100644
--- a/packages/kbn-config-schema/src/types/object_type.ts
+++ b/packages/kbn-config-schema/src/types/object_type.ts
@@ -30,17 +30,25 @@ export type TypeOf> = RT['type'];
// this might not have perfect _rendering_ output, but it will be typed.
export type ObjectResultType = Readonly<{ [K in keyof P]: TypeOf
}>;
+interface UnknownOptions {
+ /**
+ * Options for dealing with unknown keys:
+ * - allow: unknown keys will be permitted
+ * - ignore: unknown keys will not fail validation, but will be stripped out
+ * - forbid (default): unknown keys will fail validation
+ */
+ unknowns?: 'allow' | 'ignore' | 'forbid';
+}
+
export type ObjectTypeOptions
= TypeOptions<
{ [K in keyof P]: TypeOf
}
-> & {
- /** Should uknown keys not be defined in the schema be allowed. Defaults to `false` */
- allowUnknowns?: boolean;
-};
+> &
+ UnknownOptions;
export class ObjectType
extends Type> {
private props: Record;
- constructor(props: P, { allowUnknowns = false, ...typeOptions }: ObjectTypeOptions = {}) {
+ constructor(props: P, { unknowns = 'forbid', ...typeOptions }: ObjectTypeOptions
= {}) {
const schemaKeys = {} as Record;
for (const [key, value] of Object.entries(props)) {
schemaKeys[key] = value.getSchema();
@@ -50,7 +58,8 @@ export class ObjectType extends Type>
.keys(schemaKeys)
.default()
.optional()
- .unknown(Boolean(allowUnknowns));
+ .unknown(unknowns === 'allow')
+ .options({ stripUnknown: { objects: unknowns === 'ignore' } });
super(schema, typeOptions);
this.props = schemaKeys;
diff --git a/packages/kbn-config-schema/src/types/record_of_type.test.ts b/packages/kbn-config-schema/src/types/record_of_type.test.ts
index ef15e7b0f6ad6b..aee7dde71c3e46 100644
--- a/packages/kbn-config-schema/src/types/record_of_type.test.ts
+++ b/packages/kbn-config-schema/src/types/record_of_type.test.ts
@@ -159,6 +159,24 @@ test('object within recordOf', () => {
expect(type.validate(value)).toEqual({ foo: { bar: 123 } });
});
+test('enforces required object fields within recordOf', () => {
+ const type = schema.recordOf(
+ schema.string(),
+ schema.object({
+ bar: schema.object({
+ baz: schema.number(),
+ }),
+ })
+ );
+ const value = {
+ foo: {},
+ };
+
+ expect(() => type.validate(value)).toThrowErrorMatchingInlineSnapshot(
+ `"[foo.bar.baz]: expected value of type [number] but got [undefined]"`
+ );
+});
+
test('error preserves full path', () => {
const type = schema.object({
grandParentKey: schema.object({
diff --git a/packages/kbn-config-schema/src/types/record_type.ts b/packages/kbn-config-schema/src/types/record_type.ts
index c6d4b4d71b4f1d..ef9e70cbabc086 100644
--- a/packages/kbn-config-schema/src/types/record_type.ts
+++ b/packages/kbn-config-schema/src/types/record_type.ts
@@ -49,7 +49,10 @@ export class RecordOfType extends Type> {
path.length,
0,
// If `key` validation failed, let's stress that to make error more obvious.
- type === 'record.key' ? `key("${entryKey}")` : entryKey.toString()
+ type === 'record.key' ? `key("${entryKey}")` : entryKey.toString(),
+ // Error could have happened deep inside value/key schema and error message should
+ // include full path.
+ ...(reason instanceof SchemaTypeError ? reason.path : [])
);
return reason instanceof SchemaTypesError
diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json
index bea153d0a672bc..ee9f349f490517 100644
--- a/packages/kbn-dev-utils/package.json
+++ b/packages/kbn-dev-utils/package.json
@@ -12,7 +12,7 @@
"dependencies": {
"chalk": "^2.4.2",
"dedent": "^0.7.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"exit-hook": "^2.2.0",
"getopts": "^2.2.5",
"load-json-file": "^6.2.0",
diff --git a/packages/kbn-dev-utils/src/run/run.ts b/packages/kbn-dev-utils/src/run/run.ts
index e185f86cc3bf79..35477e988d8371 100644
--- a/packages/kbn-dev-utils/src/run/run.ts
+++ b/packages/kbn-dev-utils/src/run/run.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+import { inspect } from 'util';
+
// @ts-ignore @types are outdated and module is super simple
import exitHook from 'exit-hook';
@@ -62,7 +64,11 @@ export async function run(fn: RunFn, options: Options = {}) {
process.on('unhandledRejection', error => {
log.error('UNHANDLED PROMISE REJECTION');
- log.error(error);
+ log.error(
+ error instanceof Error
+ ? error
+ : new Error(`non-Error type rejection value: ${inspect(error)}`)
+ );
process.exit(1);
});
diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json
index f9d7bffed1e226..8b964d83999040 100644
--- a/packages/kbn-es/package.json
+++ b/packages/kbn-es/package.json
@@ -11,7 +11,7 @@
"chalk": "^2.4.2",
"dedent": "^0.7.0",
"del": "^5.1.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"getopts": "^2.2.4",
"glob": "^7.1.2",
"node-fetch": "^2.6.0",
diff --git a/packages/kbn-plugin-generator/package.json b/packages/kbn-plugin-generator/package.json
index ac98a0e675fb18..b3b1eff41e4b5f 100644
--- a/packages/kbn-plugin-generator/package.json
+++ b/packages/kbn-plugin-generator/package.json
@@ -6,7 +6,7 @@
"dependencies": {
"chalk": "^2.4.2",
"dedent": "^0.7.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"getopts": "^2.2.4",
"lodash.camelcase": "^4.3.0",
"lodash.kebabcase": "^4.1.1",
diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json
index 3b358c03b8053a..c348aa43789d17 100644
--- a/packages/kbn-plugin-helpers/package.json
+++ b/packages/kbn-plugin-helpers/package.json
@@ -17,7 +17,7 @@
"argv-split": "^2.0.1",
"commander": "^3.0.0",
"del": "^5.1.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"globby": "^8.0.1",
"gulp-babel": "^8.0.0",
"gulp-rename": "1.4.0",
diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js
index 338d4893005260..62b12e8e38c875 100644
--- a/packages/kbn-pm/dist/index.js
+++ b/packages/kbn-pm/dist/index.js
@@ -99,16 +99,16 @@ __webpack_require__.r(__webpack_exports__);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; });
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(501);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return _utils_projects__WEBPACK_IMPORTED_MODULE_2__["getProjects"]; });
-/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(516);
+/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; });
-/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578);
+/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(577);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; });
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; });
/*
@@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17);
-/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(689);
+/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(688);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
@@ -2506,9 +2506,9 @@ module.exports = require("path");
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; });
/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18);
-/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586);
-/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(686);
-/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(687);
+/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585);
+/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(685);
+/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(686);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -2549,10 +2549,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34);
-/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(501);
-/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(580);
-/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(585);
+/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(500);
+/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579);
+/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(584);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -4490,10 +4490,10 @@ const tslib_1 = __webpack_require__(36);
var proc_runner_1 = __webpack_require__(37);
exports.withProcRunner = proc_runner_1.withProcRunner;
exports.ProcRunner = proc_runner_1.ProcRunner;
-tslib_1.__exportStar(__webpack_require__(415), exports);
-var serializers_1 = __webpack_require__(420);
+tslib_1.__exportStar(__webpack_require__(414), exports);
+var serializers_1 = __webpack_require__(419);
exports.createAbsolutePathSerializer = serializers_1.createAbsolutePathSerializer;
-var certs_1 = __webpack_require__(445);
+var certs_1 = __webpack_require__(444);
exports.CA_CERT_PATH = certs_1.CA_CERT_PATH;
exports.ES_KEY_PATH = certs_1.ES_KEY_PATH;
exports.ES_CERT_PATH = certs_1.ES_CERT_PATH;
@@ -4505,17 +4505,17 @@ exports.KBN_KEY_PATH = certs_1.KBN_KEY_PATH;
exports.KBN_CERT_PATH = certs_1.KBN_CERT_PATH;
exports.KBN_P12_PATH = certs_1.KBN_P12_PATH;
exports.KBN_P12_PASSWORD = certs_1.KBN_P12_PASSWORD;
-var run_1 = __webpack_require__(446);
+var run_1 = __webpack_require__(445);
exports.run = run_1.run;
exports.createFailError = run_1.createFailError;
exports.createFlagError = run_1.createFlagError;
exports.combineErrors = run_1.combineErrors;
exports.isFailError = run_1.isFailError;
-var repo_root_1 = __webpack_require__(422);
+var repo_root_1 = __webpack_require__(421);
exports.REPO_ROOT = repo_root_1.REPO_ROOT;
-var kbn_client_1 = __webpack_require__(451);
+var kbn_client_1 = __webpack_require__(450);
exports.KbnClient = kbn_client_1.KbnClient;
-tslib_1.__exportStar(__webpack_require__(493), exports);
+tslib_1.__exportStar(__webpack_require__(492), exports);
/***/ }),
@@ -32149,13 +32149,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
const execa_1 = tslib_1.__importDefault(__webpack_require__(351));
const fs_1 = __webpack_require__(23);
-const Rx = tslib_1.__importStar(__webpack_require__(392));
+const Rx = tslib_1.__importStar(__webpack_require__(391));
const operators_1 = __webpack_require__(169);
const chalk_1 = tslib_1.__importDefault(__webpack_require__(2));
-const tree_kill_1 = tslib_1.__importDefault(__webpack_require__(412));
+const tree_kill_1 = tslib_1.__importDefault(__webpack_require__(411));
const util_1 = __webpack_require__(29);
const treeKillAsync = util_1.promisify((...args) => tree_kill_1.default(...args));
-const observe_lines_1 = __webpack_require__(413);
+const observe_lines_1 = __webpack_require__(412);
const errors_1 = __webpack_require__(349);
const SECOND = 1000;
const STOP_TIMEOUT = 30 * SECOND;
@@ -32271,9 +32271,9 @@ const onetime = __webpack_require__(368);
const makeError = __webpack_require__(370);
const normalizeStdio = __webpack_require__(375);
const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(376);
-const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(381);
-const {mergePromise, getSpawnedPromise} = __webpack_require__(390);
-const {joinCommand, parseCommand} = __webpack_require__(391);
+const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(380);
+const {mergePromise, getSpawnedPromise} = __webpack_require__(389);
+const {joinCommand, parseCommand} = __webpack_require__(390);
const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;
@@ -32305,8 +32305,8 @@ const handleArgs = (file, args, options = {}) => {
reject: true,
cleanup: true,
all: false,
- ...options,
- windowsHide: true
+ windowsHide: true,
+ ...options
};
options.env = getEnv(options);
@@ -33430,15 +33430,18 @@ const makeError = ({
const errorCode = error && error.code;
const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled});
- const message = `Command ${prefix}: ${command}`;
+ const execaMessage = `Command ${prefix}: ${command}`;
+ const shortMessage = error instanceof Error ? `${execaMessage}\n${error.message}` : execaMessage;
+ const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n');
if (error instanceof Error) {
error.originalMessage = error.message;
- error.message = `${message}\n${error.message}`;
+ error.message = message;
} else {
error = new Error(message);
}
+ error.shortMessage = shortMessage;
error.command = command;
error.exitCode = exitCode;
error.signal = signal;
@@ -33954,7 +33957,6 @@ module.exports.node = opts => {
const os = __webpack_require__(11);
const onExit = __webpack_require__(377);
-const pFinally = __webpack_require__(380);
const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5;
@@ -33971,9 +33973,17 @@ const setKillTimeout = (kill, signal, options, killResult) => {
}
const timeout = getForceKillAfterTimeout(options);
- setTimeout(() => {
+ const t = setTimeout(() => {
kill('SIGKILL');
- }, timeout).unref();
+ }, timeout);
+
+ // Guarded because there's no `.unref()` when `execa` is used in the renderer
+ // process in Electron. This cannot be tested since we don't run tests in
+ // Electron.
+ // istanbul ignore else
+ if (t.unref) {
+ t.unref();
+ }
};
const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => {
@@ -34028,7 +34038,7 @@ const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise
}, timeout);
});
- const safeSpawnedPromise = pFinally(spawnedPromise, () => {
+ const safeSpawnedPromise = spawnedPromise.finally(() => {
clearTimeout(timeoutId);
});
@@ -34036,7 +34046,7 @@ const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise
};
// `cleanup` option handling
-const setExitHandler = (spawned, {cleanup, detached}, timedPromise) => {
+const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => {
if (!cleanup || detached) {
return timedPromise;
}
@@ -34045,8 +34055,9 @@ const setExitHandler = (spawned, {cleanup, detached}, timedPromise) => {
spawned.kill();
});
- // TODO: Use native "finally" syntax when targeting Node.js 10
- return pFinally(timedPromise, removeExitHandler);
+ return timedPromise.finally(() => {
+ removeExitHandler();
+ });
};
module.exports = {
@@ -34291,33 +34302,9 @@ module.exports = require("events");
"use strict";
-
-module.exports = async (
- promise,
- onFinally = (() => {})
-) => {
- let value;
- try {
- value = await promise;
- } catch (error) {
- await onFinally();
- throw error;
- }
-
- await onFinally();
- return value;
-};
-
-
-/***/ }),
-/* 381 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-
-const isStream = __webpack_require__(382);
-const getStream = __webpack_require__(383);
-const mergeStream = __webpack_require__(389);
+const isStream = __webpack_require__(381);
+const getStream = __webpack_require__(382);
+const mergeStream = __webpack_require__(388);
// `input` option
const handleInput = (spawned, input) => {
@@ -34414,7 +34401,7 @@ module.exports = {
/***/ }),
-/* 382 */
+/* 381 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -34450,13 +34437,13 @@ module.exports = isStream;
/***/ }),
-/* 383 */
+/* 382 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const pump = __webpack_require__(384);
-const bufferStream = __webpack_require__(388);
+const pump = __webpack_require__(383);
+const bufferStream = __webpack_require__(387);
class MaxBufferError extends Error {
constructor() {
@@ -34515,11 +34502,11 @@ module.exports.MaxBufferError = MaxBufferError;
/***/ }),
-/* 384 */
+/* 383 */
/***/ (function(module, exports, __webpack_require__) {
-var once = __webpack_require__(385)
-var eos = __webpack_require__(387)
+var once = __webpack_require__(384)
+var eos = __webpack_require__(386)
var fs = __webpack_require__(23) // we only need fs to get the ReadStream and WriteStream prototypes
var noop = function () {}
@@ -34603,10 +34590,10 @@ module.exports = pump
/***/ }),
-/* 385 */
+/* 384 */
/***/ (function(module, exports, __webpack_require__) {
-var wrappy = __webpack_require__(386)
+var wrappy = __webpack_require__(385)
module.exports = wrappy(once)
module.exports.strict = wrappy(onceStrict)
@@ -34651,7 +34638,7 @@ function onceStrict (fn) {
/***/ }),
-/* 386 */
+/* 385 */
/***/ (function(module, exports) {
// Returns a wrapper function that returns a wrapped callback
@@ -34690,10 +34677,10 @@ function wrappy (fn, cb) {
/***/ }),
-/* 387 */
+/* 386 */
/***/ (function(module, exports, __webpack_require__) {
-var once = __webpack_require__(385);
+var once = __webpack_require__(384);
var noop = function() {};
@@ -34783,7 +34770,7 @@ module.exports = eos;
/***/ }),
-/* 388 */
+/* 387 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -34842,7 +34829,7 @@ module.exports = options => {
/***/ }),
-/* 389 */
+/* 388 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -34890,7 +34877,7 @@ module.exports = function (/*streams...*/) {
/***/ }),
-/* 390 */
+/* 389 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -34913,12 +34900,7 @@ const mergePromiseProperty = (spawned, promise, property) => {
const mergePromise = (spawned, promise) => {
mergePromiseProperty(spawned, promise, 'then');
mergePromiseProperty(spawned, promise, 'catch');
-
- // TODO: Remove the `if`-guard when targeting Node.js 10
- if (Promise.prototype.finally) {
- mergePromiseProperty(spawned, promise, 'finally');
- }
-
+ mergePromiseProperty(spawned, promise, 'finally');
return spawned;
};
@@ -34949,7 +34931,7 @@ module.exports = {
/***/ }),
-/* 391 */
+/* 390 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -34994,7 +34976,7 @@ module.exports = {
/***/ }),
-/* 392 */
+/* 391 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35032,10 +35014,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(298);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; });
-/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(393);
+/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(392);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; });
-/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(396);
+/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(395);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; });
@@ -35063,7 +35045,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(232);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; });
-/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(397);
+/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(396);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; });
/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(250);
@@ -35081,10 +35063,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(335);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; });
-/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(398);
+/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(397);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; });
-/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(399);
+/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(398);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; });
/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(214);
@@ -35099,49 +35081,49 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(242);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; });
-/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(400);
+/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(399);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; });
/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(218);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; });
-/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(401);
+/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(400);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__["fromEvent"]; });
-/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(402);
+/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(401);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__["fromEventPattern"]; });
-/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(403);
+/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(402);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__["generate"]; });
-/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(404);
+/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(403);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__["iif"]; });
-/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(405);
+/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(404);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__["interval"]; });
/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(278);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__["merge"]; });
-/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(406);
+/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(405);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; });
/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(227);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; });
-/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(407);
+/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(406);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__["onErrorResumeNext"]; });
-/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(408);
+/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(407);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; });
-/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(409);
+/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(408);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__["partition"]; });
/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(302);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__["race"]; });
-/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(410);
+/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(409);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__["range"]; });
/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(243);
@@ -35150,7 +35132,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(204);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__["timer"]; });
-/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(411);
+/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(410);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__["using"]; });
/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(346);
@@ -35226,14 +35208,14 @@ __webpack_require__.r(__webpack_exports__);
/***/ }),
-/* 393 */
+/* 392 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; });
-/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(394);
-/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(395);
+/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(393);
+/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(394);
/** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */
@@ -35242,7 +35224,7 @@ var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTE
/***/ }),
-/* 394 */
+/* 393 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35291,7 +35273,7 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 395 */
+/* 394 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35335,7 +35317,7 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 396 */
+/* 395 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35458,7 +35440,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) {
/***/ }),
-/* 397 */
+/* 396 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35474,7 +35456,7 @@ function isObservable(obj) {
/***/ }),
-/* 398 */
+/* 397 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35594,7 +35576,7 @@ function dispatchError(state) {
/***/ }),
-/* 399 */
+/* 398 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35722,7 +35704,7 @@ function dispatchError(arg) {
/***/ }),
-/* 400 */
+/* 399 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35805,7 +35787,7 @@ function forkJoinInternal(sources, keys) {
/***/ }),
-/* 401 */
+/* 400 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35881,7 +35863,7 @@ function isEventTarget(sourceObj) {
/***/ }),
-/* 402 */
+/* 401 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -35926,7 +35908,7 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) {
/***/ }),
-/* 403 */
+/* 402 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36063,7 +36045,7 @@ function dispatch(state) {
/***/ }),
-/* 404 */
+/* 403 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36087,7 +36069,7 @@ function iif(condition, trueResult, falseResult) {
/***/ }),
-/* 405 */
+/* 404 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36127,7 +36109,7 @@ function dispatch(state) {
/***/ }),
-/* 406 */
+/* 405 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36147,7 +36129,7 @@ function never() {
/***/ }),
-/* 407 */
+/* 406 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36187,7 +36169,7 @@ function onErrorResumeNext() {
/***/ }),
-/* 408 */
+/* 407 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36238,7 +36220,7 @@ function dispatch(state) {
/***/ }),
-/* 409 */
+/* 408 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36263,7 +36245,7 @@ function partition(source, predicate, thisArg) {
/***/ }),
-/* 410 */
+/* 409 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36322,7 +36304,7 @@ function dispatch(state) {
/***/ }),
-/* 411 */
+/* 410 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -36367,7 +36349,7 @@ function using(resourceFactory, observableFactory) {
/***/ }),
-/* 412 */
+/* 411 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36492,7 +36474,7 @@ function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesLi
/***/ }),
-/* 413 */
+/* 412 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36517,10 +36499,10 @@ function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesLi
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
-const Rx = tslib_1.__importStar(__webpack_require__(392));
+const Rx = tslib_1.__importStar(__webpack_require__(391));
const operators_1 = __webpack_require__(169);
const SEP = /\r?\n/;
-const observe_readable_1 = __webpack_require__(414);
+const observe_readable_1 = __webpack_require__(413);
/**
* Creates an Observable from a Readable Stream that:
* - splits data from `readable` into lines
@@ -36561,7 +36543,7 @@ exports.observeLines = observeLines;
/***/ }),
-/* 414 */
+/* 413 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36586,7 +36568,7 @@ exports.observeLines = observeLines;
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
-const Rx = tslib_1.__importStar(__webpack_require__(392));
+const Rx = tslib_1.__importStar(__webpack_require__(391));
const operators_1 = __webpack_require__(169);
/**
* Produces an Observable from a ReadableSteam that:
@@ -36600,7 +36582,7 @@ exports.observeReadable = observeReadable;
/***/ }),
-/* 415 */
+/* 414 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36624,19 +36606,19 @@ exports.observeReadable = observeReadable;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-var tooling_log_1 = __webpack_require__(416);
+var tooling_log_1 = __webpack_require__(415);
exports.ToolingLog = tooling_log_1.ToolingLog;
-var tooling_log_text_writer_1 = __webpack_require__(417);
+var tooling_log_text_writer_1 = __webpack_require__(416);
exports.ToolingLogTextWriter = tooling_log_text_writer_1.ToolingLogTextWriter;
-var log_levels_1 = __webpack_require__(418);
+var log_levels_1 = __webpack_require__(417);
exports.pickLevelFromFlags = log_levels_1.pickLevelFromFlags;
exports.parseLogLevel = log_levels_1.parseLogLevel;
-var tooling_log_collecting_writer_1 = __webpack_require__(419);
+var tooling_log_collecting_writer_1 = __webpack_require__(418);
exports.ToolingLogCollectingWriter = tooling_log_collecting_writer_1.ToolingLogCollectingWriter;
/***/ }),
-/* 416 */
+/* 415 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36661,8 +36643,8 @@ exports.ToolingLogCollectingWriter = tooling_log_collecting_writer_1.ToolingLogC
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
-const Rx = tslib_1.__importStar(__webpack_require__(392));
-const tooling_log_text_writer_1 = __webpack_require__(417);
+const Rx = tslib_1.__importStar(__webpack_require__(391));
+const tooling_log_text_writer_1 = __webpack_require__(416);
class ToolingLog {
constructor(writerConfig) {
this.identWidth = 0;
@@ -36724,7 +36706,7 @@ exports.ToolingLog = ToolingLog;
/***/ }),
-/* 417 */
+/* 416 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36751,7 +36733,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
const util_1 = __webpack_require__(29);
const chalk_1 = tslib_1.__importDefault(__webpack_require__(2));
-const log_levels_1 = __webpack_require__(418);
+const log_levels_1 = __webpack_require__(417);
const { magentaBright, yellow, red, blue, green, dim } = chalk_1.default;
const PREFIX_INDENT = ' '.repeat(6);
const MSG_PREFIXES = {
@@ -36818,7 +36800,7 @@ exports.ToolingLogTextWriter = ToolingLogTextWriter;
/***/ }),
-/* 418 */
+/* 417 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36874,7 +36856,7 @@ exports.parseLogLevel = parseLogLevel;
/***/ }),
-/* 419 */
+/* 418 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36898,7 +36880,7 @@ exports.parseLogLevel = parseLogLevel;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-const tooling_log_text_writer_1 = __webpack_require__(417);
+const tooling_log_text_writer_1 = __webpack_require__(416);
class ToolingLogCollectingWriter extends tooling_log_text_writer_1.ToolingLogTextWriter {
constructor() {
super({
@@ -36917,7 +36899,7 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter;
/***/ }),
-/* 420 */
+/* 419 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36941,12 +36923,12 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-var absolute_path_serializer_1 = __webpack_require__(421);
+var absolute_path_serializer_1 = __webpack_require__(420);
exports.createAbsolutePathSerializer = absolute_path_serializer_1.createAbsolutePathSerializer;
/***/ }),
-/* 421 */
+/* 420 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -36970,7 +36952,7 @@ exports.createAbsolutePathSerializer = absolute_path_serializer_1.createAbsolute
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-const repo_root_1 = __webpack_require__(422);
+const repo_root_1 = __webpack_require__(421);
function createAbsolutePathSerializer(rootPath = repo_root_1.REPO_ROOT) {
return {
print: (value) => value.replace(rootPath, '').replace(/\\/g, '/'),
@@ -36981,7 +36963,7 @@ exports.createAbsolutePathSerializer = createAbsolutePathSerializer;
/***/ }),
-/* 422 */
+/* 421 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -37008,7 +36990,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
const path_1 = tslib_1.__importDefault(__webpack_require__(16));
const fs_1 = tslib_1.__importDefault(__webpack_require__(23));
-const load_json_file_1 = tslib_1.__importDefault(__webpack_require__(423));
+const load_json_file_1 = tslib_1.__importDefault(__webpack_require__(422));
const isKibanaDir = (dir) => {
try {
const path = path_1.default.resolve(dir, 'package.json');
@@ -37044,16 +37026,16 @@ exports.REPO_ROOT = cursor;
/***/ }),
-/* 423 */
+/* 422 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
const {promisify} = __webpack_require__(29);
-const fs = __webpack_require__(424);
-const stripBom = __webpack_require__(428);
-const parseJson = __webpack_require__(429);
+const fs = __webpack_require__(423);
+const stripBom = __webpack_require__(427);
+const parseJson = __webpack_require__(428);
const parse = (data, filePath, options = {}) => {
data = stripBom(data);
@@ -37070,13 +37052,13 @@ module.exports.sync = (filePath, options) => parse(fs.readFileSync(filePath, 'ut
/***/ }),
-/* 424 */
+/* 423 */
/***/ (function(module, exports, __webpack_require__) {
var fs = __webpack_require__(23)
-var polyfills = __webpack_require__(425)
-var legacy = __webpack_require__(426)
-var clone = __webpack_require__(427)
+var polyfills = __webpack_require__(424)
+var legacy = __webpack_require__(425)
+var clone = __webpack_require__(426)
var queue = []
@@ -37355,7 +37337,7 @@ function retry () {
/***/ }),
-/* 425 */
+/* 424 */
/***/ (function(module, exports, __webpack_require__) {
var constants = __webpack_require__(25)
@@ -37690,7 +37672,7 @@ function patch (fs) {
/***/ }),
-/* 426 */
+/* 425 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(27).Stream
@@ -37814,7 +37796,7 @@ function legacy (fs) {
/***/ }),
-/* 427 */
+/* 426 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -37840,7 +37822,7 @@ function clone (obj) {
/***/ }),
-/* 428 */
+/* 427 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -37862,15 +37844,15 @@ module.exports = string => {
/***/ }),
-/* 429 */
+/* 428 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const errorEx = __webpack_require__(430);
-const fallback = __webpack_require__(432);
-const {default: LinesAndColumns} = __webpack_require__(433);
-const {codeFrameColumns} = __webpack_require__(434);
+const errorEx = __webpack_require__(429);
+const fallback = __webpack_require__(431);
+const {default: LinesAndColumns} = __webpack_require__(432);
+const {codeFrameColumns} = __webpack_require__(433);
const JSONError = errorEx('JSONError', {
fileName: errorEx.append('in %s'),
@@ -37919,14 +37901,14 @@ module.exports = (string, reviver, filename) => {
/***/ }),
-/* 430 */
+/* 429 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(29);
-var isArrayish = __webpack_require__(431);
+var isArrayish = __webpack_require__(430);
var errorEx = function errorEx(name, properties) {
if (!name || name.constructor !== String) {
@@ -38059,7 +38041,7 @@ module.exports = errorEx;
/***/ }),
-/* 431 */
+/* 430 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -38076,7 +38058,7 @@ module.exports = function isArrayish(obj) {
/***/ }),
-/* 432 */
+/* 431 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -38115,7 +38097,7 @@ function parseJson (txt, reviver, context) {
/***/ }),
-/* 433 */
+/* 432 */
/***/ (function(__webpack_module__, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -38179,7 +38161,7 @@ var LinesAndColumns = (function () {
/***/ }),
-/* 434 */
+/* 433 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -38192,7 +38174,7 @@ exports.codeFrameColumns = codeFrameColumns;
exports.default = _default;
function _highlight() {
- const data = _interopRequireWildcard(__webpack_require__(435));
+ const data = _interopRequireWildcard(__webpack_require__(434));
_highlight = function () {
return data;
@@ -38358,7 +38340,7 @@ function _default(rawLines, lineNumber, colNumber, opts = {}) {
}
/***/ }),
-/* 435 */
+/* 434 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -38372,7 +38354,7 @@ exports.getChalk = getChalk;
exports.default = highlight;
function _jsTokens() {
- const data = _interopRequireWildcard(__webpack_require__(436));
+ const data = _interopRequireWildcard(__webpack_require__(435));
_jsTokens = function () {
return data;
@@ -38382,7 +38364,7 @@ function _jsTokens() {
}
function _esutils() {
- const data = _interopRequireDefault(__webpack_require__(437));
+ const data = _interopRequireDefault(__webpack_require__(436));
_esutils = function () {
return data;
@@ -38392,7 +38374,7 @@ function _esutils() {
}
function _chalk() {
- const data = _interopRequireDefault(__webpack_require__(441));
+ const data = _interopRequireDefault(__webpack_require__(440));
_chalk = function () {
return data;
@@ -38493,7 +38475,7 @@ function highlight(code, options = {}) {
}
/***/ }),
-/* 436 */
+/* 435 */
/***/ (function(module, exports) {
// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell
@@ -38522,7 +38504,7 @@ exports.matchToToken = function(match) {
/***/ }),
-/* 437 */
+/* 436 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -38553,15 +38535,15 @@ exports.matchToToken = function(match) {
(function () {
'use strict';
- exports.ast = __webpack_require__(438);
- exports.code = __webpack_require__(439);
- exports.keyword = __webpack_require__(440);
+ exports.ast = __webpack_require__(437);
+ exports.code = __webpack_require__(438);
+ exports.keyword = __webpack_require__(439);
}());
/* vim: set sw=4 ts=4 et tw=80 : */
/***/ }),
-/* 438 */
+/* 437 */
/***/ (function(module, exports) {
/*
@@ -38711,7 +38693,7 @@ exports.matchToToken = function(match) {
/***/ }),
-/* 439 */
+/* 438 */
/***/ (function(module, exports) {
/*
@@ -38852,7 +38834,7 @@ exports.matchToToken = function(match) {
/***/ }),
-/* 440 */
+/* 439 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -38882,7 +38864,7 @@ exports.matchToToken = function(match) {
(function () {
'use strict';
- var code = __webpack_require__(439);
+ var code = __webpack_require__(438);
function isStrictModeReservedWordES6(id) {
switch (id) {
@@ -39023,16 +39005,16 @@ exports.matchToToken = function(match) {
/***/ }),
-/* 441 */
+/* 440 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const escapeStringRegexp = __webpack_require__(3);
-const ansiStyles = __webpack_require__(442);
-const stdoutColor = __webpack_require__(443).stdout;
+const ansiStyles = __webpack_require__(441);
+const stdoutColor = __webpack_require__(442).stdout;
-const template = __webpack_require__(444);
+const template = __webpack_require__(443);
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
@@ -39258,7 +39240,7 @@ module.exports.default = module.exports; // For TypeScript
/***/ }),
-/* 442 */
+/* 441 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39431,7 +39413,7 @@ Object.defineProperty(module, 'exports', {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module)))
/***/ }),
-/* 443 */
+/* 442 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39573,7 +39555,7 @@ module.exports = {
/***/ }),
-/* 444 */
+/* 443 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39708,7 +39690,7 @@ module.exports = (chalk, tmp) => {
/***/ }),
-/* 445 */
+/* 444 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39747,7 +39729,7 @@ exports.KBN_P12_PASSWORD = 'storepass';
/***/ }),
-/* 446 */
+/* 445 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39771,9 +39753,9 @@ exports.KBN_P12_PASSWORD = 'storepass';
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-var run_1 = __webpack_require__(447);
+var run_1 = __webpack_require__(446);
exports.run = run_1.run;
-var fail_1 = __webpack_require__(448);
+var fail_1 = __webpack_require__(447);
exports.createFailError = fail_1.createFailError;
exports.createFlagError = fail_1.createFlagError;
exports.combineErrors = fail_1.combineErrors;
@@ -39781,7 +39763,7 @@ exports.isFailError = fail_1.isFailError;
/***/ }),
-/* 447 */
+/* 446 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39806,11 +39788,12 @@ exports.isFailError = fail_1.isFailError;
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
+const util_1 = __webpack_require__(29);
// @ts-ignore @types are outdated and module is super simple
const exit_hook_1 = tslib_1.__importDefault(__webpack_require__(348));
-const tooling_log_1 = __webpack_require__(415);
-const fail_1 = __webpack_require__(448);
-const flags_1 = __webpack_require__(449);
+const tooling_log_1 = __webpack_require__(414);
+const fail_1 = __webpack_require__(447);
+const flags_1 = __webpack_require__(448);
const proc_runner_1 = __webpack_require__(37);
async function run(fn, options = {}) {
var _a;
@@ -39825,7 +39808,9 @@ async function run(fn, options = {}) {
});
process.on('unhandledRejection', error => {
log.error('UNHANDLED PROMISE REJECTION');
- log.error(error);
+ log.error(error instanceof Error
+ ? error
+ : new Error(`non-Error type rejection value: ${util_1.inspect(error)}`));
process.exit(1);
});
const handleErrorWithoutExit = (error) => {
@@ -39883,7 +39868,7 @@ exports.run = run;
/***/ }),
-/* 448 */
+/* 447 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39951,7 +39936,7 @@ exports.combineErrors = combineErrors;
/***/ }),
-/* 449 */
+/* 448 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -39978,7 +39963,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
const path_1 = __webpack_require__(16);
const dedent_1 = tslib_1.__importDefault(__webpack_require__(14));
-const getopts_1 = tslib_1.__importDefault(__webpack_require__(450));
+const getopts_1 = tslib_1.__importDefault(__webpack_require__(449));
function getFlags(argv, options) {
const unexpectedNames = new Set();
const flagOpts = options.flags || {};
@@ -40081,7 +40066,7 @@ exports.getHelp = getHelp;
/***/ }),
-/* 450 */
+/* 449 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -40293,7 +40278,7 @@ module.exports = getopts
/***/ }),
-/* 451 */
+/* 450 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -40317,14 +40302,14 @@ module.exports = getopts
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-var kbn_client_1 = __webpack_require__(452);
+var kbn_client_1 = __webpack_require__(451);
exports.KbnClient = kbn_client_1.KbnClient;
-var kbn_client_requester_1 = __webpack_require__(453);
+var kbn_client_requester_1 = __webpack_require__(452);
exports.uriencode = kbn_client_requester_1.uriencode;
/***/ }),
-/* 452 */
+/* 451 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -40348,12 +40333,12 @@ exports.uriencode = kbn_client_requester_1.uriencode;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-const kbn_client_requester_1 = __webpack_require__(453);
-const kbn_client_status_1 = __webpack_require__(495);
-const kbn_client_plugins_1 = __webpack_require__(496);
-const kbn_client_version_1 = __webpack_require__(497);
-const kbn_client_saved_objects_1 = __webpack_require__(498);
-const kbn_client_ui_settings_1 = __webpack_require__(499);
+const kbn_client_requester_1 = __webpack_require__(452);
+const kbn_client_status_1 = __webpack_require__(494);
+const kbn_client_plugins_1 = __webpack_require__(495);
+const kbn_client_version_1 = __webpack_require__(496);
+const kbn_client_saved_objects_1 = __webpack_require__(497);
+const kbn_client_ui_settings_1 = __webpack_require__(498);
class KbnClient {
/**
* Basic Kibana server client that implements common behaviors for talking
@@ -40391,7 +40376,7 @@ exports.KbnClient = KbnClient;
/***/ }),
-/* 453 */
+/* 452 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -40416,9 +40401,9 @@ exports.KbnClient = KbnClient;
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
-const url_1 = tslib_1.__importDefault(__webpack_require__(454));
-const axios_1 = tslib_1.__importDefault(__webpack_require__(455));
-const axios_2 = __webpack_require__(493);
+const url_1 = tslib_1.__importDefault(__webpack_require__(453));
+const axios_1 = tslib_1.__importDefault(__webpack_require__(454));
+const axios_2 = __webpack_require__(492);
const isConcliftOnGetError = (error) => {
return (axios_2.isAxiosResponseError(error) && error.config.method === 'GET' && error.response.status === 409);
};
@@ -40502,28 +40487,28 @@ exports.KbnClientRequester = KbnClientRequester;
/***/ }),
-/* 454 */
+/* 453 */
/***/ (function(module, exports) {
module.exports = require("url");
/***/ }),
-/* 455 */
+/* 454 */
/***/ (function(module, exports, __webpack_require__) {
-module.exports = __webpack_require__(456);
+module.exports = __webpack_require__(455);
/***/ }),
-/* 456 */
+/* 455 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
-var bind = __webpack_require__(458);
-var Axios = __webpack_require__(460);
-var defaults = __webpack_require__(461);
+var utils = __webpack_require__(456);
+var bind = __webpack_require__(457);
+var Axios = __webpack_require__(459);
+var defaults = __webpack_require__(460);
/**
* Create an instance of Axios
@@ -40556,15 +40541,15 @@ axios.create = function create(instanceConfig) {
};
// Expose Cancel & CancelToken
-axios.Cancel = __webpack_require__(490);
-axios.CancelToken = __webpack_require__(491);
-axios.isCancel = __webpack_require__(487);
+axios.Cancel = __webpack_require__(489);
+axios.CancelToken = __webpack_require__(490);
+axios.isCancel = __webpack_require__(486);
// Expose all/spread
axios.all = function all(promises) {
return Promise.all(promises);
};
-axios.spread = __webpack_require__(492);
+axios.spread = __webpack_require__(491);
module.exports = axios;
@@ -40573,14 +40558,14 @@ module.exports.default = axios;
/***/ }),
-/* 457 */
+/* 456 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var bind = __webpack_require__(458);
-var isBuffer = __webpack_require__(459);
+var bind = __webpack_require__(457);
+var isBuffer = __webpack_require__(458);
/*global toString:true*/
@@ -40883,7 +40868,7 @@ module.exports = {
/***/ }),
-/* 458 */
+/* 457 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -40901,7 +40886,7 @@ module.exports = function bind(fn, thisArg) {
/***/ }),
-/* 459 */
+/* 458 */
/***/ (function(module, exports) {
/*!
@@ -40918,16 +40903,16 @@ module.exports = function isBuffer (obj) {
/***/ }),
-/* 460 */
+/* 459 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var defaults = __webpack_require__(461);
-var utils = __webpack_require__(457);
-var InterceptorManager = __webpack_require__(484);
-var dispatchRequest = __webpack_require__(485);
+var defaults = __webpack_require__(460);
+var utils = __webpack_require__(456);
+var InterceptorManager = __webpack_require__(483);
+var dispatchRequest = __webpack_require__(484);
/**
* Create a new instance of Axios
@@ -41004,14 +40989,14 @@ module.exports = Axios;
/***/ }),
-/* 461 */
+/* 460 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
-var normalizeHeaderName = __webpack_require__(462);
+var utils = __webpack_require__(456);
+var normalizeHeaderName = __webpack_require__(461);
var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded'
@@ -41027,10 +41012,10 @@ function getDefaultAdapter() {
var adapter;
if (typeof XMLHttpRequest !== 'undefined') {
// For browsers use XHR adapter
- adapter = __webpack_require__(463);
+ adapter = __webpack_require__(462);
} else if (typeof process !== 'undefined') {
// For node use HTTP adapter
- adapter = __webpack_require__(471);
+ adapter = __webpack_require__(470);
}
return adapter;
}
@@ -41107,13 +41092,13 @@ module.exports = defaults;
/***/ }),
-/* 462 */
+/* 461 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
module.exports = function normalizeHeaderName(headers, normalizedName) {
utils.forEach(headers, function processHeader(value, name) {
@@ -41126,18 +41111,18 @@ module.exports = function normalizeHeaderName(headers, normalizedName) {
/***/ }),
-/* 463 */
+/* 462 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
-var settle = __webpack_require__(464);
-var buildURL = __webpack_require__(467);
-var parseHeaders = __webpack_require__(468);
-var isURLSameOrigin = __webpack_require__(469);
-var createError = __webpack_require__(465);
+var utils = __webpack_require__(456);
+var settle = __webpack_require__(463);
+var buildURL = __webpack_require__(466);
+var parseHeaders = __webpack_require__(467);
+var isURLSameOrigin = __webpack_require__(468);
+var createError = __webpack_require__(464);
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
@@ -41217,7 +41202,7 @@ module.exports = function xhrAdapter(config) {
// This is only done if running in a standard browser environment.
// Specifically not if we're in a web worker, or react-native.
if (utils.isStandardBrowserEnv()) {
- var cookies = __webpack_require__(470);
+ var cookies = __webpack_require__(469);
// Add xsrf header
var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
@@ -41295,13 +41280,13 @@ module.exports = function xhrAdapter(config) {
/***/ }),
-/* 464 */
+/* 463 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var createError = __webpack_require__(465);
+var createError = __webpack_require__(464);
/**
* Resolve or reject a Promise based on response status.
@@ -41328,13 +41313,13 @@ module.exports = function settle(resolve, reject, response) {
/***/ }),
-/* 465 */
+/* 464 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var enhanceError = __webpack_require__(466);
+var enhanceError = __webpack_require__(465);
/**
* Create an Error with the specified message, config, error code, request and response.
@@ -41353,7 +41338,7 @@ module.exports = function createError(message, config, code, request, response)
/***/ }),
-/* 466 */
+/* 465 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -41381,13 +41366,13 @@ module.exports = function enhanceError(error, config, code, request, response) {
/***/ }),
-/* 467 */
+/* 466 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
function encode(val) {
return encodeURIComponent(val).
@@ -41454,13 +41439,13 @@ module.exports = function buildURL(url, params, paramsSerializer) {
/***/ }),
-/* 468 */
+/* 467 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
// Headers whose duplicates are ignored by node
// c.f. https://nodejs.org/api/http.html#http_message_headers
@@ -41514,13 +41499,13 @@ module.exports = function parseHeaders(headers) {
/***/ }),
-/* 469 */
+/* 468 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
module.exports = (
utils.isStandardBrowserEnv() ?
@@ -41589,13 +41574,13 @@ module.exports = (
/***/ }),
-/* 470 */
+/* 469 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
module.exports = (
utils.isStandardBrowserEnv() ?
@@ -41649,24 +41634,24 @@ module.exports = (
/***/ }),
-/* 471 */
+/* 470 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
-var settle = __webpack_require__(464);
-var buildURL = __webpack_require__(467);
-var http = __webpack_require__(472);
-var https = __webpack_require__(473);
-var httpFollow = __webpack_require__(474).http;
-var httpsFollow = __webpack_require__(474).https;
-var url = __webpack_require__(454);
-var zlib = __webpack_require__(482);
-var pkg = __webpack_require__(483);
-var createError = __webpack_require__(465);
-var enhanceError = __webpack_require__(466);
+var utils = __webpack_require__(456);
+var settle = __webpack_require__(463);
+var buildURL = __webpack_require__(466);
+var http = __webpack_require__(471);
+var https = __webpack_require__(472);
+var httpFollow = __webpack_require__(473).http;
+var httpsFollow = __webpack_require__(473).https;
+var url = __webpack_require__(453);
+var zlib = __webpack_require__(481);
+var pkg = __webpack_require__(482);
+var createError = __webpack_require__(464);
+var enhanceError = __webpack_require__(465);
/*eslint consistent-return:0*/
module.exports = function httpAdapter(config) {
@@ -41894,27 +41879,27 @@ module.exports = function httpAdapter(config) {
/***/ }),
-/* 472 */
+/* 471 */
/***/ (function(module, exports) {
module.exports = require("http");
/***/ }),
-/* 473 */
+/* 472 */
/***/ (function(module, exports) {
module.exports = require("https");
/***/ }),
-/* 474 */
+/* 473 */
/***/ (function(module, exports, __webpack_require__) {
-var url = __webpack_require__(454);
-var http = __webpack_require__(472);
-var https = __webpack_require__(473);
+var url = __webpack_require__(453);
+var http = __webpack_require__(471);
+var https = __webpack_require__(472);
var assert = __webpack_require__(30);
var Writable = __webpack_require__(27).Writable;
-var debug = __webpack_require__(475)("follow-redirects");
+var debug = __webpack_require__(474)("follow-redirects");
// RFC7231§4.2.1: Of the request methods defined by this specification,
// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe.
@@ -42234,7 +42219,7 @@ module.exports.wrap = wrap;
/***/ }),
-/* 475 */
+/* 474 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -42243,14 +42228,14 @@ module.exports.wrap = wrap;
*/
if (typeof process === 'undefined' || process.type === 'renderer') {
- module.exports = __webpack_require__(476);
+ module.exports = __webpack_require__(475);
} else {
- module.exports = __webpack_require__(479);
+ module.exports = __webpack_require__(478);
}
/***/ }),
-/* 476 */
+/* 475 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -42259,7 +42244,7 @@ if (typeof process === 'undefined' || process.type === 'renderer') {
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(477);
+exports = module.exports = __webpack_require__(476);
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
@@ -42451,7 +42436,7 @@ function localstorage() {
/***/ }),
-/* 477 */
+/* 476 */
/***/ (function(module, exports, __webpack_require__) {
@@ -42467,7 +42452,7 @@ exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
-exports.humanize = __webpack_require__(478);
+exports.humanize = __webpack_require__(477);
/**
* Active `debug` instances.
@@ -42682,7 +42667,7 @@ function coerce(val) {
/***/ }),
-/* 478 */
+/* 477 */
/***/ (function(module, exports) {
/**
@@ -42840,14 +42825,14 @@ function plural(ms, n, name) {
/***/ }),
-/* 479 */
+/* 478 */
/***/ (function(module, exports, __webpack_require__) {
/**
* Module dependencies.
*/
-var tty = __webpack_require__(480);
+var tty = __webpack_require__(479);
var util = __webpack_require__(29);
/**
@@ -42856,7 +42841,7 @@ var util = __webpack_require__(29);
* Expose `debug()` as the module.
*/
-exports = module.exports = __webpack_require__(477);
+exports = module.exports = __webpack_require__(476);
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
@@ -42871,7 +42856,7 @@ exports.useColors = useColors;
exports.colors = [ 6, 2, 3, 4, 5, 1 ];
try {
- var supportsColor = __webpack_require__(481);
+ var supportsColor = __webpack_require__(480);
if (supportsColor && supportsColor.level >= 2) {
exports.colors = [
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
@@ -43032,13 +43017,13 @@ exports.enable(load());
/***/ }),
-/* 480 */
+/* 479 */
/***/ (function(module, exports) {
module.exports = require("tty");
/***/ }),
-/* 481 */
+/* 480 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43183,25 +43168,25 @@ module.exports = {
/***/ }),
-/* 482 */
+/* 481 */
/***/ (function(module, exports) {
module.exports = require("zlib");
/***/ }),
-/* 483 */
+/* 482 */
/***/ (function(module) {
module.exports = JSON.parse("{\"name\":\"axios\",\"version\":\"0.18.1\",\"description\":\"Promise based HTTP client for the browser and node.js\",\"main\":\"index.js\",\"scripts\":{\"test\":\"grunt test && bundlesize\",\"start\":\"node ./sandbox/server.js\",\"build\":\"NODE_ENV=production grunt build\",\"preversion\":\"npm test\",\"version\":\"npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json\",\"postversion\":\"git push && git push --tags\",\"examples\":\"node ./examples/server.js\",\"coveralls\":\"cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\"},\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/axios/axios.git\"},\"keywords\":[\"xhr\",\"http\",\"ajax\",\"promise\",\"node\"],\"author\":\"Matt Zabriskie\",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/axios/axios/issues\"},\"homepage\":\"https://github.com/axios/axios\",\"devDependencies\":{\"bundlesize\":\"^0.5.7\",\"coveralls\":\"^2.11.9\",\"es6-promise\":\"^4.0.5\",\"grunt\":\"^1.0.1\",\"grunt-banner\":\"^0.6.0\",\"grunt-cli\":\"^1.2.0\",\"grunt-contrib-clean\":\"^1.0.0\",\"grunt-contrib-nodeunit\":\"^1.0.0\",\"grunt-contrib-watch\":\"^1.0.0\",\"grunt-eslint\":\"^19.0.0\",\"grunt-karma\":\"^2.0.0\",\"grunt-ts\":\"^6.0.0-beta.3\",\"grunt-webpack\":\"^1.0.18\",\"istanbul-instrumenter-loader\":\"^1.0.0\",\"jasmine-core\":\"^2.4.1\",\"karma\":\"^1.3.0\",\"karma-chrome-launcher\":\"^2.0.0\",\"karma-coverage\":\"^1.0.0\",\"karma-firefox-launcher\":\"^1.0.0\",\"karma-jasmine\":\"^1.0.2\",\"karma-jasmine-ajax\":\"^0.1.13\",\"karma-opera-launcher\":\"^1.0.0\",\"karma-safari-launcher\":\"^1.0.0\",\"karma-sauce-launcher\":\"^1.1.0\",\"karma-sinon\":\"^1.0.5\",\"karma-sourcemap-loader\":\"^0.3.7\",\"karma-webpack\":\"^1.7.0\",\"load-grunt-tasks\":\"^3.5.2\",\"minimist\":\"^1.2.0\",\"sinon\":\"^1.17.4\",\"webpack\":\"^1.13.1\",\"webpack-dev-server\":\"^1.14.1\",\"url-search-params\":\"^0.6.1\",\"typescript\":\"^2.0.3\"},\"browser\":{\"./lib/adapters/http.js\":\"./lib/adapters/xhr.js\"},\"typings\":\"./index.d.ts\",\"dependencies\":{\"follow-redirects\":\"1.5.10\",\"is-buffer\":\"^2.0.2\"},\"bundlesize\":[{\"path\":\"./dist/axios.min.js\",\"threshold\":\"5kB\"}]}");
/***/ }),
-/* 484 */
+/* 483 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
function InterceptorManager() {
this.handlers = [];
@@ -43254,18 +43239,18 @@ module.exports = InterceptorManager;
/***/ }),
-/* 485 */
+/* 484 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
-var transformData = __webpack_require__(486);
-var isCancel = __webpack_require__(487);
-var defaults = __webpack_require__(461);
-var isAbsoluteURL = __webpack_require__(488);
-var combineURLs = __webpack_require__(489);
+var utils = __webpack_require__(456);
+var transformData = __webpack_require__(485);
+var isCancel = __webpack_require__(486);
+var defaults = __webpack_require__(460);
+var isAbsoluteURL = __webpack_require__(487);
+var combineURLs = __webpack_require__(488);
/**
* Throws a `Cancel` if cancellation has been requested.
@@ -43347,13 +43332,13 @@ module.exports = function dispatchRequest(config) {
/***/ }),
-/* 486 */
+/* 485 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var utils = __webpack_require__(457);
+var utils = __webpack_require__(456);
/**
* Transform the data for a request or a response
@@ -43374,7 +43359,7 @@ module.exports = function transformData(data, headers, fns) {
/***/ }),
-/* 487 */
+/* 486 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43386,7 +43371,7 @@ module.exports = function isCancel(value) {
/***/ }),
-/* 488 */
+/* 487 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43407,7 +43392,7 @@ module.exports = function isAbsoluteURL(url) {
/***/ }),
-/* 489 */
+/* 488 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43428,7 +43413,7 @@ module.exports = function combineURLs(baseURL, relativeURL) {
/***/ }),
-/* 490 */
+/* 489 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43454,13 +43439,13 @@ module.exports = Cancel;
/***/ }),
-/* 491 */
+/* 490 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var Cancel = __webpack_require__(490);
+var Cancel = __webpack_require__(489);
/**
* A `CancelToken` is an object that can be used to request cancellation of an operation.
@@ -43518,7 +43503,7 @@ module.exports = CancelToken;
/***/ }),
-/* 492 */
+/* 491 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43552,7 +43537,7 @@ module.exports = function spread(callback) {
/***/ }),
-/* 493 */
+/* 492 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43577,11 +43562,11 @@ module.exports = function spread(callback) {
*/
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = __webpack_require__(36);
-tslib_1.__exportStar(__webpack_require__(494), exports);
+tslib_1.__exportStar(__webpack_require__(493), exports);
/***/ }),
-/* 494 */
+/* 493 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43614,7 +43599,7 @@ exports.isAxiosResponseError = (error) => {
/***/ }),
-/* 495 */
+/* 494 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43663,7 +43648,7 @@ exports.KbnClientStatus = KbnClientStatus;
/***/ }),
-/* 496 */
+/* 495 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43713,7 +43698,7 @@ exports.KbnClientPlugins = KbnClientPlugins;
/***/ }),
-/* 497 */
+/* 496 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43754,7 +43739,7 @@ exports.KbnClientVersion = KbnClientVersion;
/***/ }),
-/* 498 */
+/* 497 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43778,7 +43763,7 @@ exports.KbnClientVersion = KbnClientVersion;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-const kbn_client_requester_1 = __webpack_require__(453);
+const kbn_client_requester_1 = __webpack_require__(452);
class KbnClientSavedObjects {
constructor(log, requester) {
this.log = log;
@@ -43863,7 +43848,7 @@ exports.KbnClientSavedObjects = KbnClientSavedObjects;
/***/ }),
-/* 499 */
+/* 498 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -43887,7 +43872,7 @@ exports.KbnClientSavedObjects = KbnClientSavedObjects;
* under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
-const kbn_client_requester_1 = __webpack_require__(453);
+const kbn_client_requester_1 = __webpack_require__(452);
class KbnClientUiSettings {
constructor(log, requester, defaults) {
this.log = log;
@@ -43963,7 +43948,7 @@ exports.KbnClientUiSettings = KbnClientUiSettings;
/***/ }),
-/* 500 */
+/* 499 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -44029,7 +44014,7 @@ async function parallelize(items, fn, concurrency = 4) {
}
/***/ }),
-/* 501 */
+/* 500 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -44038,15 +44023,15 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; });
-/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(502);
+/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(501);
/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515);
-/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(516);
-/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578);
+/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514);
+/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515);
+/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(577);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -44245,7 +44230,7 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, {
}
/***/ }),
-/* 502 */
+/* 501 */
/***/ (function(module, exports, __webpack_require__) {
// Approach:
@@ -44291,26 +44276,26 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, {
module.exports = glob
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
-var inherits = __webpack_require__(509)
+var inherits = __webpack_require__(508)
var EE = __webpack_require__(379).EventEmitter
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
-var globSync = __webpack_require__(512)
-var common = __webpack_require__(513)
+var isAbsolute = __webpack_require__(510)
+var globSync = __webpack_require__(511)
+var common = __webpack_require__(512)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
-var inflight = __webpack_require__(514)
+var inflight = __webpack_require__(513)
var util = __webpack_require__(29)
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
-var once = __webpack_require__(385)
+var once = __webpack_require__(384)
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
@@ -45041,7 +45026,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
/***/ }),
-/* 503 */
+/* 502 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = realpath
@@ -45057,7 +45042,7 @@ var origRealpathSync = fs.realpathSync
var version = process.version
var ok = /^v[0-5]\./.test(version)
-var old = __webpack_require__(504)
+var old = __webpack_require__(503)
function newError (er) {
return er && er.syscall === 'realpath' && (
@@ -45113,7 +45098,7 @@ function unmonkeypatch () {
/***/ }),
-/* 504 */
+/* 503 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright Joyent, Inc. and other Node contributors.
@@ -45422,7 +45407,7 @@ exports.realpath = function realpath(p, cache, cb) {
/***/ }),
-/* 505 */
+/* 504 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = minimatch
@@ -45434,7 +45419,7 @@ try {
} catch (er) {}
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
-var expand = __webpack_require__(506)
+var expand = __webpack_require__(505)
var plTypes = {
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
@@ -46351,11 +46336,11 @@ function regExpEscape (s) {
/***/ }),
-/* 506 */
+/* 505 */
/***/ (function(module, exports, __webpack_require__) {
-var concatMap = __webpack_require__(507);
-var balanced = __webpack_require__(508);
+var concatMap = __webpack_require__(506);
+var balanced = __webpack_require__(507);
module.exports = expandTop;
@@ -46558,7 +46543,7 @@ function expand(str, isTop) {
/***/ }),
-/* 507 */
+/* 506 */
/***/ (function(module, exports) {
module.exports = function (xs, fn) {
@@ -46577,7 +46562,7 @@ var isArray = Array.isArray || function (xs) {
/***/ }),
-/* 508 */
+/* 507 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46643,7 +46628,7 @@ function range(a, b, str) {
/***/ }),
-/* 509 */
+/* 508 */
/***/ (function(module, exports, __webpack_require__) {
try {
@@ -46653,12 +46638,12 @@ try {
module.exports = util.inherits;
} catch (e) {
/* istanbul ignore next */
- module.exports = __webpack_require__(510);
+ module.exports = __webpack_require__(509);
}
/***/ }),
-/* 510 */
+/* 509 */
/***/ (function(module, exports) {
if (typeof Object.create === 'function') {
@@ -46691,7 +46676,7 @@ if (typeof Object.create === 'function') {
/***/ }),
-/* 511 */
+/* 510 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -46718,22 +46703,22 @@ module.exports.win32 = win32;
/***/ }),
-/* 512 */
+/* 511 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = globSync
globSync.GlobSync = GlobSync
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
-var Glob = __webpack_require__(502).Glob
+var Glob = __webpack_require__(501).Glob
var util = __webpack_require__(29)
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
-var common = __webpack_require__(513)
+var isAbsolute = __webpack_require__(510)
+var common = __webpack_require__(512)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
@@ -47210,7 +47195,7 @@ GlobSync.prototype._makeAbs = function (f) {
/***/ }),
-/* 513 */
+/* 512 */
/***/ (function(module, exports, __webpack_require__) {
exports.alphasort = alphasort
@@ -47228,8 +47213,8 @@ function ownProp (obj, field) {
}
var path = __webpack_require__(16)
-var minimatch = __webpack_require__(505)
-var isAbsolute = __webpack_require__(511)
+var minimatch = __webpack_require__(504)
+var isAbsolute = __webpack_require__(510)
var Minimatch = minimatch.Minimatch
function alphasorti (a, b) {
@@ -47456,12 +47441,12 @@ function childrenIgnored (self, path) {
/***/ }),
-/* 514 */
+/* 513 */
/***/ (function(module, exports, __webpack_require__) {
-var wrappy = __webpack_require__(386)
+var wrappy = __webpack_require__(385)
var reqs = Object.create(null)
-var once = __webpack_require__(385)
+var once = __webpack_require__(384)
module.exports = wrappy(inflight)
@@ -47516,7 +47501,7 @@ function slice (args) {
/***/ }),
-/* 515 */
+/* 514 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -47549,7 +47534,7 @@ class CliError extends Error {
}
/***/ }),
-/* 516 */
+/* 515 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -47563,10 +47548,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(29);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_3__);
-/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515);
+/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(514);
/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34);
-/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517);
-/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(563);
+/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516);
+/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(562);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -47797,7 +47782,7 @@ function normalizePath(path) {
}
/***/ }),
-/* 517 */
+/* 516 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -47805,9 +47790,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readPackageJson", function() { return readPackageJson; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writePackageJson", function() { return writePackageJson; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; });
-/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(518);
+/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(517);
/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(544);
+/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(543);
/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
@@ -47841,7 +47826,7 @@ function writePackageJson(path, json) {
const isLinkDependency = depVersion => depVersion.startsWith('link:');
/***/ }),
-/* 518 */
+/* 517 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -47849,7 +47834,7 @@ const isLinkDependency = depVersion => depVersion.startsWith('link:');
const {promisify} = __webpack_require__(29);
const fs = __webpack_require__(23);
const path = __webpack_require__(16);
-const parseJson = __webpack_require__(519);
+const parseJson = __webpack_require__(518);
const readFileAsync = promisify(fs.readFile);
@@ -47864,7 +47849,7 @@ module.exports = async options => {
const json = parseJson(await readFileAsync(filePath, 'utf8'));
if (options.normalize) {
- __webpack_require__(520)(json);
+ __webpack_require__(519)(json);
}
return json;
@@ -47881,7 +47866,7 @@ module.exports.sync = options => {
const json = parseJson(fs.readFileSync(filePath, 'utf8'));
if (options.normalize) {
- __webpack_require__(520)(json);
+ __webpack_require__(519)(json);
}
return json;
@@ -47889,15 +47874,15 @@ module.exports.sync = options => {
/***/ }),
-/* 519 */
+/* 518 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const errorEx = __webpack_require__(430);
-const fallback = __webpack_require__(432);
-const {default: LinesAndColumns} = __webpack_require__(433);
-const {codeFrameColumns} = __webpack_require__(434);
+const errorEx = __webpack_require__(429);
+const fallback = __webpack_require__(431);
+const {default: LinesAndColumns} = __webpack_require__(432);
+const {codeFrameColumns} = __webpack_require__(433);
const JSONError = errorEx('JSONError', {
fileName: errorEx.append('in %s'),
@@ -47946,15 +47931,15 @@ module.exports = (string, reviver, filename) => {
/***/ }),
-/* 520 */
+/* 519 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = normalize
-var fixer = __webpack_require__(521)
+var fixer = __webpack_require__(520)
normalize.fixer = fixer
-var makeWarning = __webpack_require__(542)
+var makeWarning = __webpack_require__(541)
var fieldsToFix = ['name','version','description','repository','modules','scripts'
,'files','bin','man','bugs','keywords','readme','homepage','license']
@@ -47991,17 +47976,17 @@ function ucFirst (string) {
/***/ }),
-/* 521 */
+/* 520 */
/***/ (function(module, exports, __webpack_require__) {
-var semver = __webpack_require__(522)
-var validateLicense = __webpack_require__(523);
-var hostedGitInfo = __webpack_require__(528)
-var isBuiltinModule = __webpack_require__(531).isCore
+var semver = __webpack_require__(521)
+var validateLicense = __webpack_require__(522);
+var hostedGitInfo = __webpack_require__(527)
+var isBuiltinModule = __webpack_require__(530).isCore
var depTypes = ["dependencies","devDependencies","optionalDependencies"]
-var extractDescription = __webpack_require__(540)
-var url = __webpack_require__(454)
-var typos = __webpack_require__(541)
+var extractDescription = __webpack_require__(539)
+var url = __webpack_require__(453)
+var typos = __webpack_require__(540)
var fixer = module.exports = {
// default warning function
@@ -48415,7 +48400,7 @@ function bugsTypos(bugs, warn) {
/***/ }),
-/* 522 */
+/* 521 */
/***/ (function(module, exports) {
exports = module.exports = SemVer
@@ -49904,11 +49889,11 @@ function coerce (version) {
/***/ }),
-/* 523 */
+/* 522 */
/***/ (function(module, exports, __webpack_require__) {
-var parse = __webpack_require__(524);
-var correct = __webpack_require__(526);
+var parse = __webpack_require__(523);
+var correct = __webpack_require__(525);
var genericWarning = (
'license should be ' +
@@ -49994,10 +49979,10 @@ module.exports = function(argument) {
/***/ }),
-/* 524 */
+/* 523 */
/***/ (function(module, exports, __webpack_require__) {
-var parser = __webpack_require__(525).parser
+var parser = __webpack_require__(524).parser
module.exports = function (argument) {
return parser.parse(argument)
@@ -50005,7 +49990,7 @@ module.exports = function (argument) {
/***/ }),
-/* 525 */
+/* 524 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */
@@ -51369,10 +51354,10 @@ if ( true && __webpack_require__.c[__webpack_require__.s] === module) {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module)))
/***/ }),
-/* 526 */
+/* 525 */
/***/ (function(module, exports, __webpack_require__) {
-var licenseIDs = __webpack_require__(527);
+var licenseIDs = __webpack_require__(526);
function valid(string) {
return licenseIDs.indexOf(string) > -1;
@@ -51612,20 +51597,20 @@ module.exports = function(identifier) {
/***/ }),
-/* 527 */
+/* 526 */
/***/ (function(module) {
module.exports = JSON.parse("[\"Glide\",\"Abstyles\",\"AFL-1.1\",\"AFL-1.2\",\"AFL-2.0\",\"AFL-2.1\",\"AFL-3.0\",\"AMPAS\",\"APL-1.0\",\"Adobe-Glyph\",\"APAFML\",\"Adobe-2006\",\"AGPL-1.0\",\"Afmparse\",\"Aladdin\",\"ADSL\",\"AMDPLPA\",\"ANTLR-PD\",\"Apache-1.0\",\"Apache-1.1\",\"Apache-2.0\",\"AML\",\"APSL-1.0\",\"APSL-1.1\",\"APSL-1.2\",\"APSL-2.0\",\"Artistic-1.0\",\"Artistic-1.0-Perl\",\"Artistic-1.0-cl8\",\"Artistic-2.0\",\"AAL\",\"Bahyph\",\"Barr\",\"Beerware\",\"BitTorrent-1.0\",\"BitTorrent-1.1\",\"BSL-1.0\",\"Borceux\",\"BSD-2-Clause\",\"BSD-2-Clause-FreeBSD\",\"BSD-2-Clause-NetBSD\",\"BSD-3-Clause\",\"BSD-3-Clause-Clear\",\"BSD-4-Clause\",\"BSD-Protection\",\"BSD-Source-Code\",\"BSD-3-Clause-Attribution\",\"0BSD\",\"BSD-4-Clause-UC\",\"bzip2-1.0.5\",\"bzip2-1.0.6\",\"Caldera\",\"CECILL-1.0\",\"CECILL-1.1\",\"CECILL-2.0\",\"CECILL-2.1\",\"CECILL-B\",\"CECILL-C\",\"ClArtistic\",\"MIT-CMU\",\"CNRI-Jython\",\"CNRI-Python\",\"CNRI-Python-GPL-Compatible\",\"CPOL-1.02\",\"CDDL-1.0\",\"CDDL-1.1\",\"CPAL-1.0\",\"CPL-1.0\",\"CATOSL-1.1\",\"Condor-1.1\",\"CC-BY-1.0\",\"CC-BY-2.0\",\"CC-BY-2.5\",\"CC-BY-3.0\",\"CC-BY-4.0\",\"CC-BY-ND-1.0\",\"CC-BY-ND-2.0\",\"CC-BY-ND-2.5\",\"CC-BY-ND-3.0\",\"CC-BY-ND-4.0\",\"CC-BY-NC-1.0\",\"CC-BY-NC-2.0\",\"CC-BY-NC-2.5\",\"CC-BY-NC-3.0\",\"CC-BY-NC-4.0\",\"CC-BY-NC-ND-1.0\",\"CC-BY-NC-ND-2.0\",\"CC-BY-NC-ND-2.5\",\"CC-BY-NC-ND-3.0\",\"CC-BY-NC-ND-4.0\",\"CC-BY-NC-SA-1.0\",\"CC-BY-NC-SA-2.0\",\"CC-BY-NC-SA-2.5\",\"CC-BY-NC-SA-3.0\",\"CC-BY-NC-SA-4.0\",\"CC-BY-SA-1.0\",\"CC-BY-SA-2.0\",\"CC-BY-SA-2.5\",\"CC-BY-SA-3.0\",\"CC-BY-SA-4.0\",\"CC0-1.0\",\"Crossword\",\"CrystalStacker\",\"CUA-OPL-1.0\",\"Cube\",\"curl\",\"D-FSL-1.0\",\"diffmark\",\"WTFPL\",\"DOC\",\"Dotseqn\",\"DSDP\",\"dvipdfm\",\"EPL-1.0\",\"ECL-1.0\",\"ECL-2.0\",\"eGenix\",\"EFL-1.0\",\"EFL-2.0\",\"MIT-advertising\",\"MIT-enna\",\"Entessa\",\"ErlPL-1.1\",\"EUDatagrid\",\"EUPL-1.0\",\"EUPL-1.1\",\"Eurosym\",\"Fair\",\"MIT-feh\",\"Frameworx-1.0\",\"FreeImage\",\"FTL\",\"FSFAP\",\"FSFUL\",\"FSFULLR\",\"Giftware\",\"GL2PS\",\"Glulxe\",\"AGPL-3.0\",\"GFDL-1.1\",\"GFDL-1.2\",\"GFDL-1.3\",\"GPL-1.0\",\"GPL-2.0\",\"GPL-3.0\",\"LGPL-2.1\",\"LGPL-3.0\",\"LGPL-2.0\",\"gnuplot\",\"gSOAP-1.3b\",\"HaskellReport\",\"HPND\",\"IBM-pibs\",\"IPL-1.0\",\"ICU\",\"ImageMagick\",\"iMatix\",\"Imlib2\",\"IJG\",\"Info-ZIP\",\"Intel-ACPI\",\"Intel\",\"Interbase-1.0\",\"IPA\",\"ISC\",\"JasPer-2.0\",\"JSON\",\"LPPL-1.0\",\"LPPL-1.1\",\"LPPL-1.2\",\"LPPL-1.3a\",\"LPPL-1.3c\",\"Latex2e\",\"BSD-3-Clause-LBNL\",\"Leptonica\",\"LGPLLR\",\"Libpng\",\"libtiff\",\"LAL-1.2\",\"LAL-1.3\",\"LiLiQ-P-1.1\",\"LiLiQ-Rplus-1.1\",\"LiLiQ-R-1.1\",\"LPL-1.02\",\"LPL-1.0\",\"MakeIndex\",\"MTLL\",\"MS-PL\",\"MS-RL\",\"MirOS\",\"MITNFA\",\"MIT\",\"Motosoto\",\"MPL-1.0\",\"MPL-1.1\",\"MPL-2.0\",\"MPL-2.0-no-copyleft-exception\",\"mpich2\",\"Multics\",\"Mup\",\"NASA-1.3\",\"Naumen\",\"NBPL-1.0\",\"NetCDF\",\"NGPL\",\"NOSL\",\"NPL-1.0\",\"NPL-1.1\",\"Newsletr\",\"NLPL\",\"Nokia\",\"NPOSL-3.0\",\"NLOD-1.0\",\"Noweb\",\"NRL\",\"NTP\",\"Nunit\",\"OCLC-2.0\",\"ODbL-1.0\",\"PDDL-1.0\",\"OCCT-PL\",\"OGTSL\",\"OLDAP-2.2.2\",\"OLDAP-1.1\",\"OLDAP-1.2\",\"OLDAP-1.3\",\"OLDAP-1.4\",\"OLDAP-2.0\",\"OLDAP-2.0.1\",\"OLDAP-2.1\",\"OLDAP-2.2\",\"OLDAP-2.2.1\",\"OLDAP-2.3\",\"OLDAP-2.4\",\"OLDAP-2.5\",\"OLDAP-2.6\",\"OLDAP-2.7\",\"OLDAP-2.8\",\"OML\",\"OPL-1.0\",\"OSL-1.0\",\"OSL-1.1\",\"OSL-2.0\",\"OSL-2.1\",\"OSL-3.0\",\"OpenSSL\",\"OSET-PL-2.1\",\"PHP-3.0\",\"PHP-3.01\",\"Plexus\",\"PostgreSQL\",\"psfrag\",\"psutils\",\"Python-2.0\",\"QPL-1.0\",\"Qhull\",\"Rdisc\",\"RPSL-1.0\",\"RPL-1.1\",\"RPL-1.5\",\"RHeCos-1.1\",\"RSCPL\",\"RSA-MD\",\"Ruby\",\"SAX-PD\",\"Saxpath\",\"SCEA\",\"SWL\",\"SMPPL\",\"Sendmail\",\"SGI-B-1.0\",\"SGI-B-1.1\",\"SGI-B-2.0\",\"OFL-1.0\",\"OFL-1.1\",\"SimPL-2.0\",\"Sleepycat\",\"SNIA\",\"Spencer-86\",\"Spencer-94\",\"Spencer-99\",\"SMLNJ\",\"SugarCRM-1.1.3\",\"SISSL\",\"SISSL-1.2\",\"SPL-1.0\",\"Watcom-1.0\",\"TCL\",\"Unlicense\",\"TMate\",\"TORQUE-1.1\",\"TOSL\",\"Unicode-TOU\",\"UPL-1.0\",\"NCSA\",\"Vim\",\"VOSTROM\",\"VSL-1.0\",\"W3C-19980720\",\"W3C\",\"Wsuipa\",\"Xnet\",\"X11\",\"Xerox\",\"XFree86-1.1\",\"xinetd\",\"xpp\",\"XSkat\",\"YPL-1.0\",\"YPL-1.1\",\"Zed\",\"Zend-2.0\",\"Zimbra-1.3\",\"Zimbra-1.4\",\"Zlib\",\"zlib-acknowledgement\",\"ZPL-1.1\",\"ZPL-2.0\",\"ZPL-2.1\",\"BSD-3-Clause-No-Nuclear-License\",\"BSD-3-Clause-No-Nuclear-Warranty\",\"BSD-3-Clause-No-Nuclear-License-2014\",\"eCos-2.0\",\"GPL-2.0-with-autoconf-exception\",\"GPL-2.0-with-bison-exception\",\"GPL-2.0-with-classpath-exception\",\"GPL-2.0-with-font-exception\",\"GPL-2.0-with-GCC-exception\",\"GPL-3.0-with-autoconf-exception\",\"GPL-3.0-with-GCC-exception\",\"StandardML-NJ\",\"WXwindows\"]");
/***/ }),
-/* 528 */
+/* 527 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var url = __webpack_require__(454)
-var gitHosts = __webpack_require__(529)
-var GitHost = module.exports = __webpack_require__(530)
+var url = __webpack_require__(453)
+var gitHosts = __webpack_require__(528)
+var GitHost = module.exports = __webpack_require__(529)
var protocolToRepresentationMap = {
'git+ssh': 'sshurl',
@@ -51746,7 +51731,7 @@ function parseGitUrl (giturl) {
/***/ }),
-/* 529 */
+/* 528 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -51821,12 +51806,12 @@ Object.keys(gitHosts).forEach(function (name) {
/***/ }),
-/* 530 */
+/* 529 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var gitHosts = __webpack_require__(529)
+var gitHosts = __webpack_require__(528)
var extend = Object.assign || __webpack_require__(29)._extend
var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) {
@@ -51942,21 +51927,21 @@ GitHost.prototype.toString = function (opts) {
/***/ }),
-/* 531 */
+/* 530 */
/***/ (function(module, exports, __webpack_require__) {
-var core = __webpack_require__(532);
-var async = __webpack_require__(534);
+var core = __webpack_require__(531);
+var async = __webpack_require__(533);
async.core = core;
async.isCore = function isCore(x) { return core[x]; };
-async.sync = __webpack_require__(539);
+async.sync = __webpack_require__(538);
exports = async;
module.exports = async;
/***/ }),
-/* 532 */
+/* 531 */
/***/ (function(module, exports, __webpack_require__) {
var current = (process.versions && process.versions.node && process.versions.node.split('.')) || [];
@@ -52003,7 +51988,7 @@ function versionIncluded(specifierValue) {
return matchesRange(specifierValue);
}
-var data = __webpack_require__(533);
+var data = __webpack_require__(532);
var core = {};
for (var mod in data) { // eslint-disable-line no-restricted-syntax
@@ -52015,21 +52000,21 @@ module.exports = core;
/***/ }),
-/* 533 */
+/* 532 */
/***/ (function(module) {
module.exports = JSON.parse("{\"assert\":true,\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debugger\":\"< 8\",\"dgram\":true,\"dns\":true,\"domain\":true,\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":\">= 10 && < 10.1\",\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"string_decoder\":true,\"sys\":true,\"timers\":true,\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0\"],\"v8\":\">= 1\",\"vm\":true,\"worker_threads\":\">= 11.7\",\"zlib\":true}");
/***/ }),
-/* 534 */
+/* 533 */
/***/ (function(module, exports, __webpack_require__) {
-var core = __webpack_require__(532);
+var core = __webpack_require__(531);
var fs = __webpack_require__(23);
var path = __webpack_require__(16);
-var caller = __webpack_require__(535);
-var nodeModulesPaths = __webpack_require__(536);
-var normalizeOptions = __webpack_require__(538);
+var caller = __webpack_require__(534);
+var nodeModulesPaths = __webpack_require__(535);
+var normalizeOptions = __webpack_require__(537);
var defaultIsFile = function isFile(file, cb) {
fs.stat(file, function (err, stat) {
@@ -52256,7 +52241,7 @@ module.exports = function resolve(x, options, callback) {
/***/ }),
-/* 535 */
+/* 534 */
/***/ (function(module, exports) {
module.exports = function () {
@@ -52270,11 +52255,11 @@ module.exports = function () {
/***/ }),
-/* 536 */
+/* 535 */
/***/ (function(module, exports, __webpack_require__) {
var path = __webpack_require__(16);
-var parse = path.parse || __webpack_require__(537);
+var parse = path.parse || __webpack_require__(536);
var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) {
var prefix = '/';
@@ -52318,7 +52303,7 @@ module.exports = function nodeModulesPaths(start, opts, request) {
/***/ }),
-/* 537 */
+/* 536 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -52418,7 +52403,7 @@ module.exports.win32 = win32.parse;
/***/ }),
-/* 538 */
+/* 537 */
/***/ (function(module, exports) {
module.exports = function (x, opts) {
@@ -52434,15 +52419,15 @@ module.exports = function (x, opts) {
/***/ }),
-/* 539 */
+/* 538 */
/***/ (function(module, exports, __webpack_require__) {
-var core = __webpack_require__(532);
+var core = __webpack_require__(531);
var fs = __webpack_require__(23);
var path = __webpack_require__(16);
-var caller = __webpack_require__(535);
-var nodeModulesPaths = __webpack_require__(536);
-var normalizeOptions = __webpack_require__(538);
+var caller = __webpack_require__(534);
+var nodeModulesPaths = __webpack_require__(535);
+var normalizeOptions = __webpack_require__(537);
var defaultIsFile = function isFile(file) {
try {
@@ -52594,7 +52579,7 @@ module.exports = function (x, options) {
/***/ }),
-/* 540 */
+/* 539 */
/***/ (function(module, exports) {
module.exports = extractDescription
@@ -52614,17 +52599,17 @@ function extractDescription (d) {
/***/ }),
-/* 541 */
+/* 540 */
/***/ (function(module) {
module.exports = JSON.parse("{\"topLevel\":{\"dependancies\":\"dependencies\",\"dependecies\":\"dependencies\",\"depdenencies\":\"dependencies\",\"devEependencies\":\"devDependencies\",\"depends\":\"dependencies\",\"dev-dependencies\":\"devDependencies\",\"devDependences\":\"devDependencies\",\"devDepenencies\":\"devDependencies\",\"devdependencies\":\"devDependencies\",\"repostitory\":\"repository\",\"repo\":\"repository\",\"prefereGlobal\":\"preferGlobal\",\"hompage\":\"homepage\",\"hampage\":\"homepage\",\"autohr\":\"author\",\"autor\":\"author\",\"contributers\":\"contributors\",\"publicationConfig\":\"publishConfig\",\"script\":\"scripts\"},\"bugs\":{\"web\":\"url\",\"name\":\"url\"},\"script\":{\"server\":\"start\",\"tests\":\"test\"}}");
/***/ }),
-/* 542 */
+/* 541 */
/***/ (function(module, exports, __webpack_require__) {
var util = __webpack_require__(29)
-var messages = __webpack_require__(543)
+var messages = __webpack_require__(542)
module.exports = function() {
var args = Array.prototype.slice.call(arguments, 0)
@@ -52649,20 +52634,20 @@ function makeTypoWarning (providedName, probableName, field) {
/***/ }),
-/* 543 */
+/* 542 */
/***/ (function(module) {
module.exports = JSON.parse("{\"repositories\":\"'repositories' (plural) Not supported. Please pick one as the 'repository' field\",\"missingRepository\":\"No repository field.\",\"brokenGitUrl\":\"Probably broken git url: %s\",\"nonObjectScripts\":\"scripts must be an object\",\"nonStringScript\":\"script values must be string commands\",\"nonArrayFiles\":\"Invalid 'files' member\",\"invalidFilename\":\"Invalid filename in 'files' list: %s\",\"nonArrayBundleDependencies\":\"Invalid 'bundleDependencies' list. Must be array of package names\",\"nonStringBundleDependency\":\"Invalid bundleDependencies member: %s\",\"nonDependencyBundleDependency\":\"Non-dependency in bundleDependencies: %s\",\"nonObjectDependencies\":\"%s field must be an object\",\"nonStringDependency\":\"Invalid dependency: %s %s\",\"deprecatedArrayDependencies\":\"specifying %s as array is deprecated\",\"deprecatedModules\":\"modules field is deprecated\",\"nonArrayKeywords\":\"keywords should be an array of strings\",\"nonStringKeyword\":\"keywords should be an array of strings\",\"conflictingName\":\"%s is also the name of a node core module.\",\"nonStringDescription\":\"'description' field should be a string\",\"missingDescription\":\"No description\",\"missingReadme\":\"No README data\",\"missingLicense\":\"No license field.\",\"nonEmailUrlBugsString\":\"Bug string field must be url, email, or {email,url}\",\"nonUrlBugsUrlField\":\"bugs.url field must be a string url. Deleted.\",\"nonEmailBugsEmailField\":\"bugs.email field must be a string email. Deleted.\",\"emptyNormalizedBugs\":\"Normalized value of bugs field is an empty object. Deleted.\",\"nonUrlHomepage\":\"homepage field must be a string url. Deleted.\",\"invalidLicense\":\"license should be a valid SPDX license expression\",\"typo\":\"%s should probably be %s.\"}");
/***/ }),
-/* 544 */
+/* 543 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const writeJsonFile = __webpack_require__(545);
-const sortKeys = __webpack_require__(557);
+const writeJsonFile = __webpack_require__(544);
+const sortKeys = __webpack_require__(556);
const dependencyKeys = new Set([
'dependencies',
@@ -52727,18 +52712,18 @@ module.exports.sync = (filePath, data, options) => {
/***/ }),
-/* 545 */
+/* 544 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const fs = __webpack_require__(546);
-const writeFileAtomic = __webpack_require__(550);
-const sortKeys = __webpack_require__(557);
-const makeDir = __webpack_require__(559);
-const pify = __webpack_require__(561);
-const detectIndent = __webpack_require__(562);
+const fs = __webpack_require__(545);
+const writeFileAtomic = __webpack_require__(549);
+const sortKeys = __webpack_require__(556);
+const makeDir = __webpack_require__(558);
+const pify = __webpack_require__(560);
+const detectIndent = __webpack_require__(561);
const init = (fn, filePath, data, options) => {
if (!filePath) {
@@ -52810,13 +52795,13 @@ module.exports.sync = (filePath, data, options) => {
/***/ }),
-/* 546 */
+/* 545 */
/***/ (function(module, exports, __webpack_require__) {
var fs = __webpack_require__(23)
-var polyfills = __webpack_require__(547)
-var legacy = __webpack_require__(548)
-var clone = __webpack_require__(549)
+var polyfills = __webpack_require__(546)
+var legacy = __webpack_require__(547)
+var clone = __webpack_require__(548)
var queue = []
@@ -53095,7 +53080,7 @@ function retry () {
/***/ }),
-/* 547 */
+/* 546 */
/***/ (function(module, exports, __webpack_require__) {
var constants = __webpack_require__(25)
@@ -53430,7 +53415,7 @@ function patch (fs) {
/***/ }),
-/* 548 */
+/* 547 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(27).Stream
@@ -53554,7 +53539,7 @@ function legacy (fs) {
/***/ }),
-/* 549 */
+/* 548 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -53580,7 +53565,7 @@ function clone (obj) {
/***/ }),
-/* 550 */
+/* 549 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -53590,8 +53575,8 @@ module.exports.sync = writeFileSync
module.exports._getTmpname = getTmpname // for testing
module.exports._cleanupOnExit = cleanupOnExit
-var fs = __webpack_require__(551)
-var MurmurHash3 = __webpack_require__(555)
+var fs = __webpack_require__(550)
+var MurmurHash3 = __webpack_require__(554)
var onExit = __webpack_require__(377)
var path = __webpack_require__(16)
var activeFiles = {}
@@ -53600,7 +53585,7 @@ var activeFiles = {}
/* istanbul ignore next */
var threadId = (function getId () {
try {
- var workerThreads = __webpack_require__(556)
+ var workerThreads = __webpack_require__(555)
/// if we are in main thread, this is set to `0`
return workerThreads.threadId
@@ -53825,12 +53810,12 @@ function writeFileSync (filename, data, options) {
/***/ }),
-/* 551 */
+/* 550 */
/***/ (function(module, exports, __webpack_require__) {
var fs = __webpack_require__(23)
-var polyfills = __webpack_require__(552)
-var legacy = __webpack_require__(554)
+var polyfills = __webpack_require__(551)
+var legacy = __webpack_require__(553)
var queue = []
var util = __webpack_require__(29)
@@ -53854,7 +53839,7 @@ if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
})
}
-module.exports = patch(__webpack_require__(553))
+module.exports = patch(__webpack_require__(552))
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
module.exports = patch(fs)
}
@@ -54093,10 +54078,10 @@ function retry () {
/***/ }),
-/* 552 */
+/* 551 */
/***/ (function(module, exports, __webpack_require__) {
-var fs = __webpack_require__(553)
+var fs = __webpack_require__(552)
var constants = __webpack_require__(25)
var origCwd = process.cwd
@@ -54429,7 +54414,7 @@ function chownErOk (er) {
/***/ }),
-/* 553 */
+/* 552 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54457,7 +54442,7 @@ function clone (obj) {
/***/ }),
-/* 554 */
+/* 553 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(27).Stream
@@ -54581,7 +54566,7 @@ function legacy (fs) {
/***/ }),
-/* 555 */
+/* 554 */
/***/ (function(module, exports, __webpack_require__) {
/**
@@ -54723,18 +54708,18 @@ function legacy (fs) {
/***/ }),
-/* 556 */
+/* 555 */
/***/ (function(module, exports) {
module.exports = require(undefined);
/***/ }),
-/* 557 */
+/* 556 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const isPlainObj = __webpack_require__(558);
+const isPlainObj = __webpack_require__(557);
module.exports = (obj, opts) => {
if (!isPlainObj(obj)) {
@@ -54791,7 +54776,7 @@ module.exports = (obj, opts) => {
/***/ }),
-/* 558 */
+/* 557 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -54805,15 +54790,15 @@ module.exports = function (x) {
/***/ }),
-/* 559 */
+/* 558 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
const path = __webpack_require__(16);
-const pify = __webpack_require__(560);
-const semver = __webpack_require__(522);
+const pify = __webpack_require__(559);
+const semver = __webpack_require__(521);
const defaults = {
mode: 0o777 & (~process.umask()),
@@ -54951,7 +54936,7 @@ module.exports.sync = (input, options) => {
/***/ }),
-/* 560 */
+/* 559 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55026,7 +55011,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 561 */
+/* 560 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55101,7 +55086,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 562 */
+/* 561 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55230,7 +55215,7 @@ module.exports = str => {
/***/ }),
-/* 563 */
+/* 562 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -55239,7 +55224,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; });
-/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(564);
+/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(563);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -55309,7 +55294,7 @@ async function yarnWorkspacesInfo(directory) {
}
/***/ }),
-/* 564 */
+/* 563 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -55320,9 +55305,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(351);
/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(565);
+/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(564);
/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(570);
+/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(569);
/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
@@ -55388,12 +55373,12 @@ function spawnStreaming(command, args, opts, {
}
/***/ }),
-/* 565 */
+/* 564 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const chalk = __webpack_require__(566);
+const chalk = __webpack_require__(565);
const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color';
@@ -55415,16 +55400,16 @@ module.exports = isSupported ? main : fallbacks;
/***/ }),
-/* 566 */
+/* 565 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const escapeStringRegexp = __webpack_require__(3);
-const ansiStyles = __webpack_require__(567);
-const stdoutColor = __webpack_require__(568).stdout;
+const ansiStyles = __webpack_require__(566);
+const stdoutColor = __webpack_require__(567).stdout;
-const template = __webpack_require__(569);
+const template = __webpack_require__(568);
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
@@ -55650,7 +55635,7 @@ module.exports.default = module.exports; // For TypeScript
/***/ }),
-/* 567 */
+/* 566 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55823,7 +55808,7 @@ Object.defineProperty(module, 'exports', {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module)))
/***/ }),
-/* 568 */
+/* 567 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -55965,7 +55950,7 @@ module.exports = {
/***/ }),
-/* 569 */
+/* 568 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56100,7 +56085,7 @@ module.exports = (chalk, tmp) => {
/***/ }),
-/* 570 */
+/* 569 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright IBM Corp. 2014,2018. All Rights Reserved.
@@ -56108,12 +56093,12 @@ module.exports = (chalk, tmp) => {
// This file is licensed under the Apache License 2.0.
// License text available at https://opensource.org/licenses/Apache-2.0
-module.exports = __webpack_require__(571);
-module.exports.cli = __webpack_require__(575);
+module.exports = __webpack_require__(570);
+module.exports.cli = __webpack_require__(574);
/***/ }),
-/* 571 */
+/* 570 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56128,9 +56113,9 @@ var stream = __webpack_require__(27);
var util = __webpack_require__(29);
var fs = __webpack_require__(23);
-var through = __webpack_require__(572);
-var duplexer = __webpack_require__(573);
-var StringDecoder = __webpack_require__(574).StringDecoder;
+var through = __webpack_require__(571);
+var duplexer = __webpack_require__(572);
+var StringDecoder = __webpack_require__(573).StringDecoder;
module.exports = Logger;
@@ -56319,7 +56304,7 @@ function lineMerger(host) {
/***/ }),
-/* 572 */
+/* 571 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(27)
@@ -56433,7 +56418,7 @@ function through (write, end, opts) {
/***/ }),
-/* 573 */
+/* 572 */
/***/ (function(module, exports, __webpack_require__) {
var Stream = __webpack_require__(27)
@@ -56526,13 +56511,13 @@ function duplex(writer, reader) {
/***/ }),
-/* 574 */
+/* 573 */
/***/ (function(module, exports) {
module.exports = require("string_decoder");
/***/ }),
-/* 575 */
+/* 574 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -56543,11 +56528,11 @@ module.exports = require("string_decoder");
-var minimist = __webpack_require__(576);
+var minimist = __webpack_require__(575);
var path = __webpack_require__(16);
-var Logger = __webpack_require__(571);
-var pkg = __webpack_require__(577);
+var Logger = __webpack_require__(570);
+var pkg = __webpack_require__(576);
module.exports = cli;
@@ -56601,7 +56586,7 @@ function usage($0, p) {
/***/ }),
-/* 576 */
+/* 575 */
/***/ (function(module, exports) {
module.exports = function (args, opts) {
@@ -56843,29 +56828,29 @@ function isNumber (x) {
/***/ }),
-/* 577 */
+/* 576 */
/***/ (function(module) {
module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}");
/***/ }),
-/* 578 */
+/* 577 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; });
-/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(502);
+/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(501);
/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578);
/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20);
-/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(517);
-/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(501);
+/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(516);
+/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(500);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -56957,7 +56942,7 @@ function packagesFromGlobPattern({
}
/***/ }),
-/* 579 */
+/* 578 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -57011,6 +56996,7 @@ function getProjectPaths({
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack'));
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*'));
projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/legacy/plugins/*'));
+ projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/test/functional_with_es_ssl/fixtures/plugins/*'));
}
if (!skipKibanaPlugins) {
@@ -57026,7 +57012,7 @@ function getProjectPaths({
}
/***/ }),
-/* 580 */
+/* 579 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -57034,13 +57020,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; });
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23);
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(581);
+/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(580);
/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29);
/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(351);
/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__);
-/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(582);
+/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(581);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -57074,7 +57060,7 @@ async function getChangesForProjects(projects, kbn, log) {
log.verbose('getting changed files');
const {
stdout
- } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['ls-files', '-dmt', '--', ...Array.from(projects.values()).map(p => p.path)], {
+ } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['ls-files', '-dmt', '--', ...Array.from(projects.values()).filter(p => kbn.isPartOfRepo(p)).map(p => p.path)], {
cwd: kbn.getAbsolute()
});
const output = stdout.trim();
@@ -57117,6 +57103,11 @@ async function getChangesForProjects(projects, kbn, log) {
const changesByProject = new Map();
for (const project of sortedRelevantProjects) {
+ if (kbn.isOutsideRepo(project)) {
+ changesByProject.set(project, undefined);
+ continue;
+ }
+
const ownChanges = new Map();
const prefix = kbn.getRelative(project.path);
@@ -57141,6 +57132,10 @@ async function getChangesForProjects(projects, kbn, log) {
async function getLatestSha(project, kbn) {
+ if (kbn.isOutsideRepo(project)) {
+ return;
+ }
+
const {
stdout
} = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['log', '-n', '1', '--pretty=format:%H', '--', project.path], {
@@ -57200,7 +57195,7 @@ async function getChecksum(project, changes, yarnLock, kbn, log) {
log.verbose(`[${project.name}] local sha:`, sha);
}
- if (Array.from(changes.values()).includes('invalid')) {
+ if (!changes || Array.from(changes.values()).includes('invalid')) {
log.warning(`[${project.name}] unable to determine local changes, caching disabled`);
return;
}
@@ -57257,19 +57252,19 @@ async function getAllChecksums(kbn, log) {
}
/***/ }),
-/* 581 */
+/* 580 */
/***/ (function(module, exports) {
module.exports = require("crypto");
/***/ }),
-/* 582 */
+/* 581 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; });
-/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583);
+/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(582);
/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20);
/*
@@ -57313,7 +57308,7 @@ async function readYarnLock(kbn) {
}
/***/ }),
-/* 583 */
+/* 582 */
/***/ (function(module, exports, __webpack_require__) {
module.exports =
@@ -58872,7 +58867,7 @@ module.exports = invariant;
/* 9 */
/***/ (function(module, exports) {
-module.exports = __webpack_require__(581);
+module.exports = __webpack_require__(580);
/***/ }),
/* 10 */,
@@ -61196,7 +61191,7 @@ function onceStrict (fn) {
/* 63 */
/***/ (function(module, exports) {
-module.exports = __webpack_require__(584);
+module.exports = __webpack_require__(583);
/***/ }),
/* 64 */,
@@ -62134,7 +62129,7 @@ module.exports.win32 = win32;
/* 79 */
/***/ (function(module, exports) {
-module.exports = __webpack_require__(480);
+module.exports = __webpack_require__(479);
/***/ }),
/* 80 */,
@@ -67591,13 +67586,13 @@ module.exports = process && support(supportLevel);
/******/ ]);
/***/ }),
-/* 584 */
+/* 583 */
/***/ (function(module, exports) {
module.exports = require("buffer");
/***/ }),
-/* 585 */
+/* 584 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -67694,7 +67689,7 @@ class BootstrapCacheFile {
}
/***/ }),
-/* 586 */
+/* 585 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -67702,9 +67697,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; });
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587);
+/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(675);
+/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(674);
/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
@@ -67804,21 +67799,21 @@ const CleanCommand = {
};
/***/ }),
-/* 587 */
+/* 586 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const {promisify} = __webpack_require__(29);
const path = __webpack_require__(16);
-const globby = __webpack_require__(588);
-const isGlob = __webpack_require__(605);
-const slash = __webpack_require__(666);
+const globby = __webpack_require__(587);
+const isGlob = __webpack_require__(604);
+const slash = __webpack_require__(665);
const gracefulFs = __webpack_require__(22);
-const isPathCwd = __webpack_require__(668);
-const isPathInside = __webpack_require__(669);
-const rimraf = __webpack_require__(670);
-const pMap = __webpack_require__(671);
+const isPathCwd = __webpack_require__(667);
+const isPathInside = __webpack_require__(668);
+const rimraf = __webpack_require__(669);
+const pMap = __webpack_require__(670);
const rimrafP = promisify(rimraf);
@@ -67932,19 +67927,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options
/***/ }),
-/* 588 */
+/* 587 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(23);
-const arrayUnion = __webpack_require__(589);
-const merge2 = __webpack_require__(590);
-const glob = __webpack_require__(591);
-const fastGlob = __webpack_require__(596);
-const dirGlob = __webpack_require__(662);
-const gitignore = __webpack_require__(664);
-const {FilterStream, UniqueStream} = __webpack_require__(667);
+const arrayUnion = __webpack_require__(588);
+const merge2 = __webpack_require__(589);
+const glob = __webpack_require__(590);
+const fastGlob = __webpack_require__(595);
+const dirGlob = __webpack_require__(661);
+const gitignore = __webpack_require__(663);
+const {FilterStream, UniqueStream} = __webpack_require__(666);
const DEFAULT_FILTER = () => false;
@@ -68117,7 +68112,7 @@ module.exports.gitignore = gitignore;
/***/ }),
-/* 589 */
+/* 588 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68129,7 +68124,7 @@ module.exports = (...arguments_) => {
/***/ }),
-/* 590 */
+/* 589 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -68243,7 +68238,7 @@ function pauseStreams (streams, options) {
/***/ }),
-/* 591 */
+/* 590 */
/***/ (function(module, exports, __webpack_require__) {
// Approach:
@@ -68289,26 +68284,26 @@ function pauseStreams (streams, options) {
module.exports = glob
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
-var inherits = __webpack_require__(592)
+var inherits = __webpack_require__(591)
var EE = __webpack_require__(379).EventEmitter
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
-var globSync = __webpack_require__(594)
-var common = __webpack_require__(595)
+var isAbsolute = __webpack_require__(510)
+var globSync = __webpack_require__(593)
+var common = __webpack_require__(594)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
-var inflight = __webpack_require__(514)
+var inflight = __webpack_require__(513)
var util = __webpack_require__(29)
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
-var once = __webpack_require__(385)
+var once = __webpack_require__(384)
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
@@ -69039,7 +69034,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
/***/ }),
-/* 592 */
+/* 591 */
/***/ (function(module, exports, __webpack_require__) {
try {
@@ -69049,12 +69044,12 @@ try {
module.exports = util.inherits;
} catch (e) {
/* istanbul ignore next */
- module.exports = __webpack_require__(593);
+ module.exports = __webpack_require__(592);
}
/***/ }),
-/* 593 */
+/* 592 */
/***/ (function(module, exports) {
if (typeof Object.create === 'function') {
@@ -69087,22 +69082,22 @@ if (typeof Object.create === 'function') {
/***/ }),
-/* 594 */
+/* 593 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = globSync
globSync.GlobSync = GlobSync
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
-var Glob = __webpack_require__(591).Glob
+var Glob = __webpack_require__(590).Glob
var util = __webpack_require__(29)
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
-var common = __webpack_require__(595)
+var isAbsolute = __webpack_require__(510)
+var common = __webpack_require__(594)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
@@ -69579,7 +69574,7 @@ GlobSync.prototype._makeAbs = function (f) {
/***/ }),
-/* 595 */
+/* 594 */
/***/ (function(module, exports, __webpack_require__) {
exports.alphasort = alphasort
@@ -69597,8 +69592,8 @@ function ownProp (obj, field) {
}
var path = __webpack_require__(16)
-var minimatch = __webpack_require__(505)
-var isAbsolute = __webpack_require__(511)
+var minimatch = __webpack_require__(504)
+var isAbsolute = __webpack_require__(510)
var Minimatch = minimatch.Minimatch
function alphasorti (a, b) {
@@ -69825,17 +69820,17 @@ function childrenIgnored (self, path) {
/***/ }),
-/* 596 */
+/* 595 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const taskManager = __webpack_require__(597);
-const async_1 = __webpack_require__(625);
-const stream_1 = __webpack_require__(658);
-const sync_1 = __webpack_require__(659);
-const settings_1 = __webpack_require__(661);
-const utils = __webpack_require__(598);
+const taskManager = __webpack_require__(596);
+const async_1 = __webpack_require__(624);
+const stream_1 = __webpack_require__(657);
+const sync_1 = __webpack_require__(658);
+const settings_1 = __webpack_require__(660);
+const utils = __webpack_require__(597);
function FastGlob(source, options) {
try {
assertPatternsInput(source);
@@ -69893,13 +69888,13 @@ module.exports = FastGlob;
/***/ }),
-/* 597 */
+/* 596 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(598);
+const utils = __webpack_require__(597);
function generate(patterns, settings) {
const positivePatterns = getPositivePatterns(patterns);
const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore);
@@ -69967,28 +69962,28 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask;
/***/ }),
-/* 598 */
+/* 597 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const array = __webpack_require__(599);
+const array = __webpack_require__(598);
exports.array = array;
-const errno = __webpack_require__(600);
+const errno = __webpack_require__(599);
exports.errno = errno;
-const fs = __webpack_require__(601);
+const fs = __webpack_require__(600);
exports.fs = fs;
-const path = __webpack_require__(602);
+const path = __webpack_require__(601);
exports.path = path;
-const pattern = __webpack_require__(603);
+const pattern = __webpack_require__(602);
exports.pattern = pattern;
-const stream = __webpack_require__(624);
+const stream = __webpack_require__(623);
exports.stream = stream;
/***/ }),
-/* 599 */
+/* 598 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70001,7 +69996,7 @@ exports.flatten = flatten;
/***/ }),
-/* 600 */
+/* 599 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70014,7 +70009,7 @@ exports.isEnoentCodeError = isEnoentCodeError;
/***/ }),
-/* 601 */
+/* 600 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70039,7 +70034,7 @@ exports.createDirentFromStats = createDirentFromStats;
/***/ }),
-/* 602 */
+/* 601 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -70060,16 +70055,16 @@ exports.makeAbsolute = makeAbsolute;
/***/ }),
-/* 603 */
+/* 602 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(16);
-const globParent = __webpack_require__(604);
-const isGlob = __webpack_require__(605);
-const micromatch = __webpack_require__(607);
+const globParent = __webpack_require__(603);
+const isGlob = __webpack_require__(604);
+const micromatch = __webpack_require__(606);
const GLOBSTAR = '**';
function isStaticPattern(pattern) {
return !isDynamicPattern(pattern);
@@ -70158,13 +70153,13 @@ exports.matchAny = matchAny;
/***/ }),
-/* 604 */
+/* 603 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var isGlob = __webpack_require__(605);
+var isGlob = __webpack_require__(604);
var pathPosixDirname = __webpack_require__(16).posix.dirname;
var isWin32 = __webpack_require__(11).platform() === 'win32';
@@ -70199,7 +70194,7 @@ module.exports = function globParent(str) {
/***/ }),
-/* 605 */
+/* 604 */
/***/ (function(module, exports, __webpack_require__) {
/*!
@@ -70209,7 +70204,7 @@ module.exports = function globParent(str) {
* Released under the MIT License.
*/
-var isExtglob = __webpack_require__(606);
+var isExtglob = __webpack_require__(605);
var chars = { '{': '}', '(': ')', '[': ']'};
var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/;
var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/;
@@ -70253,7 +70248,7 @@ module.exports = function isGlob(str, options) {
/***/ }),
-/* 606 */
+/* 605 */
/***/ (function(module, exports) {
/*!
@@ -70279,16 +70274,16 @@ module.exports = function isExtglob(str) {
/***/ }),
-/* 607 */
+/* 606 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const util = __webpack_require__(29);
-const braces = __webpack_require__(608);
-const picomatch = __webpack_require__(618);
-const utils = __webpack_require__(621);
+const braces = __webpack_require__(607);
+const picomatch = __webpack_require__(617);
+const utils = __webpack_require__(620);
const isEmptyString = val => typeof val === 'string' && (val === '' || val === './');
/**
@@ -70753,16 +70748,16 @@ module.exports = micromatch;
/***/ }),
-/* 608 */
+/* 607 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringify = __webpack_require__(609);
-const compile = __webpack_require__(611);
-const expand = __webpack_require__(615);
-const parse = __webpack_require__(616);
+const stringify = __webpack_require__(608);
+const compile = __webpack_require__(610);
+const expand = __webpack_require__(614);
+const parse = __webpack_require__(615);
/**
* Expand the given pattern or create a regex-compatible string.
@@ -70930,13 +70925,13 @@ module.exports = braces;
/***/ }),
-/* 609 */
+/* 608 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const utils = __webpack_require__(610);
+const utils = __webpack_require__(609);
module.exports = (ast, options = {}) => {
let stringify = (node, parent = {}) => {
@@ -70969,7 +70964,7 @@ module.exports = (ast, options = {}) => {
/***/ }),
-/* 610 */
+/* 609 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -71088,14 +71083,14 @@ exports.flatten = (...args) => {
/***/ }),
-/* 611 */
+/* 610 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const fill = __webpack_require__(612);
-const utils = __webpack_require__(610);
+const fill = __webpack_require__(611);
+const utils = __webpack_require__(609);
const compile = (ast, options = {}) => {
let walk = (node, parent = {}) => {
@@ -71152,7 +71147,7 @@ module.exports = compile;
/***/ }),
-/* 612 */
+/* 611 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -71166,7 +71161,7 @@ module.exports = compile;
const util = __webpack_require__(29);
-const toRegexRange = __webpack_require__(613);
+const toRegexRange = __webpack_require__(612);
const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
@@ -71408,7 +71403,7 @@ module.exports = fill;
/***/ }),
-/* 613 */
+/* 612 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -71421,7 +71416,7 @@ module.exports = fill;
-const isNumber = __webpack_require__(614);
+const isNumber = __webpack_require__(613);
const toRegexRange = (min, max, options) => {
if (isNumber(min) === false) {
@@ -71703,7 +71698,7 @@ module.exports = toRegexRange;
/***/ }),
-/* 614 */
+/* 613 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -71728,15 +71723,15 @@ module.exports = function(num) {
/***/ }),
-/* 615 */
+/* 614 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const fill = __webpack_require__(612);
-const stringify = __webpack_require__(609);
-const utils = __webpack_require__(610);
+const fill = __webpack_require__(611);
+const stringify = __webpack_require__(608);
+const utils = __webpack_require__(609);
const append = (queue = '', stash = '', enclose = false) => {
let result = [];
@@ -71848,13 +71843,13 @@ module.exports = expand;
/***/ }),
-/* 616 */
+/* 615 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringify = __webpack_require__(609);
+const stringify = __webpack_require__(608);
/**
* Constants
@@ -71876,7 +71871,7 @@ const {
CHAR_SINGLE_QUOTE, /* ' */
CHAR_NO_BREAK_SPACE,
CHAR_ZERO_WIDTH_NOBREAK_SPACE
-} = __webpack_require__(617);
+} = __webpack_require__(616);
/**
* parse
@@ -72188,7 +72183,7 @@ module.exports = parse;
/***/ }),
-/* 617 */
+/* 616 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72252,26 +72247,26 @@ module.exports = {
/***/ }),
-/* 618 */
+/* 617 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = __webpack_require__(619);
+module.exports = __webpack_require__(618);
/***/ }),
-/* 619 */
+/* 618 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const scan = __webpack_require__(620);
-const parse = __webpack_require__(623);
-const utils = __webpack_require__(621);
+const scan = __webpack_require__(619);
+const parse = __webpack_require__(622);
+const utils = __webpack_require__(620);
/**
* Creates a matcher function from one or more glob patterns. The
@@ -72574,7 +72569,7 @@ picomatch.toRegex = (source, options) => {
* @return {Object}
*/
-picomatch.constants = __webpack_require__(622);
+picomatch.constants = __webpack_require__(621);
/**
* Expose "picomatch"
@@ -72584,13 +72579,13 @@ module.exports = picomatch;
/***/ }),
-/* 620 */
+/* 619 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const utils = __webpack_require__(621);
+const utils = __webpack_require__(620);
const {
CHAR_ASTERISK, /* * */
@@ -72608,7 +72603,7 @@ const {
CHAR_RIGHT_CURLY_BRACE, /* } */
CHAR_RIGHT_PARENTHESES, /* ) */
CHAR_RIGHT_SQUARE_BRACKET /* ] */
-} = __webpack_require__(622);
+} = __webpack_require__(621);
const isPathSeparator = code => {
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
@@ -72810,7 +72805,7 @@ module.exports = (input, options) => {
/***/ }),
-/* 621 */
+/* 620 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -72822,7 +72817,7 @@ const {
REGEX_SPECIAL_CHARS,
REGEX_SPECIAL_CHARS_GLOBAL,
REGEX_REMOVE_BACKSLASH
-} = __webpack_require__(622);
+} = __webpack_require__(621);
exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str);
@@ -72860,7 +72855,7 @@ exports.escapeLast = (input, char, lastIdx) => {
/***/ }),
-/* 622 */
+/* 621 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -73046,14 +73041,14 @@ module.exports = {
/***/ }),
-/* 623 */
+/* 622 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const utils = __webpack_require__(621);
-const constants = __webpack_require__(622);
+const utils = __webpack_require__(620);
+const constants = __webpack_require__(621);
/**
* Constants
@@ -74064,13 +74059,13 @@ module.exports = parse;
/***/ }),
-/* 624 */
+/* 623 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const merge2 = __webpack_require__(590);
+const merge2 = __webpack_require__(589);
function merge(streams) {
const mergedStream = merge2(streams);
streams.forEach((stream) => {
@@ -74082,14 +74077,14 @@ exports.merge = merge;
/***/ }),
-/* 625 */
+/* 624 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const stream_1 = __webpack_require__(626);
-const provider_1 = __webpack_require__(653);
+const stream_1 = __webpack_require__(625);
+const provider_1 = __webpack_require__(652);
class ProviderAsync extends provider_1.default {
constructor() {
super(...arguments);
@@ -74117,16 +74112,16 @@ exports.default = ProviderAsync;
/***/ }),
-/* 626 */
+/* 625 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = __webpack_require__(27);
-const fsStat = __webpack_require__(627);
-const fsWalk = __webpack_require__(632);
-const reader_1 = __webpack_require__(652);
+const fsStat = __webpack_require__(626);
+const fsWalk = __webpack_require__(631);
+const reader_1 = __webpack_require__(651);
class ReaderStream extends reader_1.default {
constructor() {
super(...arguments);
@@ -74179,15 +74174,15 @@ exports.default = ReaderStream;
/***/ }),
-/* 627 */
+/* 626 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const async = __webpack_require__(628);
-const sync = __webpack_require__(629);
-const settings_1 = __webpack_require__(630);
+const async = __webpack_require__(627);
+const sync = __webpack_require__(628);
+const settings_1 = __webpack_require__(629);
exports.Settings = settings_1.default;
function stat(path, optionsOrSettingsOrCallback, callback) {
if (typeof optionsOrSettingsOrCallback === 'function') {
@@ -74210,7 +74205,7 @@ function getSettings(settingsOrOptions = {}) {
/***/ }),
-/* 628 */
+/* 627 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74248,7 +74243,7 @@ function callSuccessCallback(callback, result) {
/***/ }),
-/* 629 */
+/* 628 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74277,13 +74272,13 @@ exports.read = read;
/***/ }),
-/* 630 */
+/* 629 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fs = __webpack_require__(631);
+const fs = __webpack_require__(630);
class Settings {
constructor(_options = {}) {
this._options = _options;
@@ -74300,7 +74295,7 @@ exports.default = Settings;
/***/ }),
-/* 631 */
+/* 630 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74323,16 +74318,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter;
/***/ }),
-/* 632 */
+/* 631 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const async_1 = __webpack_require__(633);
-const stream_1 = __webpack_require__(648);
-const sync_1 = __webpack_require__(649);
-const settings_1 = __webpack_require__(651);
+const async_1 = __webpack_require__(632);
+const stream_1 = __webpack_require__(647);
+const sync_1 = __webpack_require__(648);
+const settings_1 = __webpack_require__(650);
exports.Settings = settings_1.default;
function walk(dir, optionsOrSettingsOrCallback, callback) {
if (typeof optionsOrSettingsOrCallback === 'function') {
@@ -74362,13 +74357,13 @@ function getSettings(settingsOrOptions = {}) {
/***/ }),
-/* 633 */
+/* 632 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const async_1 = __webpack_require__(634);
+const async_1 = __webpack_require__(633);
class AsyncProvider {
constructor(_root, _settings) {
this._root = _root;
@@ -74399,17 +74394,17 @@ function callSuccessCallback(callback, entries) {
/***/ }),
-/* 634 */
+/* 633 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = __webpack_require__(379);
-const fsScandir = __webpack_require__(635);
-const fastq = __webpack_require__(644);
-const common = __webpack_require__(646);
-const reader_1 = __webpack_require__(647);
+const fsScandir = __webpack_require__(634);
+const fastq = __webpack_require__(643);
+const common = __webpack_require__(645);
+const reader_1 = __webpack_require__(646);
class AsyncReader extends reader_1.default {
constructor(_root, _settings) {
super(_root, _settings);
@@ -74499,15 +74494,15 @@ exports.default = AsyncReader;
/***/ }),
-/* 635 */
+/* 634 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const async = __webpack_require__(636);
-const sync = __webpack_require__(641);
-const settings_1 = __webpack_require__(642);
+const async = __webpack_require__(635);
+const sync = __webpack_require__(640);
+const settings_1 = __webpack_require__(641);
exports.Settings = settings_1.default;
function scandir(path, optionsOrSettingsOrCallback, callback) {
if (typeof optionsOrSettingsOrCallback === 'function') {
@@ -74530,16 +74525,16 @@ function getSettings(settingsOrOptions = {}) {
/***/ }),
-/* 636 */
+/* 635 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsStat = __webpack_require__(627);
-const rpl = __webpack_require__(637);
-const constants_1 = __webpack_require__(638);
-const utils = __webpack_require__(639);
+const fsStat = __webpack_require__(626);
+const rpl = __webpack_require__(636);
+const constants_1 = __webpack_require__(637);
+const utils = __webpack_require__(638);
function read(dir, settings, callback) {
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
return readdirWithFileTypes(dir, settings, callback);
@@ -74628,7 +74623,7 @@ function callSuccessCallback(callback, result) {
/***/ }),
-/* 637 */
+/* 636 */
/***/ (function(module, exports) {
module.exports = runParallel
@@ -74682,7 +74677,7 @@ function runParallel (tasks, cb) {
/***/ }),
-/* 638 */
+/* 637 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74698,18 +74693,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSIO
/***/ }),
-/* 639 */
+/* 638 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fs = __webpack_require__(640);
+const fs = __webpack_require__(639);
exports.fs = fs;
/***/ }),
-/* 640 */
+/* 639 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74734,15 +74729,15 @@ exports.createDirentFromStats = createDirentFromStats;
/***/ }),
-/* 641 */
+/* 640 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsStat = __webpack_require__(627);
-const constants_1 = __webpack_require__(638);
-const utils = __webpack_require__(639);
+const fsStat = __webpack_require__(626);
+const constants_1 = __webpack_require__(637);
+const utils = __webpack_require__(638);
function read(dir, settings) {
if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
return readdirWithFileTypes(dir, settings);
@@ -74793,15 +74788,15 @@ exports.readdir = readdir;
/***/ }),
-/* 642 */
+/* 641 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(16);
-const fsStat = __webpack_require__(627);
-const fs = __webpack_require__(643);
+const fsStat = __webpack_require__(626);
+const fs = __webpack_require__(642);
class Settings {
constructor(_options = {}) {
this._options = _options;
@@ -74824,7 +74819,7 @@ exports.default = Settings;
/***/ }),
-/* 643 */
+/* 642 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -74849,13 +74844,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter;
/***/ }),
-/* 644 */
+/* 643 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-var reusify = __webpack_require__(645)
+var reusify = __webpack_require__(644)
function fastqueue (context, worker, concurrency) {
if (typeof context === 'function') {
@@ -75029,7 +75024,7 @@ module.exports = fastqueue
/***/ }),
-/* 645 */
+/* 644 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75069,7 +75064,7 @@ module.exports = reusify
/***/ }),
-/* 646 */
+/* 645 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75100,13 +75095,13 @@ exports.joinPathSegments = joinPathSegments;
/***/ }),
-/* 647 */
+/* 646 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const common = __webpack_require__(646);
+const common = __webpack_require__(645);
class Reader {
constructor(_root, _settings) {
this._root = _root;
@@ -75118,14 +75113,14 @@ exports.default = Reader;
/***/ }),
-/* 648 */
+/* 647 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = __webpack_require__(27);
-const async_1 = __webpack_require__(634);
+const async_1 = __webpack_require__(633);
class StreamProvider {
constructor(_root, _settings) {
this._root = _root;
@@ -75155,13 +75150,13 @@ exports.default = StreamProvider;
/***/ }),
-/* 649 */
+/* 648 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const sync_1 = __webpack_require__(650);
+const sync_1 = __webpack_require__(649);
class SyncProvider {
constructor(_root, _settings) {
this._root = _root;
@@ -75176,15 +75171,15 @@ exports.default = SyncProvider;
/***/ }),
-/* 650 */
+/* 649 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsScandir = __webpack_require__(635);
-const common = __webpack_require__(646);
-const reader_1 = __webpack_require__(647);
+const fsScandir = __webpack_require__(634);
+const common = __webpack_require__(645);
+const reader_1 = __webpack_require__(646);
class SyncReader extends reader_1.default {
constructor() {
super(...arguments);
@@ -75242,14 +75237,14 @@ exports.default = SyncReader;
/***/ }),
-/* 651 */
+/* 650 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(16);
-const fsScandir = __webpack_require__(635);
+const fsScandir = __webpack_require__(634);
class Settings {
constructor(_options = {}) {
this._options = _options;
@@ -75275,15 +75270,15 @@ exports.default = Settings;
/***/ }),
-/* 652 */
+/* 651 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(16);
-const fsStat = __webpack_require__(627);
-const utils = __webpack_require__(598);
+const fsStat = __webpack_require__(626);
+const utils = __webpack_require__(597);
class Reader {
constructor(_settings) {
this._settings = _settings;
@@ -75315,17 +75310,17 @@ exports.default = Reader;
/***/ }),
-/* 653 */
+/* 652 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = __webpack_require__(16);
-const deep_1 = __webpack_require__(654);
-const entry_1 = __webpack_require__(655);
-const error_1 = __webpack_require__(656);
-const entry_2 = __webpack_require__(657);
+const deep_1 = __webpack_require__(653);
+const entry_1 = __webpack_require__(654);
+const error_1 = __webpack_require__(655);
+const entry_2 = __webpack_require__(656);
class Provider {
constructor(_settings) {
this._settings = _settings;
@@ -75370,13 +75365,13 @@ exports.default = Provider;
/***/ }),
-/* 654 */
+/* 653 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(598);
+const utils = __webpack_require__(597);
class DeepFilter {
constructor(_settings, _micromatchOptions) {
this._settings = _settings;
@@ -75436,13 +75431,13 @@ exports.default = DeepFilter;
/***/ }),
-/* 655 */
+/* 654 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(598);
+const utils = __webpack_require__(597);
class EntryFilter {
constructor(_settings, _micromatchOptions) {
this._settings = _settings;
@@ -75497,13 +75492,13 @@ exports.default = EntryFilter;
/***/ }),
-/* 656 */
+/* 655 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(598);
+const utils = __webpack_require__(597);
class ErrorFilter {
constructor(_settings) {
this._settings = _settings;
@@ -75519,13 +75514,13 @@ exports.default = ErrorFilter;
/***/ }),
-/* 657 */
+/* 656 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const utils = __webpack_require__(598);
+const utils = __webpack_require__(597);
class EntryTransformer {
constructor(_settings) {
this._settings = _settings;
@@ -75552,15 +75547,15 @@ exports.default = EntryTransformer;
/***/ }),
-/* 658 */
+/* 657 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = __webpack_require__(27);
-const stream_2 = __webpack_require__(626);
-const provider_1 = __webpack_require__(653);
+const stream_2 = __webpack_require__(625);
+const provider_1 = __webpack_require__(652);
class ProviderStream extends provider_1.default {
constructor() {
super(...arguments);
@@ -75588,14 +75583,14 @@ exports.default = ProviderStream;
/***/ }),
-/* 659 */
+/* 658 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const sync_1 = __webpack_require__(660);
-const provider_1 = __webpack_require__(653);
+const sync_1 = __webpack_require__(659);
+const provider_1 = __webpack_require__(652);
class ProviderSync extends provider_1.default {
constructor() {
super(...arguments);
@@ -75618,15 +75613,15 @@ exports.default = ProviderSync;
/***/ }),
-/* 660 */
+/* 659 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-const fsStat = __webpack_require__(627);
-const fsWalk = __webpack_require__(632);
-const reader_1 = __webpack_require__(652);
+const fsStat = __webpack_require__(626);
+const fsWalk = __webpack_require__(631);
+const reader_1 = __webpack_require__(651);
class ReaderSync extends reader_1.default {
constructor() {
super(...arguments);
@@ -75668,7 +75663,7 @@ exports.default = ReaderSync;
/***/ }),
-/* 661 */
+/* 660 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75728,13 +75723,13 @@ exports.default = Settings;
/***/ }),
-/* 662 */
+/* 661 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const path = __webpack_require__(16);
-const pathType = __webpack_require__(663);
+const pathType = __webpack_require__(662);
const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];
@@ -75810,7 +75805,7 @@ module.exports.sync = (input, options) => {
/***/ }),
-/* 663 */
+/* 662 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75860,7 +75855,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink');
/***/ }),
-/* 664 */
+/* 663 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -75868,9 +75863,9 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink');
const {promisify} = __webpack_require__(29);
const fs = __webpack_require__(23);
const path = __webpack_require__(16);
-const fastGlob = __webpack_require__(596);
-const gitIgnore = __webpack_require__(665);
-const slash = __webpack_require__(666);
+const fastGlob = __webpack_require__(595);
+const gitIgnore = __webpack_require__(664);
+const slash = __webpack_require__(665);
const DEFAULT_IGNORE = [
'**/node_modules/**',
@@ -75984,7 +75979,7 @@ module.exports.sync = options => {
/***/ }),
-/* 665 */
+/* 664 */
/***/ (function(module, exports) {
// A simple implementation of make-array
@@ -76575,7 +76570,7 @@ if (
/***/ }),
-/* 666 */
+/* 665 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -76593,7 +76588,7 @@ module.exports = path => {
/***/ }),
-/* 667 */
+/* 666 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -76646,7 +76641,7 @@ module.exports = {
/***/ }),
-/* 668 */
+/* 667 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -76668,7 +76663,7 @@ module.exports = path_ => {
/***/ }),
-/* 669 */
+/* 668 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -76696,7 +76691,7 @@ module.exports = (childPath, parentPath) => {
/***/ }),
-/* 670 */
+/* 669 */
/***/ (function(module, exports, __webpack_require__) {
const assert = __webpack_require__(30)
@@ -76704,7 +76699,7 @@ const path = __webpack_require__(16)
const fs = __webpack_require__(23)
let glob = undefined
try {
- glob = __webpack_require__(591)
+ glob = __webpack_require__(590)
} catch (_err) {
// treat glob as optional.
}
@@ -77070,12 +77065,12 @@ rimraf.sync = rimrafSync
/***/ }),
-/* 671 */
+/* 670 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const AggregateError = __webpack_require__(672);
+const AggregateError = __webpack_require__(671);
module.exports = async (
iterable,
@@ -77158,13 +77153,13 @@ module.exports = async (
/***/ }),
-/* 672 */
+/* 671 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const indentString = __webpack_require__(673);
-const cleanStack = __webpack_require__(674);
+const indentString = __webpack_require__(672);
+const cleanStack = __webpack_require__(673);
const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, '');
@@ -77212,7 +77207,7 @@ module.exports = AggregateError;
/***/ }),
-/* 673 */
+/* 672 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -77254,7 +77249,7 @@ module.exports = (string, count = 1, options) => {
/***/ }),
-/* 674 */
+/* 673 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -77301,15 +77296,15 @@ module.exports = (stack, options) => {
/***/ }),
-/* 675 */
+/* 674 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const chalk = __webpack_require__(676);
-const cliCursor = __webpack_require__(680);
-const cliSpinners = __webpack_require__(684);
-const logSymbols = __webpack_require__(565);
+const chalk = __webpack_require__(675);
+const cliCursor = __webpack_require__(679);
+const cliSpinners = __webpack_require__(683);
+const logSymbols = __webpack_require__(564);
class Ora {
constructor(options) {
@@ -77456,16 +77451,16 @@ module.exports.promise = (action, options) => {
/***/ }),
-/* 676 */
+/* 675 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
const escapeStringRegexp = __webpack_require__(3);
-const ansiStyles = __webpack_require__(677);
-const stdoutColor = __webpack_require__(678).stdout;
+const ansiStyles = __webpack_require__(676);
+const stdoutColor = __webpack_require__(677).stdout;
-const template = __webpack_require__(679);
+const template = __webpack_require__(678);
const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
@@ -77691,7 +77686,7 @@ module.exports.default = module.exports; // For TypeScript
/***/ }),
-/* 677 */
+/* 676 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -77864,7 +77859,7 @@ Object.defineProperty(module, 'exports', {
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module)))
/***/ }),
-/* 678 */
+/* 677 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78006,7 +78001,7 @@ module.exports = {
/***/ }),
-/* 679 */
+/* 678 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78141,12 +78136,12 @@ module.exports = (chalk, tmp) => {
/***/ }),
-/* 680 */
+/* 679 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const restoreCursor = __webpack_require__(681);
+const restoreCursor = __webpack_require__(680);
let hidden = false;
@@ -78187,12 +78182,12 @@ exports.toggle = (force, stream) => {
/***/ }),
-/* 681 */
+/* 680 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const onetime = __webpack_require__(682);
+const onetime = __webpack_require__(681);
const signalExit = __webpack_require__(377);
module.exports = onetime(() => {
@@ -78203,12 +78198,12 @@ module.exports = onetime(() => {
/***/ }),
-/* 682 */
+/* 681 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const mimicFn = __webpack_require__(683);
+const mimicFn = __webpack_require__(682);
module.exports = (fn, opts) => {
// TODO: Remove this in v3
@@ -78249,7 +78244,7 @@ module.exports = (fn, opts) => {
/***/ }),
-/* 683 */
+/* 682 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78265,22 +78260,22 @@ module.exports = (to, from) => {
/***/ }),
-/* 684 */
+/* 683 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-module.exports = __webpack_require__(685);
+module.exports = __webpack_require__(684);
/***/ }),
-/* 685 */
+/* 684 */
/***/ (function(module) {
module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}");
/***/ }),
-/* 686 */
+/* 685 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -78289,8 +78284,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34);
-/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501);
+/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -78340,7 +78335,7 @@ const RunCommand = {
};
/***/ }),
-/* 687 */
+/* 686 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -78349,9 +78344,9 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34);
-/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501);
-/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(688);
+/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500);
+/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(687);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -78435,13 +78430,13 @@ const WatchCommand = {
};
/***/ }),
-/* 688 */
+/* 687 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; });
-/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(392);
+/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(391);
/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(169);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
@@ -78509,7 +78504,7 @@ function waitUntilWatchIsReady(stream, opts = {}) {
}
/***/ }),
-/* 689 */
+/* 688 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -78517,15 +78512,15 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; });
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(690);
+/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(689);
/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(691);
+/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(690);
/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515);
+/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(501);
-/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(698);
-/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(699);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(500);
+/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(697);
+/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(698);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -78613,7 +78608,7 @@ function toArray(value) {
}
/***/ }),
-/* 690 */
+/* 689 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78647,13 +78642,13 @@ module.exports = (str, count, opts) => {
/***/ }),
-/* 691 */
+/* 690 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stringWidth = __webpack_require__(692);
-const stripAnsi = __webpack_require__(696);
+const stringWidth = __webpack_require__(691);
+const stripAnsi = __webpack_require__(695);
const ESCAPES = new Set([
'\u001B',
@@ -78847,13 +78842,13 @@ module.exports = (str, cols, opts) => {
/***/ }),
-/* 692 */
+/* 691 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const stripAnsi = __webpack_require__(693);
-const isFullwidthCodePoint = __webpack_require__(695);
+const stripAnsi = __webpack_require__(692);
+const isFullwidthCodePoint = __webpack_require__(694);
module.exports = str => {
if (typeof str !== 'string' || str.length === 0) {
@@ -78890,18 +78885,18 @@ module.exports = str => {
/***/ }),
-/* 693 */
+/* 692 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiRegex = __webpack_require__(694);
+const ansiRegex = __webpack_require__(693);
module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
/***/ }),
-/* 694 */
+/* 693 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78918,7 +78913,7 @@ module.exports = () => {
/***/ }),
-/* 695 */
+/* 694 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78971,18 +78966,18 @@ module.exports = x => {
/***/ }),
-/* 696 */
+/* 695 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const ansiRegex = __webpack_require__(697);
+const ansiRegex = __webpack_require__(696);
module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input;
/***/ }),
-/* 697 */
+/* 696 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -78999,7 +78994,7 @@ module.exports = () => {
/***/ }),
-/* 698 */
+/* 697 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -79152,7 +79147,7 @@ function addProjectToTree(tree, pathParts, project) {
}
/***/ }),
-/* 699 */
+/* 698 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -79160,10 +79155,12 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; });
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(700);
+/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(699);
/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(501);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579);
+/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(703);
+/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578);
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -79192,6 +79189,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
+
/**
* Helper class for dealing with a set of projects as children of
* the Kibana project. The kbn/pm is currently implemented to be
@@ -79206,7 +79204,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
class Kibana {
static async loadFrom(rootPath) {
- return new Kibana((await Object(_projects__WEBPACK_IMPORTED_MODULE_2__["getProjects"])(rootPath, Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({
+ return new Kibana((await Object(_projects__WEBPACK_IMPORTED_MODULE_3__["getProjects"])(rootPath, Object(_config__WEBPACK_IMPORTED_MODULE_4__["getProjectPaths"])({
rootPath
}))));
}
@@ -79265,7 +79263,7 @@ class Kibana {
getProjectAndDeps(name) {
const project = this.getProject(name);
- return Object(_projects__WEBPACK_IMPORTED_MODULE_2__["includeTransitiveProjects"])([project], this.allWorkspaceProjects);
+ return Object(_projects__WEBPACK_IMPORTED_MODULE_3__["includeTransitiveProjects"])([project], this.allWorkspaceProjects);
}
/** filter the projects to just those matching certain paths/include/exclude tags */
@@ -79274,7 +79272,7 @@ class Kibana {
const allProjects = this.getAllProjects();
const filteredProjects = new Map();
const pkgJsonPaths = Array.from(allProjects.values()).map(p => p.packageJsonLocation);
- const filteredPkgJsonGlobs = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])(_objectSpread({}, options, {
+ const filteredPkgJsonGlobs = Object(_config__WEBPACK_IMPORTED_MODULE_4__["getProjectPaths"])(_objectSpread({}, options, {
rootPath: this.kibanaProject.path
})).map(g => path__WEBPACK_IMPORTED_MODULE_0___default.a.resolve(g, 'package.json'));
const matchingPkgJsonPaths = multimatch__WEBPACK_IMPORTED_MODULE_1___default()(pkgJsonPaths, filteredPkgJsonGlobs);
@@ -79292,18 +79290,26 @@ class Kibana {
return filteredProjects;
}
+ isPartOfRepo(project) {
+ return project.path === this.kibanaProject.path || is_path_inside__WEBPACK_IMPORTED_MODULE_2___default()(project.path, this.kibanaProject.path);
+ }
+
+ isOutsideRepo(project) {
+ return !this.isPartOfRepo(project);
+ }
+
}
/***/ }),
-/* 700 */
+/* 699 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
-const minimatch = __webpack_require__(505);
-const arrayUnion = __webpack_require__(701);
-const arrayDiffer = __webpack_require__(702);
-const arrify = __webpack_require__(703);
+const minimatch = __webpack_require__(504);
+const arrayUnion = __webpack_require__(700);
+const arrayDiffer = __webpack_require__(701);
+const arrify = __webpack_require__(702);
module.exports = (list, patterns, options = {}) => {
list = arrify(list);
@@ -79327,7 +79333,7 @@ module.exports = (list, patterns, options = {}) => {
/***/ }),
-/* 701 */
+/* 700 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79339,7 +79345,7 @@ module.exports = (...arguments_) => {
/***/ }),
-/* 702 */
+/* 701 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79354,7 +79360,7 @@ module.exports = arrayDiffer;
/***/ }),
-/* 703 */
+/* 702 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -79383,6 +79389,34 @@ const arrify = value => {
module.exports = arrify;
+/***/ }),
+/* 703 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+const path = __webpack_require__(16);
+
+module.exports = (childPath, parentPath) => {
+ childPath = path.resolve(childPath);
+ parentPath = path.resolve(parentPath);
+
+ if (process.platform === 'win32') {
+ childPath = childPath.toLowerCase();
+ parentPath = parentPath.toLowerCase();
+ }
+
+ if (childPath === parentPath) {
+ return false;
+ }
+
+ childPath += path.sep;
+ parentPath += path.sep;
+
+ return childPath.startsWith(parentPath);
+};
+
+
/***/ }),
/* 704 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -79425,15 +79459,15 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; });
/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706);
/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587);
+/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586);
/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579);
+/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578);
/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20);
/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34);
-/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517);
-/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(501);
+/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516);
+/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(500);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
@@ -79576,7 +79610,7 @@ const os = __webpack_require__(11);
const pAll = __webpack_require__(707);
const arrify = __webpack_require__(709);
const globby = __webpack_require__(710);
-const isGlob = __webpack_require__(605);
+const isGlob = __webpack_require__(604);
const cpFile = __webpack_require__(913);
const junk = __webpack_require__(925);
const CpyError = __webpack_require__(926);
@@ -80103,26 +80137,26 @@ if ('Set' in global) {
module.exports = glob
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
var inherits = __webpack_require__(714)
var EE = __webpack_require__(379).EventEmitter
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
+var isAbsolute = __webpack_require__(510)
var globSync = __webpack_require__(716)
var common = __webpack_require__(717)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
-var inflight = __webpack_require__(514)
+var inflight = __webpack_require__(513)
var util = __webpack_require__(29)
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
-var once = __webpack_require__(385)
+var once = __webpack_require__(384)
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
@@ -80908,14 +80942,14 @@ module.exports = globSync
globSync.GlobSync = GlobSync
var fs = __webpack_require__(23)
-var rp = __webpack_require__(503)
-var minimatch = __webpack_require__(505)
+var rp = __webpack_require__(502)
+var minimatch = __webpack_require__(504)
var Minimatch = minimatch.Minimatch
var Glob = __webpack_require__(713).Glob
var util = __webpack_require__(29)
var path = __webpack_require__(16)
var assert = __webpack_require__(30)
-var isAbsolute = __webpack_require__(511)
+var isAbsolute = __webpack_require__(510)
var common = __webpack_require__(717)
var alphasort = common.alphasort
var alphasorti = common.alphasorti
@@ -81411,8 +81445,8 @@ function ownProp (obj, field) {
}
var path = __webpack_require__(16)
-var minimatch = __webpack_require__(505)
-var isAbsolute = __webpack_require__(511)
+var minimatch = __webpack_require__(504)
+var isAbsolute = __webpack_require__(510)
var Minimatch = minimatch.Minimatch
function alphasorti (a, b) {
@@ -82064,7 +82098,7 @@ module.exports = function globParent(str) {
* Licensed under the MIT License.
*/
-var isExtglob = __webpack_require__(606);
+var isExtglob = __webpack_require__(605);
module.exports = function isGlob(str) {
if (typeof str !== 'string' || str === '') {
@@ -82245,7 +82279,7 @@ module.exports.win32 = win32;
* Released under the MIT License.
*/
-var isExtglob = __webpack_require__(606);
+var isExtglob = __webpack_require__(605);
var chars = { '{': '}', '(': ')', '[': ']'};
module.exports = function isGlob(str, options) {
@@ -92518,7 +92552,7 @@ function plural(ms, n, name) {
* Module dependencies.
*/
-var tty = __webpack_require__(480);
+var tty = __webpack_require__(479);
var util = __webpack_require__(29);
/**
@@ -96237,7 +96271,7 @@ void (function(root, factory) {
// Copyright 2014 Simon Lydell
// X11 (“MIT”) Licensed. (See LICENSE.)
-var url = __webpack_require__(454)
+var url = __webpack_require__(453)
function resolveUrl(/* ...urls */) {
return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) {
@@ -102525,7 +102559,7 @@ function plural(ms, n, name) {
* Module dependencies.
*/
-var tty = __webpack_require__(480);
+var tty = __webpack_require__(479);
var util = __webpack_require__(29);
/**
@@ -105778,7 +105812,7 @@ exports.flatten = flatten;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
-var merge2 = __webpack_require__(590);
+var merge2 = __webpack_require__(589);
/**
* Merge multiple streams and propagate their errors into one stream in parallel.
*/
@@ -109316,8 +109350,8 @@ module.exports = NestedError;
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return prepareExternalProjectDependencies; });
-/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(517);
-/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(516);
+/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(516);
+/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(515);
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json
index 444d46307b0593..a236db9eee18af 100644
--- a/packages/kbn-pm/package.json
+++ b/packages/kbn-pm/package.json
@@ -26,7 +26,7 @@
"@types/lodash.clonedeepwith": "^4.5.3",
"@types/log-symbols": "^2.0.0",
"@types/ncp": "^2.0.1",
- "@types/node": "^10.12.27",
+ "@types/node": ">=10.17.17 <10.20.0",
"@types/ora": "^1.3.5",
"@types/read-pkg": "^4.0.0",
"@types/strip-ansi": "^3.0.0",
@@ -42,12 +42,13 @@
"cpy": "^8.0.0",
"dedent": "^0.7.0",
"del": "^5.1.0",
- "execa": "^3.2.0",
+ "execa": "^4.0.0",
"getopts": "^2.2.4",
"glob": "^7.1.2",
"globby": "^8.0.1",
"has-ansi": "^3.0.0",
"indent-string": "^3.2.0",
+ "is-path-inside": "^3.0.2",
"lodash.clonedeepwith": "^4.5.0",
"log-symbols": "^2.2.0",
"multimatch": "^4.0.0",
diff --git a/packages/kbn-pm/src/config.ts b/packages/kbn-pm/src/config.ts
index 6ba8d58a26f88f..59b43b230e6034 100644
--- a/packages/kbn-pm/src/config.ts
+++ b/packages/kbn-pm/src/config.ts
@@ -48,6 +48,7 @@ export function getProjectPaths({ rootPath, ossOnly, skipKibanaPlugins }: Option
projectPaths.push(resolve(rootPath, 'x-pack'));
projectPaths.push(resolve(rootPath, 'x-pack/plugins/*'));
projectPaths.push(resolve(rootPath, 'x-pack/legacy/plugins/*'));
+ projectPaths.push(resolve(rootPath, 'x-pack/test/functional_with_es_ssl/fixtures/plugins/*'));
}
if (!skipKibanaPlugins) {
diff --git a/packages/kbn-pm/src/utils/kibana.ts b/packages/kbn-pm/src/utils/kibana.ts
index 36f697d19fc1f2..58af98b2a92dbd 100644
--- a/packages/kbn-pm/src/utils/kibana.ts
+++ b/packages/kbn-pm/src/utils/kibana.ts
@@ -20,6 +20,7 @@
import Path from 'path';
import multimatch from 'multimatch';
+import isPathInside from 'is-path-inside';
import { ProjectMap, getProjects, includeTransitiveProjects } from './projects';
import { Project } from './project';
@@ -121,4 +122,15 @@ export class Kibana {
return filteredProjects;
}
+
+ isPartOfRepo(project: Project) {
+ return (
+ project.path === this.kibanaProject.path ||
+ isPathInside(project.path, this.kibanaProject.path)
+ );
+ }
+
+ isOutsideRepo(project: Project) {
+ return !this.isPartOfRepo(project);
+ }
}
diff --git a/packages/kbn-pm/src/utils/project_checksums.ts b/packages/kbn-pm/src/utils/project_checksums.ts
index 2fd24c8fc9577a..572f2adb19bd99 100644
--- a/packages/kbn-pm/src/utils/project_checksums.ts
+++ b/packages/kbn-pm/src/utils/project_checksums.ts
@@ -43,7 +43,14 @@ async function getChangesForProjects(projects: ProjectMap, kbn: Kibana, log: Too
const { stdout } = await execa(
'git',
- ['ls-files', '-dmt', '--', ...Array.from(projects.values()).map(p => p.path)],
+ [
+ 'ls-files',
+ '-dmt',
+ '--',
+ ...Array.from(projects.values())
+ .filter(p => kbn.isPartOfRepo(p))
+ .map(p => p.path),
+ ],
{
cwd: kbn.getAbsolute(),
}
@@ -84,9 +91,14 @@ async function getChangesForProjects(projects: ProjectMap, kbn: Kibana, log: Too
}
const sortedRelevantProjects = Array.from(projects.values()).sort(projectBySpecificitySorter);
- const changesByProject = new Map();
+ const changesByProject = new Map();
for (const project of sortedRelevantProjects) {
+ if (kbn.isOutsideRepo(project)) {
+ changesByProject.set(project, undefined);
+ continue;
+ }
+
const ownChanges: Changes = new Map();
const prefix = kbn.getRelative(project.path);
@@ -114,6 +126,10 @@ async function getChangesForProjects(projects: ProjectMap, kbn: Kibana, log: Too
/** Get the latest commit sha for a project */
async function getLatestSha(project: Project, kbn: Kibana) {
+ if (kbn.isOutsideRepo(project)) {
+ return;
+ }
+
const { stdout } = await execa(
'git',
['log', '-n', '1', '--pretty=format:%H', '--', project.path],
@@ -175,7 +191,7 @@ function resolveDepsForProject(project: Project, yarnLock: YarnLock, kbn: Kibana
*/
async function getChecksum(
project: Project,
- changes: Changes,
+ changes: Changes | undefined,
yarnLock: YarnLock,
kbn: Kibana,
log: ToolingLog
@@ -185,7 +201,7 @@ async function getChecksum(
log.verbose(`[${project.name}] local sha:`, sha);
}
- if (Array.from(changes.values()).includes('invalid')) {
+ if (!changes || Array.from(changes.values()).includes('invalid')) {
log.warning(`[${project.name}] unable to determine local changes, caching disabled`);
return;
}
@@ -248,7 +264,7 @@ export async function getAllChecksums(kbn: Kibana, log: ToolingLog) {
Array.from(projects.values()).map(async project => {
cacheKeys.set(
project.name,
- await getChecksum(project, changesByProject.get(project)!, yarnLock, kbn, log)
+ await getChecksum(project, changesByProject.get(project), yarnLock, kbn, log)
);
})
);
diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json
index 73deadba0a6198..0b38554f7806c0 100644
--- a/packages/kbn-storybook/package.json
+++ b/packages/kbn-storybook/package.json
@@ -15,7 +15,6 @@
"@storybook/react": "^5.2.8",
"@storybook/theming": "^5.2.8",
"copy-webpack-plugin": "5.0.3",
- "execa": "1.0.0",
"fast-glob": "2.2.7",
"glob-watcher": "5.0.3",
"jest-specific-snapshot": "2.0.0",
diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts
index 11b9450f2af6eb..276a51c3a6a997 100644
--- a/packages/kbn-test/src/functional_test_runner/cli.ts
+++ b/packages/kbn-test/src/functional_test_runner/cli.ts
@@ -18,6 +18,7 @@
*/
import { resolve } from 'path';
+import { inspect } from 'util';
import { run, createFlagError, Flags } from '@kbn/dev-utils';
import { FunctionalTestRunner } from './functional_test_runner';
@@ -48,12 +49,15 @@ export function runFtrCli() {
kbnTestServer: {
installDir: parseInstallDir(flags),
},
+ suiteFiles: {
+ include: toArray(flags.include as string | string[]).map(makeAbsolutePath),
+ exclude: toArray(flags.exclude as string | string[]).map(makeAbsolutePath),
+ },
suiteTags: {
include: toArray(flags['include-tag'] as string | string[]),
exclude: toArray(flags['exclude-tag'] as string | string[]),
},
updateBaselines: flags.updateBaselines,
- excludeTestFiles: flags.exclude || undefined,
}
);
@@ -83,7 +87,11 @@ export function runFtrCli() {
}
};
- process.on('unhandledRejection', err => teardown(err));
+ process.on('unhandledRejection', err =>
+ teardown(
+ err instanceof Error ? err : new Error(`non-Error type rejection value: ${inspect(err)}`)
+ )
+ );
process.on('SIGTERM', () => teardown());
process.on('SIGINT', () => teardown());
@@ -104,7 +112,15 @@ export function runFtrCli() {
},
{
flags: {
- string: ['config', 'grep', 'exclude', 'include-tag', 'exclude-tag', 'kibana-install-dir'],
+ string: [
+ 'config',
+ 'grep',
+ 'include',
+ 'exclude',
+ 'include-tag',
+ 'exclude-tag',
+ 'kibana-install-dir',
+ ],
boolean: ['bail', 'invert', 'test-stats', 'updateBaselines', 'throttle', 'headless'],
default: {
config: 'test/functional/config.js',
@@ -115,7 +131,8 @@ export function runFtrCli() {
--bail stop tests after the first failure
--grep pattern used to select which tests to run
--invert invert grep to exclude tests
- --exclude=file path to a test file that should not be loaded
+ --include=file a test file to be included, pass multiple times for multiple files
+ --exclude=file a test file to be excluded, pass multiple times for multiple files
--include-tag=tag a tag to be included, pass multiple times for multiple tags
--exclude-tag=tag a tag to be excluded, pass multiple times for multiple tags
--test-stats print the number of tests (included and excluded) to STDERR
diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts
index 75623d6c088905..66f17ab579ec39 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts
+++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts
@@ -64,9 +64,16 @@ export const schema = Joi.object()
testFiles: Joi.array().items(Joi.string()),
testRunner: Joi.func(),
- excludeTestFiles: Joi.array()
- .items(Joi.string())
- .default([]),
+ suiteFiles: Joi.object()
+ .keys({
+ include: Joi.array()
+ .items(Joi.string())
+ .default([]),
+ exclude: Joi.array()
+ .items(Joi.string())
+ .default([]),
+ })
+ .default(),
suiteTags: Joi.object()
.keys({
@@ -248,5 +255,20 @@ export const schema = Joi.object()
fixedHeaderHeight: Joi.number().default(50),
})
.default(),
+
+ // settings for the security service if there is no defaultRole defined, then default to superuser role.
+ security: Joi.object()
+ .keys({
+ roles: Joi.object().default(),
+ defaultRoles: Joi.array()
+ .items(Joi.string())
+ .when('$primary', {
+ is: true,
+ then: Joi.array().min(1),
+ })
+ .default(['superuser']),
+ disableTestUser: Joi.boolean(),
+ })
+ .default(),
})
.default();
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
index 64fc51a04aac9b..1cac852a7e7130 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+import { relative } from 'path';
+import { REPO_ROOT } from '@kbn/dev-utils';
import { createAssignmentProxy } from './assignment_proxy';
import { wrapFunction } from './wrap_function';
import { wrapRunnableArgs } from './wrap_runnable_args';
@@ -65,6 +66,10 @@ export function decorateMochaUi(lifecycle, context) {
this._tags = [].concat(this._tags || [], tags);
};
+ const relativeFilePath = relative(REPO_ROOT, this.file);
+ this.tags(relativeFilePath);
+ this.suiteTag = relativeFilePath; // The tag that uniquely targets this suite/file
+
provider.call(this);
after(async () => {
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js
index 70b0c0874e5e91..6ee65b1b7e3941 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/load_test_files.js
@@ -31,28 +31,12 @@ import { decorateMochaUi } from './decorate_mocha_ui';
* @param {String} path
* @return {undefined} - mutates mocha, no return value
*/
-export const loadTestFiles = ({
- mocha,
- log,
- lifecycle,
- providers,
- paths,
- excludePaths,
- updateBaselines,
-}) => {
- const pendingExcludes = new Set(excludePaths.slice(0));
-
+export const loadTestFiles = ({ mocha, log, lifecycle, providers, paths, updateBaselines }) => {
const innerLoadTestFile = path => {
if (typeof path !== 'string' || !isAbsolute(path)) {
throw new TypeError('loadTestFile() only accepts absolute paths');
}
- if (pendingExcludes.has(path)) {
- pendingExcludes.delete(path);
- log.warning('Skipping test file %s', path);
- return;
- }
-
loadTracer(path, `testFile[${path}]`, () => {
log.verbose('Loading test file %s', path);
@@ -94,13 +78,4 @@ export const loadTestFiles = ({
};
paths.forEach(innerLoadTestFile);
-
- if (pendingExcludes.size) {
- throw new Error(
- `After loading all test files some exclude paths were not consumed:${[
- '',
- ...pendingExcludes,
- ].join('\n -')}`
- );
- }
};
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
index 326877919d9855..61851cece0e8ff 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js
@@ -18,6 +18,8 @@
*/
import Mocha from 'mocha';
+import { relative } from 'path';
+import { REPO_ROOT } from '@kbn/dev-utils';
import { loadTestFiles } from './load_test_files';
import { filterSuitesByTags } from './filter_suites_by_tags';
@@ -50,10 +52,20 @@ export async function setupMocha(lifecycle, log, config, providers) {
lifecycle,
providers,
paths: config.get('testFiles'),
- excludePaths: config.get('excludeTestFiles'),
updateBaselines: config.get('updateBaselines'),
});
+ // Each suite has a tag that is the path relative to the root of the repo
+ // So we just need to take input paths, make them relative to the root, and use them as tags
+ // Also, this is a separate filterSuitesByTags() call so that the test suites will be filtered first by
+ // files, then by tags. This way, you can target tags (like smoke) in a specific file.
+ filterSuitesByTags({
+ log,
+ mocha,
+ include: config.get('suiteFiles.include').map(file => relative(REPO_ROOT, file)),
+ exclude: config.get('suiteFiles.exclude').map(file => relative(REPO_ROOT, file)),
+ });
+
filterSuitesByTags({
log,
mocha,
diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap
index bbf8b38712ac17..434c374d5d23da 100644
--- a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap
+++ b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap
@@ -16,6 +16,8 @@ Options:
--bail Stop the test run at the first failure.
--grep Pattern to select which tests to run.
--updateBaselines Replace baseline screenshots with whatever is generated from the test.
+ --include Files that must included to be run, can be included multiple times.
+ --exclude Files that must NOT be included to be run, can be included multiple times.
--include-tag Tags that suites must include to be run, can be included multiple times.
--exclude-tag Tags that suites must NOT include to be run, can be included multiple times.
--assert-none-excluded Exit with 1/0 based on if any test is excluded with the current set of tags.
@@ -34,6 +36,10 @@ Object {
"createLogger": [Function],
"esFrom": "snapshot",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -52,6 +58,10 @@ Object {
"debug": true,
"esFrom": "snapshot",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -69,6 +79,10 @@ Object {
"createLogger": [Function],
"esFrom": "snapshot",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -90,6 +104,10 @@ Object {
"extraKbnOpts": Object {
"server.foo": "bar",
},
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -107,6 +125,10 @@ Object {
"esFrom": "snapshot",
"extraKbnOpts": undefined,
"quiet": true,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -124,6 +146,10 @@ Object {
"esFrom": "snapshot",
"extraKbnOpts": undefined,
"silent": true,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -140,6 +166,10 @@ Object {
"createLogger": [Function],
"esFrom": "source",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -156,6 +186,10 @@ Object {
"createLogger": [Function],
"esFrom": "source",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -173,6 +207,10 @@ Object {
"esFrom": "snapshot",
"extraKbnOpts": undefined,
"installDir": "foo",
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -190,6 +228,10 @@ Object {
"esFrom": "snapshot",
"extraKbnOpts": undefined,
"grep": "management",
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -206,6 +248,10 @@ Object {
"createLogger": [Function],
"esFrom": "snapshot",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
@@ -223,6 +269,10 @@ Object {
"createLogger": [Function],
"esFrom": "snapshot",
"extraKbnOpts": undefined,
+ "suiteFiles": Object {
+ "exclude": Array [],
+ "include": Array [],
+ },
"suiteTags": Object {
"exclude": Array [],
"include": Array [],
diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap
index b12739b3b5df5b..6ede71a6c39402 100644
--- a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap
+++ b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap
@@ -16,6 +16,8 @@ Options:
--bail Stop the test run at the first failure.
--grep Pattern to select which tests to run.
--updateBaselines Replace baseline screenshots with whatever is generated from the test.
+ --include Files that must included to be run, can be included multiple times.
+ --exclude Files that must NOT be included to be run, can be included multiple times.
--include-tag Tags that suites must include to be run, can be included multiple times.
--exclude-tag Tags that suites must NOT include to be run, can be included multiple times.
--assert-none-excluded Exit with 1/0 based on if any test is excluded with the current set of tags.
diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js
index b34006a38a45d8..7d2414305de8e7 100644
--- a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js
+++ b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js
@@ -46,6 +46,14 @@ const options = {
updateBaselines: {
desc: 'Replace baseline screenshots with whatever is generated from the test.',
},
+ include: {
+ arg: '',
+ desc: 'Files that must included to be run, can be included multiple times.',
+ },
+ exclude: {
+ arg: '',
+ desc: 'Files that must NOT be included to be run, can be included multiple times.',
+ },
'include-tag': {
arg: '',
desc: 'Tags that suites must include to be run, can be included multiple times.',
@@ -115,6 +123,13 @@ export function processOptions(userOptions, defaultConfigPaths) {
delete userOptions['kibana-install-dir'];
}
+ userOptions.suiteFiles = {
+ include: [].concat(userOptions.include || []),
+ exclude: [].concat(userOptions.exclude || []),
+ };
+ delete userOptions.include;
+ delete userOptions.exclude;
+
userOptions.suiteTags = {
include: [].concat(userOptions['include-tag'] || []),
exclude: [].concat(userOptions['exclude-tag'] || []),
diff --git a/packages/kbn-test/src/functional_tests/lib/run_ftr.js b/packages/kbn-test/src/functional_tests/lib/run_ftr.js
index 9b631e33f3b24c..14883ac977c431 100644
--- a/packages/kbn-test/src/functional_tests/lib/run_ftr.js
+++ b/packages/kbn-test/src/functional_tests/lib/run_ftr.js
@@ -22,7 +22,7 @@ import { CliError } from './run_cli';
async function createFtr({
configPath,
- options: { installDir, log, bail, grep, updateBaselines, suiteTags },
+ options: { installDir, log, bail, grep, updateBaselines, suiteFiles, suiteTags },
}) {
const config = await readConfigFile(log, configPath);
@@ -37,6 +37,10 @@ async function createFtr({
installDir,
},
updateBaselines,
+ suiteFiles: {
+ include: [...suiteFiles.include, ...config.get('suiteFiles.include')],
+ exclude: [...suiteFiles.exclude, ...config.get('suiteFiles.exclude')],
+ },
suiteTags: {
include: [...suiteTags.include, ...config.get('suiteTags.include')],
exclude: [...suiteTags.exclude, ...config.get('suiteTags.exclude')],
diff --git a/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js
index 7472e271bd1e9c..6edd0a551ebd08 100644
--- a/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js
+++ b/packages/kbn-test/src/mocha/__tests__/junit_report_generation.js
@@ -129,7 +129,7 @@ describe('dev/mocha/junit report generation', () => {
name: 'SUITE SUB_SUITE never runs',
'metadata-json': '{}',
},
- 'system-out': testFail['system-out'],
+ 'system-out': ['-- logs are only reported for failed tests --'],
skipped: [''],
});
});
diff --git a/packages/kbn-test/src/mocha/junit_report_generation.js b/packages/kbn-test/src/mocha/junit_report_generation.js
index 95e84117106a4d..b56741b48d3670 100644
--- a/packages/kbn-test/src/mocha/junit_report_generation.js
+++ b/packages/kbn-test/src/mocha/junit_report_generation.js
@@ -126,13 +126,15 @@ export function setupJUnitReportGeneration(runner, options = {}) {
[...results, ...skippedResults].forEach(result => {
const el = addTestcaseEl(result.node);
- el.ele('system-out').dat(escapeCdata(getSnapshotOfRunnableLogs(result.node) || ''));
if (result.failed) {
+ el.ele('system-out').dat(escapeCdata(getSnapshotOfRunnableLogs(result.node) || ''));
el.ele('failure').dat(escapeCdata(inspect(result.error)));
return;
}
+ el.ele('system-out').dat('-- logs are only reported for failed tests --');
+
if (result.skipped) {
el.ele('skipped');
}
diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts
index bd932c5961eca7..89007461b63e6c 100644
--- a/src/core/public/chrome/chrome_service.mock.ts
+++ b/src/core/public/chrome/chrome_service.mock.ts
@@ -61,8 +61,6 @@ const createStartContractMock = () => {
getBrand$: jest.fn(),
setIsVisible: jest.fn(),
getIsVisible$: jest.fn(),
- setIsCollapsed: jest.fn(),
- getIsCollapsed$: jest.fn(),
addApplicationClass: jest.fn(),
removeApplicationClass: jest.fn(),
getApplicationClasses$: jest.fn(),
@@ -73,15 +71,16 @@ const createStartContractMock = () => {
getHelpExtension$: jest.fn(),
setHelpExtension: jest.fn(),
setHelpSupportUrl: jest.fn(),
+ getIsNavDrawerLocked$: jest.fn(),
};
startContract.navLinks.getAll.mockReturnValue([]);
startContract.getBrand$.mockReturnValue(new BehaviorSubject({} as ChromeBrand));
startContract.getIsVisible$.mockReturnValue(new BehaviorSubject(false));
- startContract.getIsCollapsed$.mockReturnValue(new BehaviorSubject(false));
startContract.getApplicationClasses$.mockReturnValue(new BehaviorSubject(['class-name']));
startContract.getBadge$.mockReturnValue(new BehaviorSubject({} as ChromeBadge));
startContract.getBreadcrumbs$.mockReturnValue(new BehaviorSubject([{} as ChromeBreadcrumb]));
startContract.getHelpExtension$.mockReturnValue(new BehaviorSubject(undefined));
+ startContract.getIsNavDrawerLocked$.mockReturnValue(new BehaviorSubject(false));
return startContract;
};
diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts
index 9018b219736345..bf531aaa00facb 100644
--- a/src/core/public/chrome/chrome_service.test.ts
+++ b/src/core/public/chrome/chrome_service.test.ts
@@ -259,40 +259,6 @@ describe('start', () => {
});
});
- describe('is collapsed', () => {
- it('updates/emits isCollapsed', async () => {
- const { chrome, service } = await start();
- const promise = chrome
- .getIsCollapsed$()
- .pipe(toArray())
- .toPromise();
-
- chrome.setIsCollapsed(true);
- chrome.setIsCollapsed(false);
- chrome.setIsCollapsed(true);
- service.stop();
-
- await expect(promise).resolves.toMatchInlineSnapshot(`
- Array [
- false,
- true,
- false,
- true,
- ]
- `);
- });
-
- it('only stores true in localStorage', async () => {
- const { chrome } = await start();
-
- chrome.setIsCollapsed(true);
- expect(store.size).toBe(1);
-
- chrome.setIsCollapsed(false);
- expect(store.size).toBe(0);
- });
- });
-
describe('application classes', () => {
it('updates/emits the application classes', async () => {
const { chrome, service } = await start();
@@ -442,12 +408,12 @@ describe('start', () => {
});
describe('stop', () => {
- it('completes applicationClass$, isCollapsed$, breadcrumbs$, isVisible$, and brand$ observables', async () => {
+ it('completes applicationClass$, getIsNavDrawerLocked, breadcrumbs$, isVisible$, and brand$ observables', async () => {
const { chrome, service } = await start();
const promise = Rx.combineLatest(
chrome.getBrand$(),
chrome.getApplicationClasses$(),
- chrome.getIsCollapsed$(),
+ chrome.getIsNavDrawerLocked$(),
chrome.getBreadcrumbs$(),
chrome.getIsVisible$(),
chrome.getHelpExtension$()
@@ -465,7 +431,7 @@ describe('stop', () => {
Rx.combineLatest(
chrome.getBrand$(),
chrome.getApplicationClasses$(),
- chrome.getIsCollapsed$(),
+ chrome.getIsNavDrawerLocked$(),
chrome.getBreadcrumbs$(),
chrome.getIsVisible$(),
chrome.getHelpExtension$()
diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx
index 2b0b115ce068ee..7c9b644b8b9849 100644
--- a/src/core/public/chrome/chrome_service.tsx
+++ b/src/core/public/chrome/chrome_service.tsx
@@ -34,14 +34,14 @@ import { ChromeNavLinks, NavLinksService } from './nav_links';
import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed';
import { NavControlsService, ChromeNavControls } from './nav_controls';
import { DocTitleService, ChromeDocTitle } from './doc_title';
-import { LoadingIndicator, HeaderWrapper as Header } from './ui';
+import { LoadingIndicator, Header } from './ui';
import { DocLinksStart } from '../doc_links';
import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu';
import { KIBANA_ASK_ELASTIC_LINK } from './constants';
import { IUiSettingsClient } from '../ui_settings';
export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle };
-const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed';
+const IS_LOCKED_KEY = 'core.chrome.isLocked';
/** @public */
export interface ChromeBadge {
@@ -146,18 +146,25 @@ export class ChromeService {
const appTitle$ = new BehaviorSubject('Kibana');
const brand$ = new BehaviorSubject({});
- const isCollapsed$ = new BehaviorSubject(!!localStorage.getItem(IS_COLLAPSED_KEY));
const applicationClasses$ = new BehaviorSubject>(new Set());
const helpExtension$ = new BehaviorSubject(undefined);
const breadcrumbs$ = new BehaviorSubject([]);
const badge$ = new BehaviorSubject(undefined);
const helpSupportUrl$ = new BehaviorSubject(KIBANA_ASK_ELASTIC_LINK);
+ const isNavDrawerLocked$ = new BehaviorSubject(localStorage.getItem(IS_LOCKED_KEY) === 'true');
const navControls = this.navControls.start();
const navLinks = this.navLinks.start({ application, http });
const recentlyAccessed = await this.recentlyAccessed.start({ http });
const docTitle = this.docTitle.start({ document: window.document });
+ const setIsNavDrawerLocked = (isLocked: boolean) => {
+ isNavDrawerLocked$.next(isLocked);
+ localStorage.setItem(IS_LOCKED_KEY, `${isLocked}`);
+ };
+
+ const getIsNavDrawerLocked$ = isNavDrawerLocked$.pipe(takeUntil(this.stop$));
+
if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) {
notifications.toasts.addWarning(
i18n.translate('core.chrome.legacyBrowserWarning', {
@@ -193,6 +200,8 @@ export class ChromeService {
recentlyAccessed$={recentlyAccessed.get$()}
navControlsLeft$={navControls.getLeft$()}
navControlsRight$={navControls.getRight$()}
+ onIsLockedUpdate={setIsNavDrawerLocked}
+ isLocked$={getIsNavDrawerLocked$}
/>
),
@@ -214,17 +223,6 @@ export class ChromeService {
setIsVisible: (isVisible: boolean) => this.toggleHidden$.next(!isVisible),
- getIsCollapsed$: () => isCollapsed$.pipe(takeUntil(this.stop$)),
-
- setIsCollapsed: (isCollapsed: boolean) => {
- isCollapsed$.next(isCollapsed);
- if (isCollapsed) {
- localStorage.setItem(IS_COLLAPSED_KEY, 'true');
- } else {
- localStorage.removeItem(IS_COLLAPSED_KEY);
- }
- },
-
getApplicationClasses$: () =>
applicationClasses$.pipe(
map(set => [...set]),
@@ -262,6 +260,8 @@ export class ChromeService {
},
setHelpSupportUrl: (url: string) => helpSupportUrl$.next(url),
+
+ getIsNavDrawerLocked$: () => getIsNavDrawerLocked$,
};
}
@@ -353,16 +353,6 @@ export interface ChromeStart {
*/
setIsVisible(isVisible: boolean): void;
- /**
- * Get an observable of the current collapsed state of the chrome.
- */
- getIsCollapsed$(): Observable;
-
- /**
- * Set the collapsed state of the chrome navigation.
- */
- setIsCollapsed(isCollapsed: boolean): void;
-
/**
* Get the current set of classNames that will be set on the application container.
*/
@@ -413,6 +403,11 @@ export interface ChromeStart {
* @param url The updated support URL
*/
setHelpSupportUrl(url: string): void;
+
+ /**
+ * Get an observable of the current locked state of the nav drawer.
+ */
+ getIsNavDrawerLocked$(): Observable;
}
/** @internal */
diff --git a/src/core/public/chrome/ui/_loading_indicator.scss b/src/core/public/chrome/ui/_loading_indicator.scss
index 80694347393ce9..026c23b93b040f 100644
--- a/src/core/public/chrome/ui/_loading_indicator.scss
+++ b/src/core/public/chrome/ui/_loading_indicator.scss
@@ -22,29 +22,34 @@ $kbnLoadingIndicatorColor2: tint($euiColorAccent, 60%);
}
}
- .kbnLoadingIndicator__bar {
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- position: absolute;
- z-index: $euiZLevel1 + 1;
- visibility: visible;
- display: block;
- animation: kbn-animate-loading-indicator 2s linear infinite;
- background-color: $kbnLoadingIndicatorColor2;
- background-image: linear-gradient(to right,
- $kbnLoadingIndicatorColor1 0%,
- $kbnLoadingIndicatorColor1 50%,
- $kbnLoadingIndicatorColor2 50%,
- $kbnLoadingIndicatorColor2 100%
- );
- background-repeat: repeat-x;
- background-size: $kbnLoadingIndicatorBackgroundSize $kbnLoadingIndicatorBackgroundSize;
- width: 200%;
- }
+.kbnLoadingIndicator__bar {
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ position: absolute;
+ z-index: $euiZLevel1 + 1;
+ visibility: visible;
+ display: block;
+ animation: kbn-animate-loading-indicator 2s linear infinite;
+ background-color: $kbnLoadingIndicatorColor2;
+ background-image: linear-gradient(
+ to right,
+ $kbnLoadingIndicatorColor1 0%,
+ $kbnLoadingIndicatorColor1 50%,
+ $kbnLoadingIndicatorColor2 50%,
+ $kbnLoadingIndicatorColor2 100%
+ );
+ background-repeat: repeat-x;
+ background-size: $kbnLoadingIndicatorBackgroundSize $kbnLoadingIndicatorBackgroundSize;
+ width: 200%;
+}
- @keyframes kbn-animate-loading-indicator {
- from { transform: translateX(0); }
- to { transform: translateX(-$kbnLoadingIndicatorBackgroundSize); }
+@keyframes kbn-animate-loading-indicator {
+ from {
+ transform: translateX(0);
}
+ to {
+ transform: translateX(-$kbnLoadingIndicatorBackgroundSize);
+ }
+}
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index c9a583f39b30cb..4dec084fd8a83f 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -30,6 +30,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { Component, createRef } from 'react';
+import classnames from 'classnames';
import * as Rx from 'rxjs';
import {
ChromeBadge,
@@ -68,8 +69,8 @@ export interface HeaderProps {
navControlsLeft$: Rx.Observable;
navControlsRight$: Rx.Observable;
basePath: HttpStart['basePath'];
- isLocked?: boolean;
- onIsLockedUpdate?: OnIsLockedUpdate;
+ isLocked$: Rx.Observable;
+ onIsLockedUpdate: OnIsLockedUpdate;
}
interface State {
@@ -81,6 +82,7 @@ interface State {
navControlsLeft: readonly ChromeNavControl[];
navControlsRight: readonly ChromeNavControl[];
currentAppId: string | undefined;
+ isLocked: boolean;
}
export class Header extends Component {
@@ -99,6 +101,7 @@ export class Header extends Component {
navControlsLeft: [],
navControlsRight: [],
currentAppId: '',
+ isLocked: false,
};
}
@@ -109,11 +112,12 @@ export class Header extends Component {
this.props.forceAppSwitcherNavigation$,
this.props.navLinks$,
this.props.recentlyAccessed$,
- // Types for combineLatest only handle up to 6 inferred types so we combine these two separately.
+ // Types for combineLatest only handle up to 6 inferred types so we combine these separately.
Rx.combineLatest(
this.props.navControlsLeft$,
this.props.navControlsRight$,
- this.props.application.currentAppId$
+ this.props.application.currentAppId$,
+ this.props.isLocked$
)
).subscribe({
next: ([
@@ -122,7 +126,7 @@ export class Header extends Component {
forceNavigation,
navLinks,
recentlyAccessed,
- [navControlsLeft, navControlsRight, currentAppId],
+ [navControlsLeft, navControlsRight, currentAppId, isLocked],
]) => {
this.setState({
appTitle,
@@ -133,6 +137,7 @@ export class Header extends Component {
navControlsLeft,
navControlsRight,
currentAppId,
+ isLocked,
});
},
});
@@ -181,8 +186,16 @@ export class Header extends Component {
return null;
}
+ const className = classnames(
+ 'chrHeaderWrapper',
+ {
+ 'chrHeaderWrapper--navIsLocked': this.state.isLocked,
+ },
+ 'hide-for-sharing'
+ );
+
return (
-
+
@@ -220,7 +233,7 @@ export class Header extends Component {
= props => {
- const initialIsLocked = localStorage.getItem(IS_LOCKED_KEY);
- const [isLocked, setIsLocked] = useState(initialIsLocked === 'true');
- const setIsLockedStored = (locked: boolean) => {
- localStorage.setItem(IS_LOCKED_KEY, `${locked}`);
- setIsLocked(locked);
- };
- const className = classnames(
- 'chrHeaderWrapper',
- {
- 'chrHeaderWrapper--navIsLocked': isLocked,
- },
- 'hide-for-sharing'
- );
- return (
-
-
-
- );
-};
diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts
index 4521f1f74b31bb..49e002a66d9390 100644
--- a/src/core/public/chrome/ui/header/index.ts
+++ b/src/core/public/chrome/ui/header/index.ts
@@ -18,7 +18,6 @@
*/
export { Header, HeaderProps } from './header';
-export { HeaderWrapper } from './header_wrapper';
export {
ChromeHelpExtensionMenuLink,
ChromeHelpExtensionMenuCustomLink,
diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts
index 81b2fdfb0fcc0e..460e19b7d97801 100644
--- a/src/core/public/chrome/ui/index.ts
+++ b/src/core/public/chrome/ui/index.ts
@@ -20,7 +20,6 @@
export { LoadingIndicator } from './loading_indicator';
export {
Header,
- HeaderWrapper,
ChromeHelpExtensionMenuLink,
ChromeHelpExtensionMenuCustomLink,
ChromeHelpExtensionMenuDiscussLink,
diff --git a/src/core/public/overlays/modal/modal_service.tsx b/src/core/public/overlays/modal/modal_service.tsx
index 3cf1fe745be8e7..f3bbd5c94bdb4f 100644
--- a/src/core/public/overlays/modal/modal_service.tsx
+++ b/src/core/public/overlays/modal/modal_service.tsx
@@ -69,6 +69,7 @@ export interface OverlayModalConfirmOptions {
closeButtonAriaLabel?: string;
'data-test-subj'?: string;
defaultFocusedButton?: EuiConfirmModalProps['defaultFocusedButton'];
+ buttonColor?: EuiConfirmModalProps['buttonColor'];
}
/**
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index fa5dc745e69313..7428280b2dccbb 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -337,7 +337,7 @@ export interface ChromeStart {
getBrand$(): Observable;
getBreadcrumbs$(): Observable;
getHelpExtension$(): Observable;
- getIsCollapsed$(): Observable;
+ getIsNavDrawerLocked$(): Observable;
getIsVisible$(): Observable;
navControls: ChromeNavControls;
navLinks: ChromeNavLinks;
@@ -349,7 +349,6 @@ export interface ChromeStart {
setBreadcrumbs(newBreadcrumbs: ChromeBreadcrumb[]): void;
setHelpExtension(helpExtension?: ChromeHelpExtension): void;
setHelpSupportUrl(url: string): void;
- setIsCollapsed(isCollapsed: boolean): void;
setIsVisible(isVisible: boolean): void;
}
diff --git a/src/core/server/http/router/route.ts b/src/core/server/http/router/route.ts
index bb0a8616e72222..9789d266587afc 100644
--- a/src/core/server/http/router/route.ts
+++ b/src/core/server/http/router/route.ts
@@ -179,7 +179,7 @@ export interface RouteConfig {
* access to raw values.
* In some cases you may want to use another validation library. To do this, you need to
* instruct the `@kbn/config-schema` library to output **non-validated values** with
- * setting schema as `schema.object({}, { allowUnknowns: true })`;
+ * setting schema as `schema.object({}, { unknowns: 'allow' })`;
*
* @example
* ```ts
@@ -212,7 +212,7 @@ export interface RouteConfig
{
* path: 'path/{id}',
* validate: {
* // handler has access to raw non-validated params in runtime
- * params: schema.object({}, { allowUnknowns: true })
+ * params: schema.object({}, { unknowns: 'allow' })
* },
* },
* (context, req, res,) {
diff --git a/src/core/server/http/router/router.test.ts b/src/core/server/http/router/router.test.ts
index a936da6a40a9f1..9655e2153b863e 100644
--- a/src/core/server/http/router/router.test.ts
+++ b/src/core/server/http/router/router.test.ts
@@ -59,7 +59,7 @@ describe('Router', () => {
{
path: '/',
options: { body: { output: 'file' } } as any, // We explicitly don't support 'file'
- validate: { body: schema.object({}, { allowUnknowns: true }) },
+ validate: { body: schema.object({}, { unknowns: 'allow' }) },
},
(context, req, res) => res.ok({})
)
diff --git a/src/core/server/rendering/views/styles.tsx b/src/core/server/rendering/views/styles.tsx
index 9ab9f2ad0d6b86..71b42e34641186 100644
--- a/src/core/server/rendering/views/styles.tsx
+++ b/src/core/server/rendering/views/styles.tsx
@@ -53,7 +53,7 @@ export const Styles: FunctionComponent = ({ darkMode }) => {
.kbnWelcomeView {
line-height: 1.5;
- background-color: #FFF;
+ background-color: ${darkMode ? '#1D1E24' : '#FFF'};
height: 100%;
display: -webkit-box;
display: -webkit-flex;
@@ -97,6 +97,7 @@ export const Styles: FunctionComponent = ({ darkMode }) => {
line-height: 40px !important;
height: 40px !important;
color: #98a2b3;
+ color: ${darkMode ? '#98A2B3' : '#69707D'};
}
.kbnLoaderWrap {
@@ -128,7 +129,7 @@ export const Styles: FunctionComponent = ({ darkMode }) => {
width: 32px;
height: 4px;
overflow: hidden;
- background-color: #D3DAE6;
+ background-color: ${darkMode ? '#25262E' : '#F5F7FA'};
line-height: 1;
}
@@ -142,7 +143,7 @@ export const Styles: FunctionComponent = ({ darkMode }) => {
left: 0;
transform: scaleX(0) translateX(0%);
animation: kbnProgress 1s cubic-bezier(.694, .0482, .335, 1) infinite;
- background-color: #006DE4;
+ background-color: ${darkMode ? '#1BA9F5' : '#006DE4'};
}
@keyframes kbnProgress {
diff --git a/src/core/server/ui_settings/routes/set_many.ts b/src/core/server/ui_settings/routes/set_many.ts
index 5623c3fe11b807..d19a36a7ce7684 100644
--- a/src/core/server/ui_settings/routes/set_many.ts
+++ b/src/core/server/ui_settings/routes/set_many.ts
@@ -24,7 +24,7 @@ import { CannotOverrideError } from '../ui_settings_errors';
const validate = {
body: schema.object({
- changes: schema.object({}, { allowUnknowns: true }),
+ changes: schema.object({}, { unknowns: 'allow' }),
}),
};
diff --git a/src/core/server/ui_settings/ui_settings_config.ts b/src/core/server/ui_settings/ui_settings_config.ts
index a54d482a0296a4..a0ac48e2dd0892 100644
--- a/src/core/server/ui_settings/ui_settings_config.ts
+++ b/src/core/server/ui_settings/ui_settings_config.ts
@@ -39,7 +39,7 @@ const configSchema = schema.object({
})
),
},
- { allowUnknowns: true }
+ { unknowns: 'allow' }
),
});
diff --git a/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js b/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js
deleted file mode 100644
index 267ca74c7c42ab..00000000000000
--- a/src/legacy/core_plugins/kibana/common/utils/__tests__/shorten_dotted_string.js
+++ /dev/null
@@ -1,34 +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 { shortenDottedString } from '../shorten_dotted_string';
-
-describe('shortenDottedString', () => {
- it('Convert a dot.notated.string into a short string', () => {
- expect(shortenDottedString('dot.notated.string')).to.equal('d.n.string');
- });
-
- it('Ignores non-string values', () => {
- expect(shortenDottedString(true)).to.equal(true);
- expect(shortenDottedString(123)).to.equal(123);
- const obj = { key: 'val' };
- expect(shortenDottedString(obj)).to.equal(obj);
- });
-});
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
index 0c5329d8b259f8..3f81bfe5aadf26 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts
@@ -28,12 +28,11 @@ export { npSetup, npStart } from 'ui/new_platform';
export { KbnUrl } from 'ui/url/kbn_url';
// @ts-ignore
-export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url/index';
+export { KbnUrlProvider } from 'ui/url/index';
export { IInjector } from 'ui/chrome';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export {
configureAppAngularModule,
- ensureDefaultIndexPattern,
IPrivate,
migrateLegacyQuery,
PrivateProvider,
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
index fe0e7a1d3e6d00..9447b5384d1721 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
@@ -35,7 +35,6 @@ import {
KbnUrlProvider,
PrivateProvider,
PromiseServiceCreator,
- RedirectWhenMissingProvider,
} from '../legacy_imports';
// @ts-ignore
import { initDashboardApp } from './legacy_app';
@@ -146,8 +145,7 @@ function createLocalIconModule() {
function createLocalKbnUrlModule() {
angular
.module('app/dashboard/KbnUrl', ['app/dashboard/Private', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider))
- .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider));
+ .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
}
function createLocalConfigModule(core: AppMountContext['core']) {
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
index 35b510894179de..64abbdfb87d583 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/legacy_app.js
@@ -23,11 +23,12 @@ import dashboardTemplate from './dashboard_app.html';
import dashboardListingTemplate from './listing/dashboard_listing_ng_wrapper.html';
import { createHashHistory } from 'history';
-import { ensureDefaultIndexPattern } from '../legacy_imports';
import { initDashboardAppDirective } from './dashboard_app';
import { createDashboardEditUrl, DashboardConstants } from './dashboard_constants';
import {
createKbnUrlStateStorage,
+ ensureDefaultIndexPattern,
+ redirectWhenMissing,
InvalidJSONProperty,
SavedObjectNotFound,
} from '../../../../../../plugins/kibana_utils/public';
@@ -136,8 +137,8 @@ export function initDashboardApp(app, deps) {
});
},
resolve: {
- dash: function($rootScope, $route, redirectWhenMissing, kbnUrl, history) {
- return ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl).then(() => {
+ dash: function($route, history) {
+ return ensureDefaultIndexPattern(deps.core, deps.data, history).then(() => {
const savedObjectsClient = deps.savedObjectsClient;
const title = $route.current.params.title;
if (title) {
@@ -171,17 +172,18 @@ export function initDashboardApp(app, deps) {
controller: createNewDashboardCtrl,
requireUICapability: 'dashboard.createNew',
resolve: {
- dash: function(redirectWhenMissing, $rootScope, kbnUrl) {
- return ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl)
- .then(() => {
- return deps.savedDashboards.get();
- })
+ dash: history =>
+ ensureDefaultIndexPattern(deps.core, deps.data, history)
+ .then(() => deps.savedDashboards.get())
.catch(
redirectWhenMissing({
- dashboard: DashboardConstants.LANDING_PAGE_PATH,
+ history,
+ mapping: {
+ dashboard: DashboardConstants.LANDING_PAGE_PATH,
+ },
+ toastNotifications: deps.core.notifications.toasts,
})
- );
- },
+ ),
},
})
.when(createDashboardEditUrl(':id'), {
@@ -189,13 +191,11 @@ export function initDashboardApp(app, deps) {
template: dashboardTemplate,
controller: createNewDashboardCtrl,
resolve: {
- dash: function($rootScope, $route, redirectWhenMissing, kbnUrl, history) {
+ dash: function($route, kbnUrl, history) {
const id = $route.current.params.id;
- return ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl)
- .then(() => {
- return deps.savedDashboards.get(id);
- })
+ return ensureDefaultIndexPattern(deps.core, deps.data, history)
+ .then(() => deps.savedDashboards.get(id))
.then(savedDashboard => {
deps.chrome.recentlyAccessed.add(
savedDashboard.getFullPath(),
@@ -207,7 +207,7 @@ export function initDashboardApp(app, deps) {
.catch(error => {
// A corrupt dashboard was detected (e.g. with invalid JSON properties)
if (error instanceof InvalidJSONProperty) {
- deps.toastNotifications.addDanger(error.message);
+ deps.core.notifications.toasts.addDanger(error.message);
kbnUrl.redirect(DashboardConstants.LANDING_PAGE_PATH);
return;
}
@@ -221,7 +221,7 @@ export function initDashboardApp(app, deps) {
pathname: DashboardConstants.CREATE_NEW_DASHBOARD_URL,
});
- deps.toastNotifications.addWarning(
+ deps.core.notifications.toasts.addWarning(
i18n.translate('kbn.dashboard.urlWasRemovedInSixZeroWarningMessage', {
defaultMessage:
'The url "dashboard/create" was removed in 6.0. Please update your bookmarks.',
@@ -234,7 +234,11 @@ export function initDashboardApp(app, deps) {
})
.catch(
redirectWhenMissing({
- dashboard: DashboardConstants.LANDING_PAGE_PATH,
+ history,
+ mapping: {
+ dashboard: DashboardConstants.LANDING_PAGE_PATH,
+ },
+ toastNotifications: deps.core.notifications.toasts,
})
);
},
diff --git a/src/legacy/core_plugins/kibana/public/discover/build_services.ts b/src/legacy/core_plugins/kibana/public/discover/build_services.ts
index c58307adaf38c6..282eef0c983ebe 100644
--- a/src/legacy/core_plugins/kibana/public/discover/build_services.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/build_services.ts
@@ -16,6 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
+import { createHashHistory, History } from 'history';
+
import {
Capabilities,
ChromeStart,
@@ -46,6 +48,7 @@ export interface DiscoverServices {
data: DataPublicPluginStart;
docLinks: DocLinksStart;
docViewsRegistry: DocViewsRegistry;
+ history: History;
theme: ChartsPluginStart['theme'];
filterManager: FilterManager;
indexPatterns: IndexPatternsContract;
@@ -79,6 +82,7 @@ export async function buildServices(
data: plugins.data,
docLinks: core.docLinks,
docViewsRegistry,
+ history: createHashHistory(),
theme: plugins.charts.theme,
filterManager: plugins.data.query.filterManager,
getSavedSearchById: async (id: string) => savedObjectService.get(id),
diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
index 76d475c4f7f969..4d871bcb7a8585 100644
--- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts
@@ -27,7 +27,7 @@ import { CoreStart, LegacyCoreStart, IUiSettingsClient } from 'kibana/public';
// @ts-ignore
import { StateManagementConfigProvider } from 'ui/state_management/config_provider';
// @ts-ignore
-import { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
+import { KbnUrlProvider } from 'ui/url';
import { DataPublicPluginStart } from '../../../../../plugins/data/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
@@ -173,8 +173,7 @@ export function initializeInnerAngularModule(
function createLocalKbnUrlModule() {
angular
.module('discoverKbnUrl', ['discoverPrivate', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider))
- .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider));
+ .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
}
function createLocalConfigModule(uiSettings: IUiSettingsClient) {
diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts
index 57a9e4966d6d6f..725e94f16e2e82 100644
--- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts
@@ -53,17 +53,18 @@ export { wrapInI18nContext } from 'ui/i18n';
import { search } from '../../../../../plugins/data/public';
export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search;
// @ts-ignore
-export { shortenDottedString } from '../../common/utils/shorten_dotted_string';
-// @ts-ignore
export { intervalOptions } from 'ui/agg_types';
-export { subscribeWithScope } from '../../../../../plugins/kibana_legacy/public';
// @ts-ignore
export { timezoneProvider } from 'ui/vis/lib/timezone';
-export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
export {
+ unhashUrl,
+ redirectWhenMissing,
ensureDefaultIndexPattern,
+} from '../../../../../plugins/kibana_utils/public';
+export {
formatMsg,
formatStack,
+ subscribeWithScope,
} from '../../../../../plugins/kibana_legacy/public';
// EXPORT types
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx
index 26d8a5abb24719..1b3b16332fa4fa 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/field_name/field_name.tsx
@@ -21,7 +21,7 @@ import classNames from 'classnames';
import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
import { FieldIcon, FieldIconProps } from '../../../../../../../../../plugins/kibana_react/public';
-import { shortenDottedString } from '../../../../kibana_services';
+import { shortenDottedString } from '../../../helpers';
import { getFieldTypeName } from './field_type_name';
// property field is provided at discover's field chooser
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 f3334c9211e4bd..9a383565f4f430 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
@@ -50,6 +50,7 @@ import {
tabifyAggResponse,
getAngularModule,
ensureDefaultIndexPattern,
+ redirectWhenMissing,
} from '../../kibana_services';
const {
@@ -57,6 +58,7 @@ const {
chrome,
data,
docTitle,
+ history,
indexPatterns,
filterManager,
share,
@@ -113,10 +115,10 @@ app.config($routeProvider => {
template: indexTemplate,
reloadOnSearch: false,
resolve: {
- savedObjects: function(redirectWhenMissing, $route, kbnUrl, Promise, $rootScope) {
+ savedObjects: function($route, Promise) {
const savedSearchId = $route.current.params.id;
- return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl).then(() => {
- const { appStateContainer } = getState({});
+ return ensureDefaultIndexPattern(core, data, history).then(() => {
+ const { appStateContainer } = getState({ history });
const { index } = appStateContainer.getState();
return Promise.props({
ip: indexPatterns.getCache().then(indexPatternList => {
@@ -151,9 +153,13 @@ app.config($routeProvider => {
})
.catch(
redirectWhenMissing({
- search: '/discover',
- 'index-pattern':
- '/management/kibana/objects/savedSearches/' + $route.current.params.id,
+ history,
+ mapping: {
+ search: '/discover',
+ 'index-pattern':
+ '/management/kibana/objects/savedSearches/' + $route.current.params.id,
+ },
+ toastNotifications,
})
),
});
@@ -207,6 +213,7 @@ function discoverController(
} = getState({
defaultAppState: getStateDefaults(),
storeInSessionStorage: config.get('state:storeInSessionStorage'),
+ history,
});
if (appStateContainer.getState().index !== $scope.indexPattern.id) {
//used index pattern is different than the given by url/state which is invalid
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.test.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.test.ts
index af772cb5c76f18..3840fd0c2e3bed 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.test.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.test.ts
@@ -30,7 +30,7 @@ describe('Test discover state', () => {
history.push('/');
state = getState({
defaultAppState: { index: 'test' },
- hashHistory: history,
+ history,
});
await state.replaceUrlAppState({});
await state.startSync();
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.ts
index 10e7cd1d0c49d4..981855d1ee774e 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover_state.ts
@@ -17,7 +17,7 @@
* under the License.
*/
import { isEqual } from 'lodash';
-import { createHashHistory, History } from 'history';
+import { History } from 'history';
import {
createStateContainer,
createKbnUrlStateStorage,
@@ -65,9 +65,9 @@ interface GetStateParams {
*/
storeInSessionStorage?: boolean;
/**
- * Browser history used for testing
+ * Browser history
*/
- hashHistory?: History;
+ history: History;
}
export interface GetStateReturn {
@@ -121,11 +121,11 @@ const APP_STATE_URL_KEY = '_a';
export function getState({
defaultAppState = {},
storeInSessionStorage = false,
- hashHistory,
+ history,
}: GetStateParams): GetStateReturn {
const stateStorage = createKbnUrlStateStorage({
useHash: storeInSessionStorage,
- history: hashHistory ? hashHistory : createHashHistory(),
+ history,
});
const appStateFromUrl = stateStorage.get(APP_STATE_URL_KEY) as AppState;
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx
index a2ad18d59d935c..bd48b1e0838712 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { IndexPattern, shortenDottedString } from '../../../../../kibana_services';
+import { IndexPattern } from '../../../../../kibana_services';
+import { shortenDottedString } from '../../../../helpers';
export type SortOrder = [string, string];
export interface ColumnProps {
diff --git a/src/legacy/ui/public/chrome/services/index.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/index.ts
similarity index 92%
rename from src/legacy/ui/public/chrome/services/index.js
rename to src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/index.ts
index 3b3967f51b2ffa..7196c96989e97d 100644
--- a/src/legacy/ui/public/chrome/services/index.js
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/index.ts
@@ -17,4 +17,4 @@
* under the License.
*/
-import './global_nav_state';
+export { shortenDottedString } from './shorten_dotted_string';
diff --git a/src/legacy/core_plugins/kibana/common/utils/shorten_dotted_string.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/shorten_dotted_string.ts
similarity index 81%
rename from src/legacy/core_plugins/kibana/common/utils/shorten_dotted_string.js
rename to src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/shorten_dotted_string.ts
index ca76a2a537742f..9d78a96784339b 100644
--- a/src/legacy/core_plugins/kibana/common/utils/shorten_dotted_string.js
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/helpers/shorten_dotted_string.ts
@@ -22,10 +22,5 @@ const DOT_PREFIX_RE = /(.).+?\./g;
/**
* Convert a dot.notated.string into a short
* version (d.n.string)
- *
- * @param {string} str - the long string to convert
- * @return {string}
*/
-export function shortenDottedString(input) {
- return typeof input !== 'string' ? input : input.replace(DOT_PREFIX_RE, '$1.');
-}
+export const shortenDottedString = (input: string) => input.replace(DOT_PREFIX_RE, '$1.');
diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts
index 8e73a09480c41b..cb9ac0e01bb7f8 100644
--- a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts
+++ b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts
@@ -35,9 +35,15 @@ interface SavedObjectRegistryEntry {
title: string;
}
+export interface ISavedObjectsManagementRegistry {
+ register(service: SavedObjectRegistryEntry): void;
+ all(): SavedObjectRegistryEntry[];
+ get(id: string): SavedObjectRegistryEntry | undefined;
+}
+
const registry: SavedObjectRegistryEntry[] = [];
-export const savedObjectManagementRegistry = {
+export const savedObjectManagementRegistry: ISavedObjectsManagementRegistry = {
register: (service: SavedObjectRegistryEntry) => {
registry.push(service);
},
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js
index e3ab862cd84b7b..c5901ca6ee6bf4 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js
@@ -28,7 +28,6 @@ import { ObjectsTable } from './components/objects_table';
import { I18nContext } from 'ui/i18n';
import { get } from 'lodash';
import { npStart } from 'ui/new_platform';
-
import { getIndexBreadcrumbs } from './breadcrumbs';
const REACT_OBJECTS_TABLE_DOM_ELEMENT_ID = 'reactSavedObjectsTable';
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html
index 6efef7b48fa0e8..8bce0aabcd64a9 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html
@@ -1,203 +1,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js
index d1a8d6a1b14af5..a847055b40015a 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js
@@ -17,26 +17,20 @@
* under the License.
*/
-import _ from 'lodash';
-import { i18n } from '@kbn/i18n';
-import angular from 'angular';
+import React from 'react';
+import { render, unmountComponentAtNode } from 'react-dom';
+import 'angular';
import 'angular-elastic/elastic';
-import rison from 'rison-node';
-import { savedObjectManagementRegistry } from '../../saved_object_registry';
-import objectViewHTML from './_view.html';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
-import { fatalError, toastNotifications } from 'ui/notify';
-import 'ui/accessibility/kbn_ui_ace_keyboard_mode';
-import { isNumeric } from './lib/numeric';
-import { canViewInApp } from './lib/in_app_url';
+import { I18nContext } from 'ui/i18n';
import { npStart } from 'ui/new_platform';
-
-import { castEsToKbnFieldTypeName } from '../../../../../../../plugins/data/public';
-
+import objectViewHTML from './_view.html';
import { getViewBreadcrumbs } from './breadcrumbs';
+import { savedObjectManagementRegistry } from '../../saved_object_registry';
+import { SavedObjectEdition } from './saved_object_view';
-const location = 'SavedObject view';
+const REACT_OBJECTS_VIEW_DOM_ELEMENT_ID = 'reactSavedObjectsView';
uiRoutes.when('/management/kibana/objects/:service/:id', {
template: objectViewHTML,
@@ -44,261 +38,48 @@ uiRoutes.when('/management/kibana/objects/:service/:id', {
requireUICapability: 'management.kibana.objects',
});
+function createReactView($scope, $routeParams) {
+ const { service: serviceName, id: objectId, notFound } = $routeParams;
+
+ const { savedObjects, overlays, notifications, application } = npStart.core;
+
+ $scope.$$postDigest(() => {
+ const node = document.getElementById(REACT_OBJECTS_VIEW_DOM_ELEMENT_ID);
+ if (!node) {
+ return;
+ }
+
+ render(
+
+
+ ,
+ node
+ );
+ });
+}
+
+function destroyReactView() {
+ const node = document.getElementById(REACT_OBJECTS_VIEW_DOM_ELEMENT_ID);
+ node && unmountComponentAtNode(node);
+}
+
uiModules
.get('apps/management', ['monospaced.elastic'])
.directive('kbnManagementObjectsView', function() {
return {
restrict: 'E',
- controller: function($scope, $routeParams, $location, $window, $rootScope, uiCapabilities) {
- const serviceObj = savedObjectManagementRegistry.get($routeParams.service);
- const service = serviceObj.service;
- const savedObjectsClient = npStart.core.savedObjects.client;
- const { overlays } = npStart.core;
-
- /**
- * Creates a field definition and pushes it to the memo stack. This function
- * is designed to be used in conjunction with _.reduce(). If the
- * values is plain object it will recurse through all the keys till it hits
- * a string, number or an array.
- *
- * @param {array} memo The stack of fields
- * @param {mixed} value The value of the field
- * @param {string} key The key of the field
- * @param {object} collection This is a reference the collection being reduced
- * @param {array} parents The parent keys to the field
- * @returns {array}
- */
- const createField = function(memo, val, key, collection, parents) {
- if (Array.isArray(parents)) {
- parents.push(key);
- } else {
- parents = [key];
- }
-
- const field = { type: 'text', name: parents.join('.'), value: val };
-
- if (_.isString(field.value)) {
- try {
- field.value = angular.toJson(JSON.parse(field.value), true);
- field.type = 'json';
- } catch (err) {
- field.value = field.value;
- }
- } else if (isNumeric(field.value)) {
- field.type = 'number';
- } else if (Array.isArray(field.value)) {
- field.type = 'array';
- field.value = angular.toJson(field.value, true);
- } else if (_.isBoolean(field.value)) {
- field.type = 'boolean';
- field.value = field.value;
- } else if (_.isPlainObject(field.value)) {
- // do something recursive
- return _.reduce(field.value, _.partialRight(createField, parents), memo);
- }
-
- memo.push(field);
-
- // once the field is added to the object you need to pop the parents
- // to remove it since we've hit the end of the branch.
- parents.pop();
- return memo;
- };
-
- const readObjectClass = function(fields, Class) {
- const fieldMap = _.indexBy(fields, 'name');
-
- _.forOwn(Class.mapping, function(esType, name) {
- if (fieldMap[name]) return;
-
- fields.push({
- name: name,
- type: (function() {
- switch (castEsToKbnFieldTypeName(esType)) {
- case 'string':
- return 'text';
- case 'number':
- return 'number';
- case 'boolean':
- return 'boolean';
- default:
- return 'json';
- }
- })(),
- });
- });
-
- if (Class.searchSource && !fieldMap['kibanaSavedObjectMeta.searchSourceJSON']) {
- fields.push({
- name: 'kibanaSavedObjectMeta.searchSourceJSON',
- type: 'json',
- value: '{}',
- });
- }
-
- if (!fieldMap.references) {
- fields.push({
- name: 'references',
- type: 'array',
- value: '[]',
- });
- }
- };
-
- const { edit: canEdit, delete: canDelete } = uiCapabilities.savedObjectsManagement;
- $scope.canEdit = canEdit;
- $scope.canDelete = canDelete;
- $scope.canViewInApp = canViewInApp(uiCapabilities, service.type);
-
- $scope.notFound = $routeParams.notFound;
-
- $scope.title = service.type;
-
- savedObjectsClient
- .get(service.type, $routeParams.id)
- .then(function(obj) {
- $scope.obj = obj;
- $scope.link = service.urlFor(obj.id);
-
- const fields = _.reduce(obj.attributes, createField, []);
- // Special handling for references which isn't within "attributes"
- createField(fields, obj.references, 'references');
-
- if (service.Class) readObjectClass(fields, service.Class);
-
- // sorts twice since we want numerical sort to prioritize over name,
- // and sortBy will do string comparison if trying to match against strings
- const nameSortedFields = _.sortBy(fields, 'name');
- $scope.$evalAsync(() => {
- $scope.fields = _.sortBy(nameSortedFields, field => {
- const orderIndex = service.Class.fieldOrder
- ? service.Class.fieldOrder.indexOf(field.name)
- : -1;
- return orderIndex > -1 ? orderIndex : Infinity;
- });
- });
- $scope.$digest();
- })
- .catch(error => fatalError(error, location));
-
- // This handles the validation of the Ace Editor. Since we don't have any
- // other hooks into the editors to tell us if the content is valid or not
- // we need to use the annotations to see if they have any errors. If they
- // do then we push the field.name to aceInvalidEditor variable.
- // Otherwise we remove it.
- const loadedEditors = [];
- $scope.aceInvalidEditors = [];
-
- $scope.aceLoaded = function(editor) {
- if (_.contains(loadedEditors, editor)) return;
- loadedEditors.push(editor);
-
- editor.$blockScrolling = Infinity;
-
- const session = editor.getSession();
- const fieldName = editor.container.id;
-
- session.setTabSize(2);
- session.setUseSoftTabs(true);
- session.on('changeAnnotation', function() {
- const annotations = session.getAnnotations();
- if (_.some(annotations, { type: 'error' })) {
- if (!_.contains($scope.aceInvalidEditors, fieldName)) {
- $scope.aceInvalidEditors.push(fieldName);
- }
- } else {
- $scope.aceInvalidEditors = _.without($scope.aceInvalidEditors, fieldName);
- }
-
- if (!$rootScope.$$phase) $scope.$apply();
- });
- };
-
- $scope.cancel = function() {
- $window.history.back();
- return false;
- };
-
- /**
- * Deletes an object and sets the notification
- * @param {type} name description
- * @returns {type} description
- */
- $scope.delete = function() {
- function doDelete() {
- savedObjectsClient
- .delete(service.type, $routeParams.id)
- .then(function() {
- return redirectHandler('deleted');
- })
- .catch(error => fatalError(error, location));
- }
- const confirmModalOptions = {
- confirmButtonText: i18n.translate(
- 'kbn.management.objects.confirmModalOptions.deleteButtonLabel',
- {
- defaultMessage: 'Delete',
- }
- ),
- title: i18n.translate('kbn.management.objects.confirmModalOptions.modalTitle', {
- defaultMessage: 'Delete saved Kibana object?',
- }),
- };
-
- overlays
- .openConfirm(
- i18n.translate('kbn.management.objects.confirmModalOptions.modalDescription', {
- defaultMessage: "You can't recover deleted objects",
- }),
- confirmModalOptions
- )
- .then(isConfirmed => {
- if (isConfirmed) {
- doDelete();
- }
- });
- };
-
- $scope.submit = function() {
- const source = _.cloneDeep($scope.obj.attributes);
-
- _.each($scope.fields, function(field) {
- let value = field.value;
-
- if (field.type === 'number') {
- value = Number(field.value);
- }
-
- if (field.type === 'array') {
- value = JSON.parse(field.value);
- }
-
- _.set(source, field.name, value);
- });
-
- const { references, ...attributes } = source;
-
- savedObjectsClient
- .update(service.type, $routeParams.id, attributes, { references })
- .then(function() {
- return redirectHandler('updated');
- })
- .catch(error => fatalError(error, location));
- };
-
- function redirectHandler(action) {
- $location.path('/management/kibana/objects').search({
- _a: rison.encode({
- tab: serviceObj.title,
- }),
- });
-
- toastNotifications.addSuccess(
- `${_.capitalize(action)} '${
- $scope.obj.attributes.title
- }' ${$scope.title.toLowerCase()} object`
- );
- }
+ controller: function($scope, $routeParams) {
+ createReactView($scope, $routeParams);
+ $scope.$on('$destroy', destroyReactView);
},
};
});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap
new file mode 100644
index 00000000000000..7e1f7ea12b0147
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap
@@ -0,0 +1,165 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Intro component renders correctly 1`] = `
+
+
+
+
+
+
+
+
+ Edit search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Delete search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap
new file mode 100644
index 00000000000000..812031b4b363c7
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap
@@ -0,0 +1,67 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Intro component renders correctly 1`] = `
+
+
+ }
+ >
+
+
+
+
+
+
+
+ Proceed with caution!
+
+
+
+
+
+
+
+ Modifying objects is for advanced users only. Object properties are not validated and invalid objects could cause errors, data loss, or worse. Unless someone with intimate knowledge of the code told you to be in here, you probably shouldn’t be.
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap
new file mode 100644
index 00000000000000..ac565a000813e0
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap
@@ -0,0 +1,301 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotFoundErrors component renders correctly for index-pattern type 1`] = `
+
+
+ }
+ >
+
+
+
+
+
+
+
+ There is a problem with this saved object
+
+
+
+
+
+
+
+ The index pattern associated with this object no longer exists.
+
+
+
+
+ If you know what this error means, go ahead and fix it — otherwise click the delete button above.
+
+
+
+
+
+
+
+`;
+
+exports[`NotFoundErrors component renders correctly for index-pattern-field type 1`] = `
+
+
+ }
+ >
+
+
+
+
+
+
+
+ There is a problem with this saved object
+
+
+
+
+
+
+
+ A field associated with this object no longer exists in the index pattern.
+
+
+
+
+ If you know what this error means, go ahead and fix it — otherwise click the delete button above.
+
+
+
+
+
+
+
+`;
+
+exports[`NotFoundErrors component renders correctly for search type 1`] = `
+
+
+ }
+ >
+
+
+
+
+
+
+
+ There is a problem with this saved object
+
+
+
+
+
+
+
+ The saved search associated with this object no longer exists.
+
+
+
+
+ If you know what this error means, go ahead and fix it — otherwise click the delete button above.
+
+
+
+
+
+
+
+`;
+
+exports[`NotFoundErrors component renders correctly for unknown type 1`] = `
+
+
+ }
+ >
+
+
+
+
+
+
+
+ There is a problem with this saved object
+
+
+
+
+
+
+
+
+ If you know what this error means, go ahead and fix it — otherwise click the delete button above.
+
+
+
+
+
+
+
+`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.test.tsx
new file mode 100644
index 00000000000000..051c666f782043
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.test.tsx
@@ -0,0 +1,95 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import { I18nProvider } from '@kbn/i18n/react';
+import { Field } from './field';
+import { FieldState, FieldType } from '../../types';
+
+describe('Field component', () => {
+ const mountField = (props: {
+ type: FieldType;
+ name: string;
+ value: any;
+ disabled: boolean;
+ state?: FieldState;
+ onChange: (name: string, state: FieldState) => void;
+ }) =>
+ mount(
+
+
+
+ ).find('Field');
+
+ const defaultProps = {
+ type: 'text' as FieldType,
+ name: 'field',
+ value: '',
+ disabled: false,
+ state: undefined,
+ onChange: (name: string, state: FieldState) => undefined,
+ };
+
+ it('uses the field name as the label', () => {
+ let mounted = mountField({ ...defaultProps, name: 'some.name' });
+ expect(mounted.find('EuiFormLabel').text()).toMatchInlineSnapshot(`"some.name"`);
+
+ mounted = mountField({ ...defaultProps, name: 'someother.name' });
+ expect(mounted.find('EuiFormLabel').text()).toMatchInlineSnapshot(`"someother.name"`);
+ });
+
+ it('renders a EuiCodeEditor for json type', () => {
+ const mounted = mountField({ ...defaultProps, type: 'json' });
+ expect(mounted.exists('EuiCodeEditor')).toEqual(true);
+ });
+
+ it('renders a EuiCodeEditor for array type', () => {
+ const mounted = mountField({ ...defaultProps, type: 'array' });
+ expect(mounted.exists('EuiCodeEditor')).toEqual(true);
+ });
+
+ it('renders a EuiSwitch for boolean type', () => {
+ const mounted = mountField({ ...defaultProps, type: 'boolean' });
+ expect(mounted.exists('EuiSwitch')).toEqual(true);
+ });
+
+ it('display correct label for boolean type depending on value', () => {
+ let mounted = mountField({ ...defaultProps, type: 'boolean', value: true });
+ expect(mounted.find('EuiSwitch').text()).toMatchInlineSnapshot(`"On"`);
+
+ mounted = mountField({ ...defaultProps, type: 'boolean', value: false });
+ expect(mounted.find('EuiSwitch').text()).toMatchInlineSnapshot(`"Off"`);
+ });
+
+ it('renders a EuiFieldNumber for number type', () => {
+ const mounted = mountField({ ...defaultProps, type: 'number' });
+ expect(mounted.exists('EuiFieldNumber')).toEqual(true);
+ });
+
+ it('renders a EuiFieldText for text type', () => {
+ const mounted = mountField({ ...defaultProps, type: 'text' });
+ expect(mounted.exists('EuiFieldText')).toEqual(true);
+ });
+
+ it('renders a EuiFieldText as fallback', () => {
+ const mounted = mountField({ ...defaultProps, type: 'unknown-type' as any });
+ expect(mounted.exists('EuiFieldText')).toEqual(true);
+ });
+});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx
new file mode 100644
index 00000000000000..1ed0b57e400b87
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx
@@ -0,0 +1,162 @@
+/*
+ * 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, { PureComponent } from 'react';
+import {
+ EuiFieldNumber,
+ EuiFieldText,
+ EuiFormRow,
+ EuiSwitch,
+ // @ts-ignore
+ EuiCodeEditor,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { FieldState, FieldType } from '../../types';
+
+interface FieldProps {
+ type: FieldType;
+ name: string;
+ value: any;
+ disabled: boolean;
+ state?: FieldState;
+ onChange: (name: string, state: FieldState) => void;
+}
+
+export class Field extends PureComponent {
+ render() {
+ const { name } = this.props;
+
+ return (
+
+ {this.renderField()}
+
+ );
+ }
+
+ onCodeEditorChange(targetValue: any) {
+ const { name, onChange } = this.props;
+ let invalid = false;
+ try {
+ JSON.parse(targetValue);
+ } catch (e) {
+ invalid = true;
+ }
+ onChange(name, {
+ value: targetValue,
+ invalid,
+ });
+ }
+
+ onFieldChange(targetValue: any) {
+ const { name, type, onChange } = this.props;
+
+ let newParsedValue = targetValue;
+ let invalid = false;
+ if (type === 'number') {
+ try {
+ newParsedValue = Number(newParsedValue);
+ } catch (e) {
+ invalid = true;
+ }
+ }
+ onChange(name, {
+ value: newParsedValue,
+ invalid,
+ });
+ }
+
+ renderField() {
+ const { type, name, state, disabled } = this.props;
+ const currentValue = state?.value ?? this.props.value;
+
+ switch (type) {
+ case 'number':
+ return (
+ this.onFieldChange(e.target.value)}
+ disabled={disabled}
+ data-test-subj={`savedObjects-editField-${name}`}
+ />
+ );
+ case 'boolean':
+ return (
+
+ ) : (
+
+ )
+ }
+ checked={!!currentValue}
+ onChange={e => this.onFieldChange(e.target.checked)}
+ disabled={disabled}
+ data-test-subj={`savedObjects-editField-${name}`}
+ />
+ );
+ case 'json':
+ case 'array':
+ return (
+
+ this.onCodeEditorChange(value)}
+ width="100%"
+ height="auto"
+ minLines={6}
+ maxLines={30}
+ isReadOnly={disabled}
+ setOptions={{
+ showLineNumbers: true,
+ tabSize: 2,
+ useSoftTabs: true,
+ }}
+ editorProps={{
+ $blockScrolling: Infinity,
+ }}
+ showGutter={true}
+ />
+
+ );
+ default:
+ return (
+ this.onFieldChange(e.target.value)}
+ disabled={disabled}
+ data-test-subj={`savedObjects-editField-${name}`}
+ />
+ );
+ }
+ }
+
+ private get fieldId() {
+ const { name } = this.props;
+ return `savedObjects-editField-${name}`;
+ }
+}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx
new file mode 100644
index 00000000000000..7270d41eef5290
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx
@@ -0,0 +1,186 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { Component } from 'react';
+import {
+ EuiForm,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButton,
+ EuiButtonEmpty,
+ EuiSpacer,
+} from '@elastic/eui';
+import { cloneDeep, set } from 'lodash';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+ SimpleSavedObject,
+ SavedObjectsClientContract,
+} from '../../../../../../../../../core/public';
+
+import { SavedObjectLoader } from '../../../../../../../../../plugins/saved_objects/public';
+import { Field } from './field';
+import { ObjectField, FieldState, SubmittedFormData } from '../../types';
+import { createFieldList } from '../../lib/create_field_list';
+
+interface FormProps {
+ object: SimpleSavedObject;
+ service: SavedObjectLoader;
+ savedObjectsClient: SavedObjectsClientContract;
+ editionEnabled: boolean;
+ onSave: (form: SubmittedFormData) => Promise;
+}
+
+interface FormState {
+ fields: ObjectField[];
+ fieldStates: Record;
+ submitting: boolean;
+}
+
+export class Form extends Component {
+ constructor(props: FormProps) {
+ super(props);
+ this.state = {
+ fields: [],
+ fieldStates: {},
+ submitting: false,
+ };
+ }
+
+ componentDidMount() {
+ const { object, service } = this.props;
+
+ const fields = createFieldList(object, service);
+
+ this.setState({
+ fields,
+ });
+ }
+
+ render() {
+ const { editionEnabled, service } = this.props;
+ const { fields, fieldStates, submitting } = this.state;
+ const isValid = this.isFormValid();
+ return (
+
+ {fields.map(field => (
+
+ ))}
+
+
+ {editionEnabled && (
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
+
+ );
+ }
+
+ handleFieldChange = (name: string, newState: FieldState) => {
+ this.setState({
+ fieldStates: {
+ ...this.state.fieldStates,
+ [name]: newState,
+ },
+ });
+ };
+
+ isFormValid() {
+ const { fieldStates } = this.state;
+ return !Object.values(fieldStates).some(state => state.invalid === true);
+ }
+
+ onCancel = () => {
+ window.history.back();
+ };
+
+ onSubmit = async () => {
+ const { object, onSave } = this.props;
+ const { fields, fieldStates } = this.state;
+
+ if (!this.isFormValid()) {
+ return;
+ }
+
+ this.setState({
+ submitting: true,
+ });
+
+ const source = cloneDeep(object.attributes as any);
+ fields.forEach(field => {
+ let value = fieldStates[field.name]?.value ?? field.value;
+
+ if (field.type === 'array' && typeof value === 'string') {
+ value = JSON.parse(value);
+ }
+
+ set(source, field.name, value);
+ });
+
+ const { references, ...attributes } = source;
+
+ await onSave({ attributes, references });
+
+ this.setState({
+ submitting: false,
+ });
+ };
+}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.test.tsx
new file mode 100644
index 00000000000000..ccd2df3c559481
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.test.tsx
@@ -0,0 +1,125 @@
+/*
+ * 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 { mount } from 'enzyme';
+import { I18nProvider } from '@kbn/i18n/react';
+import { Header } from './header';
+
+describe('Intro component', () => {
+ const mountHeader = (props: {
+ canEdit: boolean;
+ canDelete: boolean;
+ canViewInApp: boolean;
+ type: string;
+ viewUrl: string;
+ onDeleteClick: () => void;
+ }) =>
+ mount(
+
+
+
+ ).find('Header');
+
+ const defaultProps = {
+ type: 'search',
+ canEdit: true,
+ canDelete: true,
+ canViewInApp: true,
+ viewUrl: '/some-url',
+ onDeleteClick: () => undefined,
+ };
+
+ it('renders correctly', () => {
+ const mounted = mountHeader({
+ ...defaultProps,
+ });
+ expect(mounted).toMatchSnapshot();
+ });
+
+ it('displays correct title depending on canEdit', () => {
+ let mounted = mountHeader({
+ ...defaultProps,
+ canEdit: true,
+ });
+ expect(mounted.find('h1').text()).toMatchInlineSnapshot(`"Edit search"`);
+
+ mounted = mountHeader({
+ ...defaultProps,
+ canEdit: false,
+ });
+ expect(mounted.find('h1').text()).toMatchInlineSnapshot(`"View search"`);
+ });
+
+ it('displays correct title depending on type', () => {
+ let mounted = mountHeader({
+ ...defaultProps,
+ type: 'some-type',
+ });
+ expect(mounted.find('h1').text()).toMatchInlineSnapshot(`"Edit some-type"`);
+
+ mounted = mountHeader({
+ ...defaultProps,
+ type: 'another-type',
+ });
+ expect(mounted.find('h1').text()).toMatchInlineSnapshot(`"Edit another-type"`);
+ });
+
+ it('only displays delete button if canDelete is true', () => {
+ let mounted = mountHeader({
+ ...defaultProps,
+ canDelete: true,
+ });
+ expect(mounted.exists(`button[data-test-subj='savedObjectEditDelete']`)).toBe(true);
+
+ mounted = mountHeader({
+ ...defaultProps,
+ canDelete: false,
+ });
+ expect(mounted.exists(`button[data-test-subj='savedObjectEditDelete']`)).toBe(false);
+ });
+
+ it('calls onDeleteClick when clicking on the delete button', () => {
+ const clickHandler = jest.fn();
+
+ const mounted = mountHeader({
+ ...defaultProps,
+ canDelete: true,
+ onDeleteClick: clickHandler,
+ });
+ expect(clickHandler).toHaveBeenCalledTimes(0);
+
+ mounted.find(`button[data-test-subj='savedObjectEditDelete']`).simulate('click');
+ expect(clickHandler).toHaveBeenCalledTimes(1);
+ });
+
+ it('only displays view button if canViewInApp is true', () => {
+ let mounted = mountHeader({
+ ...defaultProps,
+ canViewInApp: true,
+ });
+ expect(mounted.exists(`a[data-test-subj='savedObjectEditViewInApp']`)).toBe(true);
+
+ mounted = mountHeader({
+ ...defaultProps,
+ canViewInApp: false,
+ });
+ expect(mounted.exists(`a[data-test-subj='savedObjectEditViewInApp']`)).toBe(false);
+ });
+});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx
new file mode 100644
index 00000000000000..641493e0cbaa80
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx
@@ -0,0 +1,110 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiButton,
+ EuiPageContentHeader,
+ EuiPageContentHeaderSection,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+interface HeaderProps {
+ canEdit: boolean;
+ canDelete: boolean;
+ canViewInApp: boolean;
+ type: string;
+ viewUrl: string;
+ onDeleteClick: () => void;
+}
+
+export const Header = ({
+ canEdit,
+ canDelete,
+ canViewInApp,
+ type,
+ viewUrl,
+ onDeleteClick,
+}: HeaderProps) => {
+ return (
+
+
+
+ {canEdit ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+
+ {canViewInApp && (
+
+
+
+
+
+ )}
+ {canDelete && (
+
+ onDeleteClick()}
+ data-test-subj="savedObjectEditDelete"
+ >
+
+
+
+ )}
+
+
+
+ );
+};
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/index.ts
new file mode 100644
index 00000000000000..a3a05c05cb4a9b
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/index.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.
+ */
+
+export { Header } from './header';
+export { NotFoundErrors } from './not_found_errors';
+export { Intro } from './intro';
+export { Form } from './form';
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.test.tsx
new file mode 100644
index 00000000000000..d154c2b6f76202
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.test.tsx
@@ -0,0 +1,34 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import { I18nProvider } from '@kbn/i18n/react';
+import { Intro } from './intro';
+
+describe('Intro component', () => {
+ it('renders correctly', () => {
+ const mounted = mount(
+
+
+
+ );
+ expect(mounted.find('Intro')).toMatchSnapshot();
+ });
+});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx
new file mode 100644
index 00000000000000..098ad71345d49d
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx
@@ -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 React from 'react';
+import { EuiCallOut } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+export const Intro = () => {
+ return (
+
+ }
+ iconType="alert"
+ color="warning"
+ >
+
+
+
+
+ );
+};
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.test.tsx
new file mode 100644
index 00000000000000..58cdf05ba37ddd
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.test.tsx
@@ -0,0 +1,64 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import { I18nProvider } from '@kbn/i18n/react';
+import { NotFoundErrors } from './not_found_errors';
+
+describe('NotFoundErrors component', () => {
+ const mountError = (type: string) =>
+ mount(
+
+
+
+ ).find('NotFoundErrors');
+
+ it('renders correctly for search type', () => {
+ const mounted = mountError('search');
+ expect(mounted).toMatchSnapshot();
+ expect(mounted.text()).toMatchInlineSnapshot(
+ `"There is a problem with this saved objectThe saved search associated with this object no longer exists.If you know what this error means, go ahead and fix it — otherwise click the delete button above."`
+ );
+ });
+
+ it('renders correctly for index-pattern type', () => {
+ const mounted = mountError('index-pattern');
+ expect(mounted).toMatchSnapshot();
+ expect(mounted.text()).toMatchInlineSnapshot(
+ `"There is a problem with this saved objectThe index pattern associated with this object no longer exists.If you know what this error means, go ahead and fix it — otherwise click the delete button above."`
+ );
+ });
+
+ it('renders correctly for index-pattern-field type', () => {
+ const mounted = mountError('index-pattern-field');
+ expect(mounted).toMatchSnapshot();
+ expect(mounted.text()).toMatchInlineSnapshot(
+ `"There is a problem with this saved objectA field associated with this object no longer exists in the index pattern.If you know what this error means, go ahead and fix it — otherwise click the delete button above."`
+ );
+ });
+
+ it('renders correctly for unknown type', () => {
+ const mounted = mountError('unknown');
+ expect(mounted).toMatchSnapshot();
+ expect(mounted.text()).toMatchInlineSnapshot(
+ `"There is a problem with this saved objectIf you know what this error means, go ahead and fix it — otherwise click the delete button above."`
+ );
+ });
+});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx
new file mode 100644
index 00000000000000..c3d18855f6c9a0
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx
@@ -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 React from 'react';
+import { EuiCallOut } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+interface NotFoundErrors {
+ type: string;
+}
+
+export const NotFoundErrors = ({ type }: NotFoundErrors) => {
+ const getMessage = () => {
+ switch (type) {
+ case 'search':
+ return (
+
+ );
+ case 'index-pattern':
+ return (
+
+ );
+ case 'index-pattern-field':
+ return (
+
+ );
+ default:
+ return null;
+ }
+ };
+
+ return (
+
+ }
+ iconType="alert"
+ color="danger"
+ >
+ {getMessage()}
+
+
+
+
+ );
+};
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
index 805131042f3852..a4dcfb9c38184c 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
@@ -126,6 +126,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
Array [
Object {
"align": "center",
+ "data-test-subj": "savedObjectsTableRowType",
"description": "Type of the saved object",
"field": "type",
"name": "Type",
@@ -134,6 +135,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
"width": "50px",
},
Object {
+ "data-test-subj": "savedObjectsTableRowTitle",
"dataType": "string",
"description": "Title of the saved object",
"field": "meta.title",
@@ -145,6 +147,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
"actions": Array [
Object {
"available": [Function],
+ "data-test-subj": "savedObjectsTableAction-inspect",
"description": "Inspect this saved object",
"icon": "inspect",
"name": "Inspect",
@@ -152,6 +155,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
"type": "icon",
},
Object {
+ "data-test-subj": "savedObjectsTableAction-relationships",
"description": "View the relationships this saved object has to other saved objects",
"icon": "kqlSelector",
"name": "Relationships",
@@ -198,6 +202,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
}
}
responsive={true}
+ rowProps={[Function]}
selection={
Object {
"onSelectionChange": [Function],
@@ -334,6 +339,7 @@ exports[`Table should render normally 1`] = `
Array [
Object {
"align": "center",
+ "data-test-subj": "savedObjectsTableRowType",
"description": "Type of the saved object",
"field": "type",
"name": "Type",
@@ -342,6 +348,7 @@ exports[`Table should render normally 1`] = `
"width": "50px",
},
Object {
+ "data-test-subj": "savedObjectsTableRowTitle",
"dataType": "string",
"description": "Title of the saved object",
"field": "meta.title",
@@ -353,6 +360,7 @@ exports[`Table should render normally 1`] = `
"actions": Array [
Object {
"available": [Function],
+ "data-test-subj": "savedObjectsTableAction-inspect",
"description": "Inspect this saved object",
"icon": "inspect",
"name": "Inspect",
@@ -360,6 +368,7 @@ exports[`Table should render normally 1`] = `
"type": "icon",
},
Object {
+ "data-test-subj": "savedObjectsTableAction-relationships",
"description": "View the relationships this saved object has to other saved objects",
"icon": "kqlSelector",
"name": "Relationships",
@@ -406,6 +415,7 @@ exports[`Table should render normally 1`] = `
}
}
responsive={true}
+ rowProps={[Function]}
selection={
Object {
"onSelectionChange": [Function],
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
index a119817fdc0c9a..386b35399b754a 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js
@@ -178,6 +178,7 @@ export class Table extends PureComponent {
{ defaultMessage: 'Type of the saved object' }
),
sortable: false,
+ 'data-test-subj': 'savedObjectsTableRowType',
render: (type, object) => {
return (
@@ -201,6 +202,7 @@ export class Table extends PureComponent {
),
dataType: 'string',
sortable: false,
+ 'data-test-subj': 'savedObjectsTableRowTitle',
render: (title, object) => {
const { path } = object.meta.inAppUrl || {};
const canGoInApp = this.props.canGoInApp(object);
@@ -230,6 +232,7 @@ export class Table extends PureComponent {
icon: 'inspect',
onClick: object => goInspectObject(object),
available: object => !!object.meta.editUrl,
+ 'data-test-subj': 'savedObjectsTableAction-inspect',
},
{
name: i18n.translate(
@@ -246,10 +249,12 @@ export class Table extends PureComponent {
type: 'icon',
icon: 'kqlSelector',
onClick: object => onShowRelationships(object),
+ 'data-test-subj': 'savedObjectsTableAction-relationships',
},
...this.extraActions.map(action => {
return {
...action.euiAction,
+ 'data-test-subj': `savedObjectsTableAction-${action.id}`,
onClick: object => {
this.setState({
activeAction: action,
@@ -372,6 +377,9 @@ export class Table extends PureComponent {
pagination={pagination}
selection={selection}
onChange={onTableChange}
+ rowProps={item => ({
+ 'data-test-subj': `savedObjectsTableRow row-${item.id}`,
+ })}
/>
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts
new file mode 100644
index 00000000000000..345716f91ea886
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts
@@ -0,0 +1,132 @@
+/*
+ * 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 { SimpleSavedObject, SavedObjectReference } from '../../../../../../../../core/public';
+import { savedObjectsServiceMock } from '../../../../../../../../core/public/mocks';
+import { createFieldList } from './create_field_list';
+
+const savedObjectClientMock = savedObjectsServiceMock.createStartContract().client;
+
+const createObject = (
+ attributes: T,
+ references: SavedObjectReference[] = []
+): SimpleSavedObject =>
+ new SimpleSavedObject(savedObjectClientMock, {
+ id: 'id',
+ type: 'type',
+ migrationVersion: {},
+ attributes,
+ references,
+ });
+
+describe('createFieldList', () => {
+ it('generate fields based on the object attributes', () => {
+ const obj = createObject({
+ textField: 'some text',
+ numberField: 12,
+ boolField: true,
+ });
+ expect(createFieldList(obj)).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "name": "textField",
+ "type": "text",
+ "value": "some text",
+ },
+ Object {
+ "name": "numberField",
+ "type": "number",
+ "value": 12,
+ },
+ Object {
+ "name": "boolField",
+ "type": "boolean",
+ "value": true,
+ },
+ ]
+ `);
+ });
+
+ it('detects json fields', () => {
+ const obj = createObject({
+ jsonField: `{"data": "value"}`,
+ });
+ expect(createFieldList(obj)).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "name": "jsonField",
+ "type": "json",
+ "value": "{
+ \\"data\\": \\"value\\"
+ }",
+ },
+ ]
+ `);
+ });
+
+ it('handles array fields', () => {
+ const obj = createObject({
+ someArray: [1, 2, 3],
+ });
+ expect(createFieldList(obj)).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "name": "someArray",
+ "type": "array",
+ "value": "[
+ 1,
+ 2,
+ 3
+ ]",
+ },
+ ]
+ `);
+ });
+
+ it('recursively collect nested fields', () => {
+ const obj = createObject({
+ firstLevel: {
+ firstLevelField: 'foo',
+ secondLevel: {
+ secondLevelFieldA: 'A',
+ secondLevelFieldB: 'B',
+ },
+ },
+ });
+ expect(createFieldList(obj)).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "name": "firstLevel.firstLevelField",
+ "type": "text",
+ "value": "foo",
+ },
+ Object {
+ "name": "firstLevel.secondLevel.secondLevelFieldA",
+ "type": "text",
+ "value": "A",
+ },
+ Object {
+ "name": "firstLevel.secondLevel.secondLevelFieldB",
+ "type": "text",
+ "value": "B",
+ },
+ ]
+ `);
+ });
+});
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.ts
new file mode 100644
index 00000000000000..88a1184d5d70f9
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.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.
+ */
+
+import { forOwn, indexBy, isNumber, isBoolean, isPlainObject, isString } from 'lodash';
+import { SimpleSavedObject } from '../../../../../../../../core/public';
+import { castEsToKbnFieldTypeName } from '../../../../../../../../plugins/data/public';
+import { ObjectField } from '../types';
+import { SavedObjectLoader } from '../../../../../../../../plugins/saved_objects/public';
+
+const maxRecursiveIterations = 20;
+
+export function createFieldList(
+ object: SimpleSavedObject,
+ service?: SavedObjectLoader
+): ObjectField[] {
+ const fields = Object.entries(object.attributes as Record).reduce(
+ (objFields, [key, value]) => {
+ return [...objFields, ...recursiveCreateFields(key, value)];
+ },
+ [] as ObjectField[]
+ );
+ if (service && (service as any).Class) {
+ addFieldsFromClass((service as any).Class, fields);
+ }
+
+ return fields;
+}
+
+/**
+ * Creates a field definition and pushes it to the memo stack. This function
+ * is designed to be used in conjunction with _.reduce(). If the
+ * values is plain object it will recurse through all the keys till it hits
+ * a string, number or an array.
+ *
+ * @param {string} key The key of the field
+ * @param {mixed} value The value of the field
+ * @param {array} parents The parent keys to the field
+ * @returns {array}
+ */
+const recursiveCreateFields = (key: string, value: any, parents: string[] = []): ObjectField[] => {
+ const path = [...parents, key];
+ if (path.length > maxRecursiveIterations) {
+ return [];
+ }
+
+ const field: ObjectField = { type: 'text', name: path.join('.'), value };
+
+ if (isString(field.value)) {
+ try {
+ field.value = JSON.stringify(JSON.parse(field.value), undefined, 2);
+ field.type = 'json';
+ } catch (err) {
+ field.type = 'text';
+ }
+ } else if (isNumber(field.value)) {
+ field.type = 'number';
+ } else if (Array.isArray(field.value)) {
+ field.type = 'array';
+ field.value = JSON.stringify(field.value, undefined, 2);
+ } else if (isBoolean(field.value)) {
+ field.type = 'boolean';
+ } else if (isPlainObject(field.value)) {
+ let fields: ObjectField[] = [];
+ forOwn(field.value, (childValue, childKey) => {
+ fields = [...fields, ...recursiveCreateFields(childKey as string, childValue, path)];
+ });
+ return fields;
+ }
+
+ return [field];
+};
+
+const addFieldsFromClass = function(
+ Class: { mapping: Record; searchSource: any },
+ fields: ObjectField[]
+) {
+ const fieldMap = indexBy(fields, 'name');
+
+ _.forOwn(Class.mapping, (esType, name) => {
+ if (!name || fieldMap[name]) {
+ return;
+ }
+
+ const getFieldTypeFromEsType = () => {
+ switch (castEsToKbnFieldTypeName(esType)) {
+ case 'string':
+ return 'text';
+ case 'number':
+ return 'number';
+ case 'boolean':
+ return 'boolean';
+ default:
+ return 'json';
+ }
+ };
+
+ fields.push({
+ name,
+ type: getFieldTypeFromEsType(),
+ value: undefined,
+ });
+ });
+
+ if (Class.searchSource && !fieldMap['kibanaSavedObjectMeta.searchSourceJSON']) {
+ fields.push({
+ name: 'kibanaSavedObjectMeta.searchSourceJSON',
+ type: 'json',
+ value: '{}',
+ });
+ }
+
+ if (!fieldMap.references) {
+ fields.push({
+ name: 'references',
+ type: 'array',
+ value: '[]',
+ });
+ }
+};
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.ts
similarity index 71%
rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.js
rename to src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.ts
index 00261548486931..82146554afa6ff 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.ts
@@ -17,22 +17,24 @@
* under the License.
*/
-export function canViewInApp(uiCapabilities, type) {
+import { Capabilities } from 'src/core/public';
+
+export function canViewInApp(uiCapabilities: Capabilities, type: string): boolean {
switch (type) {
case 'search':
case 'searches':
- return uiCapabilities.discover.show;
+ return uiCapabilities.discover.show as boolean;
case 'visualization':
case 'visualizations':
- return uiCapabilities.visualize.show;
+ return uiCapabilities.visualize.show as boolean;
case 'index-pattern':
case 'index-patterns':
case 'indexPatterns':
- return uiCapabilities.management.kibana.index_patterns;
+ return uiCapabilities.management.kibana.index_patterns as boolean;
case 'dashboard':
case 'dashboards':
- return uiCapabilities.dashboard.show;
+ return uiCapabilities.dashboard.show as boolean;
default:
- return uiCapabilities[type].show;
+ return uiCapabilities[type].show as boolean;
}
}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx b/src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx
new file mode 100644
index 00000000000000..4984fe3e6d6b8f
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx
@@ -0,0 +1,176 @@
+/*
+ * 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, { Component } from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiSpacer, EuiPageContent } from '@elastic/eui';
+import {
+ Capabilities,
+ SavedObjectsClientContract,
+ OverlayStart,
+ NotificationsStart,
+ SimpleSavedObject,
+} from '../../../../../../../core/public';
+import { ISavedObjectsManagementRegistry } from '../../saved_object_registry';
+import { Header, NotFoundErrors, Intro, Form } from './components/object_view';
+import { canViewInApp } from './lib/in_app_url';
+import { SubmittedFormData } from './types';
+
+interface SavedObjectEditionProps {
+ id: string;
+ serviceName: string;
+ serviceRegistry: ISavedObjectsManagementRegistry;
+ capabilities: Capabilities;
+ overlays: OverlayStart;
+ notifications: NotificationsStart;
+ notFoundType?: string;
+ savedObjectsClient: SavedObjectsClientContract;
+}
+
+interface SavedObjectEditionState {
+ type: string;
+ object?: SimpleSavedObject;
+}
+
+export class SavedObjectEdition extends Component<
+ SavedObjectEditionProps,
+ SavedObjectEditionState
+> {
+ constructor(props: SavedObjectEditionProps) {
+ super(props);
+
+ const { serviceRegistry, serviceName } = props;
+ const type = serviceRegistry.get(serviceName)!.service.type;
+
+ this.state = {
+ object: undefined,
+ type,
+ };
+ }
+
+ componentDidMount() {
+ const { id, savedObjectsClient } = this.props;
+ const { type } = this.state;
+ savedObjectsClient.get(type, id).then(object => {
+ this.setState({
+ object,
+ });
+ });
+ }
+
+ render() {
+ const {
+ capabilities,
+ notFoundType,
+ serviceRegistry,
+ id,
+ serviceName,
+ savedObjectsClient,
+ } = this.props;
+ const { type } = this.state;
+ const { object } = this.state;
+ const { edit: canEdit, delete: canDelete } = capabilities.savedObjectsManagement as Record<
+ string,
+ boolean
+ >;
+ const canView = canViewInApp(capabilities, type);
+ const service = serviceRegistry.get(serviceName)!.service;
+
+ return (
+
+ this.delete()}
+ viewUrl={service.urlFor(id)}
+ />
+ {notFoundType && (
+ <>
+
+
+ >
+ )}
+ {canEdit && (
+ <>
+
+
+ >
+ )}
+ {object && (
+ <>
+
+
+ >
+ )}
+
+ );
+ }
+
+ async delete() {
+ const { id, savedObjectsClient, overlays, notifications } = this.props;
+ const { type, object } = this.state;
+
+ const confirmed = await overlays.openConfirm(
+ i18n.translate('kbn.management.objects.confirmModalOptions.modalDescription', {
+ defaultMessage: 'This action permanently removes the object from Kibana.',
+ }),
+ {
+ confirmButtonText: i18n.translate(
+ 'kbn.management.objects.confirmModalOptions.deleteButtonLabel',
+ {
+ defaultMessage: 'Delete',
+ }
+ ),
+ title: i18n.translate('kbn.management.objects.confirmModalOptions.modalTitle', {
+ defaultMessage: `Delete '{title}'?`,
+ values: {
+ title: object?.attributes?.title || 'saved Kibana object',
+ },
+ }),
+ buttonColor: 'danger',
+ }
+ );
+ if (confirmed) {
+ await savedObjectsClient.delete(type, id);
+ notifications.toasts.addSuccess(`Deleted '${object!.attributes.title}' ${type} object`);
+ this.redirectToListing();
+ }
+ }
+
+ saveChanges = async ({ attributes, references }: SubmittedFormData) => {
+ const { savedObjectsClient, notifications } = this.props;
+ const { object, type } = this.state;
+
+ await savedObjectsClient.update(object!.type, object!.id, attributes, { references });
+ notifications.toasts.addSuccess(`Updated '${attributes.title}' ${type} object`);
+ this.redirectToListing();
+ };
+
+ redirectToListing() {
+ window.location.hash = '/management/kibana/objects';
+ }
+}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts b/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts
new file mode 100644
index 00000000000000..32436e96d48292
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts
@@ -0,0 +1,38 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SavedObjectReference } from 'src/core/public';
+
+export interface ObjectField {
+ type: FieldType;
+ name: string;
+ value: any;
+}
+
+export type FieldType = 'text' | 'number' | 'boolean' | 'array' | 'json';
+
+export interface FieldState {
+ value?: any;
+ invalid?: boolean;
+}
+
+export interface SubmittedFormData {
+ attributes: any;
+ references: SavedObjectReference[];
+}
diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
index 0ddf3ee67aa94a..e6b7a29e28d897 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts
@@ -25,7 +25,7 @@
*/
// @ts-ignore
-export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
+export { KbnUrlProvider } from 'ui/url';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { wrapInI18nContext } from 'ui/i18n';
@@ -33,7 +33,6 @@ export { DashboardConstants } from '../dashboard/np_ready/dashboard_constants';
export { VisSavedObject, VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/';
export {
configureAppAngularModule,
- ensureDefaultIndexPattern,
IPrivate,
migrateLegacyQuery,
PrivateProvider,
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
index 8ef63ec5778e2d..c7c3286bb5c71a 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
@@ -24,7 +24,6 @@ import { AppMountContext } from 'kibana/public';
import {
configureAppAngularModule,
KbnUrlProvider,
- RedirectWhenMissingProvider,
IPrivate,
PrivateProvider,
PromiseServiceCreator,
@@ -102,8 +101,7 @@ function createLocalAngularModule(core: AppMountContext['core'], navigation: Nav
function createLocalKbnUrlModule() {
angular
.module('app/visualize/KbnUrl', ['app/visualize/Private', 'ngRoute'])
- .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider))
- .service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider));
+ .service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider));
}
function createLocalPromiseModule() {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
index c023c402f5fead..1fab38027f65b4 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js
@@ -31,6 +31,7 @@ import { getEditBreadcrumbs } from '../breadcrumbs';
import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
import { unhashUrl } from '../../../../../../../plugins/kibana_utils/public';
+import { MarkdownSimple, toMountPoint } from '../../../../../../../plugins/kibana_react/public';
import { addFatalError, kbnBaseUrl } from '../../../../../../../plugins/kibana_legacy/public';
import {
SavedObjectSaveModal,
@@ -75,7 +76,6 @@ function VisualizeAppController(
$injector,
$timeout,
kbnUrl,
- redirectWhenMissing,
kbnUrlStateStorage,
history
) {
@@ -313,16 +313,33 @@ function VisualizeAppController(
}
);
+ const stopAllSyncing = () => {
+ stopStateSync();
+ stopSyncingQueryServiceStateWithUrl();
+ stopSyncingAppFilters();
+ };
+
// The savedVis is pulled from elasticsearch, but the appState is pulled from the url, with the
// defaults applied. If the url was from a previous session which included modifications to the
// appState then they won't be equal.
if (!_.isEqual(stateContainer.getState().vis, stateDefaults.vis)) {
try {
vis.setState(stateContainer.getState().vis);
- } catch {
- redirectWhenMissing({
- 'index-pattern-field': '/visualize',
+ } catch (error) {
+ // stop syncing url updtes with the state to prevent extra syncing
+ stopAllSyncing();
+
+ toastNotifications.addWarning({
+ title: i18n.translate('kbn.visualize.visualizationTypeInvalidNotificationMessage', {
+ defaultMessage: 'Invalid visualization type',
+ }),
+ text: toMountPoint({error.message} ),
});
+
+ history.replace(`${VisualizeConstants.LANDING_PAGE_PATH}?notFound=visualization`);
+
+ // prevent further controller execution
+ return;
}
}
@@ -529,9 +546,8 @@ function VisualizeAppController(
unsubscribePersisted();
unsubscribeStateUpdates();
- stopStateSync();
- stopSyncingQueryServiceStateWithUrl();
- stopSyncingAppFilters();
+
+ stopAllSyncing();
});
$timeout(() => {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization.js
index 6acdb0abdd0b50..c8acea168444fa 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/visualization.js
@@ -59,7 +59,9 @@ export function initVisualizationDirective(app, deps) {
});
$scope.$on('$destroy', () => {
- $scope._handler.destroy();
+ if ($scope._handler) {
+ $scope._handler.destroy();
+ }
});
},
};
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js
index b9409445166bc4..0f1d50b149cd90 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/legacy_app.js
@@ -21,7 +21,11 @@ import { find } from 'lodash';
import { i18n } from '@kbn/i18n';
import { createHashHistory } from 'history';
-import { createKbnUrlStateStorage } from '../../../../../../plugins/kibana_utils/public';
+import {
+ createKbnUrlStateStorage,
+ redirectWhenMissing,
+ ensureDefaultIndexPattern,
+} from '../../../../../../plugins/kibana_utils/public';
import editorTemplate from './editor/editor.html';
import visualizeListingTemplate from './listing/visualize_listing.html';
@@ -29,7 +33,6 @@ import visualizeListingTemplate from './listing/visualize_listing.html';
import { initVisualizeAppDirective } from './visualize_app';
import { VisualizeConstants } from './visualize_constants';
import { VisualizeListingController } from './listing/visualize_listing';
-import { ensureDefaultIndexPattern } from '../legacy_imports';
import {
getLandingBreadcrumbs,
@@ -79,8 +82,7 @@ export function initVisualizeApp(app, deps) {
controllerAs: 'listingController',
resolve: {
createNewVis: () => false,
- hasDefaultIndex: ($rootScope, kbnUrl) =>
- ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl),
+ hasDefaultIndex: history => ensureDefaultIndexPattern(deps.core, deps.data, history),
},
})
.when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, {
@@ -91,8 +93,7 @@ export function initVisualizeApp(app, deps) {
controllerAs: 'listingController',
resolve: {
createNewVis: () => true,
- hasDefaultIndex: ($rootScope, kbnUrl) =>
- ensureDefaultIndexPattern(deps.core, deps.data, $rootScope, kbnUrl),
+ hasDefaultIndex: history => ensureDefaultIndexPattern(deps.core, deps.data, history),
},
})
.when(VisualizeConstants.CREATE_PATH, {
@@ -100,8 +101,8 @@ export function initVisualizeApp(app, deps) {
template: editorTemplate,
k7Breadcrumbs: getCreateBreadcrumbs,
resolve: {
- savedVis: function(redirectWhenMissing, $route, $rootScope, kbnUrl) {
- const { core, data, savedVisualizations, visualizations } = deps;
+ savedVis: function($route, history) {
+ const { core, data, savedVisualizations, visualizations, toastNotifications } = deps;
const visTypes = visualizations.all();
const visType = find(visTypes, { name: $route.current.params.type });
const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection;
@@ -118,7 +119,7 @@ export function initVisualizeApp(app, deps) {
);
}
- return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl)
+ return ensureDefaultIndexPattern(core, data, history)
.then(() => savedVisualizations.get($route.current.params))
.then(savedVis => {
if (savedVis.vis.type.setup) {
@@ -128,7 +129,9 @@ export function initVisualizeApp(app, deps) {
})
.catch(
redirectWhenMissing({
- '*': '/visualize',
+ history,
+ mapping: VisualizeConstants.LANDING_PAGE_PATH,
+ toastNotifications,
})
);
},
@@ -139,9 +142,9 @@ export function initVisualizeApp(app, deps) {
template: editorTemplate,
k7Breadcrumbs: getEditBreadcrumbs,
resolve: {
- savedVis: function(redirectWhenMissing, $route, $rootScope, kbnUrl) {
- const { chrome, core, data, savedVisualizations } = deps;
- return ensureDefaultIndexPattern(core, data, $rootScope, kbnUrl)
+ savedVis: function($route, history) {
+ const { chrome, core, data, savedVisualizations, toastNotifications } = deps;
+ return ensureDefaultIndexPattern(core, data, history)
.then(() => savedVisualizations.get($route.current.params.id))
.then(savedVis => {
chrome.recentlyAccessed.add(savedVis.getFullPath(), savedVis.title, savedVis.id);
@@ -155,13 +158,17 @@ export function initVisualizeApp(app, deps) {
})
.catch(
redirectWhenMissing({
- visualization: '/visualize',
- search:
- '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
- 'index-pattern':
- '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
- 'index-pattern-field':
- '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ history,
+ mapping: {
+ visualization: VisualizeConstants.LANDING_PAGE_PATH,
+ search:
+ '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ 'index-pattern':
+ '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ 'index-pattern-field':
+ '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
+ },
+ toastNotifications,
})
);
},
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
index 0263f5b2c851c1..ff2546f75c51a5 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_editor.js
@@ -50,7 +50,7 @@ export class VisEditor extends Component {
visFields: props.visFields,
extractedIndexPatterns: [''],
};
- this.onBrush = createBrushHandler(getDataStart().query.timefilter);
+ this.onBrush = createBrushHandler(getDataStart().query.timefilter.timefilter);
this.visDataSubject = new Rx.BehaviorSubject(this.props.visData);
this.visData$ = this.visDataSubject.asObservable().pipe(share());
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/_vis_types.scss b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/_vis_types.scss
index 90c2007b1c94aa..3db09bace079f1 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/_vis_types.scss
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/_vis_types.scss
@@ -7,4 +7,21 @@
.tvbVisTimeSeries {
overflow: hidden;
}
+ .tvbVisTimeSeriesDark {
+ .echReactiveChart_unavailable {
+ color: #DFE5EF;
+ }
+ .echLegendItem {
+ color: #DFE5EF;
+ }
+ }
+ .tvbVisTimeSeriesLight {
+ .echReactiveChart_unavailable {
+ color: #343741;
+ }
+ .echLegendItem {
+ color: #343741;
+ }
+ }
}
+
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/timeseries/vis.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/timeseries/vis.js
index 954d3d174bb8c9..356ba08ac24272 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/timeseries/vis.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/vis_types/timeseries/vis.js
@@ -33,9 +33,8 @@ import { getAxisLabelString } from '../../lib/get_axis_label_string';
import { getInterval } from '../../lib/get_interval';
import { areFieldsDifferent } from '../../lib/charts';
import { createXaxisFormatter } from '../../lib/create_xaxis_formatter';
-import { isBackgroundDark } from '../../../lib/set_is_reversed';
import { STACKED_OPTIONS } from '../../../visualizations/constants';
-import { getCoreStart } from '../../../services';
+import { getCoreStart, getUISettings } from '../../../services';
export class TimeseriesVisualization extends Component {
static propTypes = {
@@ -238,6 +237,7 @@ export class TimeseriesVisualization extends Component {
}
});
+ const darkMode = getUISettings().get('theme:darkMode');
return (
null;
export const AreaSeries = () => null;
+
+export { LIGHT_THEME, DARK_THEME } from '@elastic/charts';
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/index.js b/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/index.js
index 986111b462b352..75554a476bdea1 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/index.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/index.js
@@ -19,14 +19,13 @@
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
+import classNames from 'classnames';
import {
Axis,
Chart,
Position,
Settings,
- DARK_THEME,
- LIGHT_THEME,
AnnotationDomainTypes,
LineAnnotation,
TooltipType,
@@ -40,6 +39,7 @@ import { GRID_LINE_CONFIG, ICON_TYPES_MAP, STACKED_OPTIONS } from '../../constan
import { AreaSeriesDecorator } from './decorators/area_decorator';
import { BarSeriesDecorator } from './decorators/bar_decorator';
import { getStackAccessors } from './utils/stack_format';
+import { getTheme, getChartClasses } from './utils/theme';
const generateAnnotationData = (values, formatter) =>
values.map(({ key, docs }) => ({
@@ -57,7 +57,8 @@ const handleCursorUpdate = cursor => {
};
export const TimeSeries = ({
- isDarkMode,
+ darkMode,
+ backgroundColor,
showGrid,
legend,
legendPosition,
@@ -89,8 +90,13 @@ export const TimeSeries = ({
const timeZone = timezoneProvider(uiSettings)();
const hasBarChart = series.some(({ bars }) => bars.show);
+ // compute the theme based on the bg color
+ const theme = getTheme(darkMode, backgroundColor);
+ // apply legend style change if bgColor is configured
+ const classes = classNames('tvbVisTimeSeries', getChartClasses(backgroundColor));
+
return (
-
+
{
+ it('should return the basic themes if no bg color is specified', () => {
+ // use original dark/light theme
+ expect(getTheme(false)).toEqual(LIGHT_THEME);
+ expect(getTheme(true)).toEqual(DARK_THEME);
+
+ // discard any wrong/missing bg color
+ expect(getTheme(true, null)).toEqual(DARK_THEME);
+ expect(getTheme(true, '')).toEqual(DARK_THEME);
+ expect(getTheme(true, undefined)).toEqual(DARK_THEME);
+ });
+ it('should return a highcontrast color theme for a different background', () => {
+ // red use a near full-black color
+ expect(getTheme(false, 'red').axes.axisTitleStyle.fill).toEqual('rgb(23,23,23)');
+
+ // violet increased the text color to full white for higer contrast
+ expect(getTheme(false, '#ba26ff').axes.axisTitleStyle.fill).toEqual('rgb(255,255,255)');
+
+ // light yellow, prefer the LIGHT_THEME fill color because already with a good contrast
+ expect(getTheme(false, '#fff49f').axes.axisTitleStyle.fill).toEqual('#333');
+ });
+});
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/utils/theme.ts b/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/utils/theme.ts
new file mode 100644
index 00000000000000..a25d5e1ce1d353
--- /dev/null
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/visualizations/views/timeseries/utils/theme.ts
@@ -0,0 +1,139 @@
+/*
+ * 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 colorJS from 'color';
+import { Theme, LIGHT_THEME, DARK_THEME } from '@elastic/charts';
+
+function computeRelativeLuminosity(rgb: string) {
+ return colorJS(rgb).luminosity();
+}
+
+function computeContrast(rgb1: string, rgb2: string) {
+ return colorJS(rgb1).contrast(colorJS(rgb2));
+}
+
+function getAAARelativeLum(bgColor: string, fgColor: string, ratio = 7) {
+ const relLum1 = computeRelativeLuminosity(bgColor);
+ const relLum2 = computeRelativeLuminosity(fgColor);
+ if (relLum1 > relLum2) {
+ // relLum1 is brighter, relLum2 is darker
+ return (relLum1 + 0.05 - ratio * 0.05) / ratio;
+ } else {
+ // relLum1 is darker, relLum2 is brighter
+ return Math.min(ratio * (relLum1 + 0.05) - 0.05, 1);
+ }
+}
+
+function getGrayFromRelLum(relLum: number) {
+ if (relLum <= 0.0031308) {
+ return relLum * 12.92;
+ } else {
+ return (1.0 + 0.055) * Math.pow(relLum, 1.0 / 2.4) - 0.055;
+ }
+}
+
+function getGrayRGBfromGray(gray: number) {
+ const g = Math.round(gray * 255);
+ return `rgb(${g},${g},${g})`;
+}
+
+function getAAAGray(bgColor: string, fgColor: string, ratio = 7) {
+ const relLum = getAAARelativeLum(bgColor, fgColor, ratio);
+ const gray = getGrayFromRelLum(relLum);
+ return getGrayRGBfromGray(gray);
+}
+
+function findBestContrastColor(
+ bgColor: string,
+ lightFgColor: string,
+ darkFgColor: string,
+ ratio = 4.5
+) {
+ const lc = computeContrast(bgColor, lightFgColor);
+ const dc = computeContrast(bgColor, darkFgColor);
+ if (lc >= dc) {
+ if (lc >= ratio) {
+ return lightFgColor;
+ }
+ return getAAAGray(bgColor, lightFgColor, ratio);
+ }
+ if (dc >= ratio) {
+ return darkFgColor;
+ }
+ return getAAAGray(bgColor, darkFgColor, ratio);
+}
+
+function isValidColor(color: string | null | undefined): color is string {
+ if (typeof color !== 'string') {
+ return false;
+ }
+ if (color.length === 0) {
+ return false;
+ }
+ try {
+ colorJS(color);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+export function getTheme(darkMode: boolean, bgColor?: string | null): Theme {
+ if (!isValidColor(bgColor)) {
+ return darkMode ? DARK_THEME : LIGHT_THEME;
+ }
+
+ const bgLuminosity = computeRelativeLuminosity(bgColor);
+ const mainTheme = bgLuminosity <= 0.179 ? DARK_THEME : LIGHT_THEME;
+ const color = findBestContrastColor(
+ bgColor,
+ LIGHT_THEME.axes.axisTitleStyle.fill,
+ DARK_THEME.axes.axisTitleStyle.fill
+ );
+ return {
+ ...mainTheme,
+ axes: {
+ ...mainTheme.axes,
+ axisTitleStyle: {
+ ...mainTheme.axes.axisTitleStyle,
+ fill: color,
+ },
+ tickLabelStyle: {
+ ...mainTheme.axes.tickLabelStyle,
+ fill: color,
+ },
+ axisLineStyle: {
+ ...mainTheme.axes.axisLineStyle,
+ stroke: color,
+ },
+ tickLineStyle: {
+ ...mainTheme.axes.tickLineStyle,
+ stroke: color,
+ },
+ },
+ };
+}
+
+export function getChartClasses(bgColor?: string) {
+ // keep the original theme color if no bg color is specified
+ if (typeof bgColor !== 'string') {
+ return;
+ }
+ const bgLuminosity = computeRelativeLuminosity(bgColor);
+ return bgLuminosity <= 0.179 ? 'tvbVisTimeSeriesDark' : 'tvbVisTimeSeriesLight';
+}
diff --git a/src/legacy/ui/public/chrome/chrome.js b/src/legacy/ui/public/chrome/chrome.js
index 3355870eabfe7c..7a75ad906a8704 100644
--- a/src/legacy/ui/public/chrome/chrome.js
+++ b/src/legacy/ui/public/chrome/chrome.js
@@ -28,7 +28,6 @@ import '../private';
import '../promises';
import '../directives/storage';
import '../directives/watch_multi';
-import './services';
import '../react_components';
import '../i18n';
diff --git a/src/legacy/ui/public/exit_full_screen/__snapshots__/exit_full_screen_button.test.js.snap b/src/legacy/ui/public/exit_full_screen/__snapshots__/exit_full_screen_button.test.js.snap
index 27226eb010ba25..365f3afdab3952 100644
--- a/src/legacy/ui/public/exit_full_screen/__snapshots__/exit_full_screen_button.test.js.snap
+++ b/src/legacy/ui/public/exit_full_screen/__snapshots__/exit_full_screen_button.test.js.snap
@@ -12,19 +12,45 @@ exports[`is rendered 1`] = `
-
- Exit full screen
+ class="euiFlexItem euiFlexItem--flexGrowZero"
+ >
+
+
+
+
diff --git a/src/legacy/ui/public/legacy_compat/index.ts b/src/legacy/ui/public/legacy_compat/index.ts
index 3b700c8d59399f..2067fa6489304f 100644
--- a/src/legacy/ui/public/legacy_compat/index.ts
+++ b/src/legacy/ui/public/legacy_compat/index.ts
@@ -17,7 +17,4 @@
* under the License.
*/
-export {
- configureAppAngularModule,
- ensureDefaultIndexPattern,
-} from '../../../../plugins/kibana_legacy/public';
+export { configureAppAngularModule } from '../../../../plugins/kibana_legacy/public';
diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
index ea84ba1ad28387..c58a7d2fbb5cde 100644
--- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
+++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js
@@ -21,13 +21,15 @@ import sinon from 'sinon';
import { getFieldFormatsRegistry } from '../../../../test_utils/public/stub_field_formats';
import { METRIC_TYPE } from '@kbn/analytics';
import {
+ setFieldFormats,
setIndexPatterns,
- setQueryService,
- setUiSettings,
setInjectedMetadata,
- setFieldFormats,
- setSearchService,
+ setHttp,
+ setNotifications,
setOverlays,
+ setQueryService,
+ setSearchService,
+ setUiSettings,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../plugins/data/public/services';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
@@ -477,11 +479,13 @@ export function __start__(coreStart) {
// Services that need to be set in the legacy platform since the legacy data plugin
// which previously provided them has been removed.
+ setHttp(npStart.core.http);
+ setNotifications(npStart.core.notifications);
+ setOverlays(npStart.core.overlays);
setUiSettings(npStart.core.uiSettings);
- setQueryService(npStart.plugins.data.query);
- setIndexPatterns(npStart.plugins.data.indexPatterns);
setFieldFormats(npStart.plugins.data.fieldFormats);
+ setIndexPatterns(npStart.plugins.data.indexPatterns);
+ setQueryService(npStart.plugins.data.query);
setSearchService(npStart.plugins.data.search);
setAggs(npStart.plugins.data.search.aggs);
- setOverlays(npStart.core.overlays);
}
diff --git a/src/legacy/ui/public/new_platform/new_platform.test.ts b/src/legacy/ui/public/new_platform/new_platform.test.ts
index 498f05457bba98..dd41093f3a1f04 100644
--- a/src/legacy/ui/public/new_platform/new_platform.test.ts
+++ b/src/legacy/ui/public/new_platform/new_platform.test.ts
@@ -20,8 +20,19 @@
jest.mock('history');
import { setRootControllerMock, historyMock } from './new_platform.test.mocks';
-import { legacyAppRegister, __reset__, __setup__ } from './new_platform';
+import {
+ legacyAppRegister,
+ __reset__,
+ __setup__,
+ __start__,
+ PluginsSetup,
+ PluginsStart,
+} from './new_platform';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import * as dataServices from '../../../../plugins/data/public/services';
+import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public';
import { coreMock } from '../../../../core/public/mocks';
+import { npSetup, npStart } from './__mocks__';
describe('ui/new_platform', () => {
describe('legacyAppRegister', () => {
@@ -108,4 +119,25 @@ describe('ui/new_platform', () => {
expect(unmountMock).toHaveBeenCalled();
});
});
+
+ describe('service getters', () => {
+ const services: Record = dataServices;
+ const getters = Object.keys(services).filter(k => k.substring(0, 3) === 'get');
+
+ getters.forEach(g => {
+ it(`sets a value for ${g}`, () => {
+ __reset__();
+ __setup__(
+ (coreMock.createSetup() as unknown) as LegacyCoreSetup,
+ (npSetup.plugins as unknown) as PluginsSetup
+ );
+ __start__(
+ (coreMock.createStart() as unknown) as LegacyCoreStart,
+ (npStart.plugins as unknown) as PluginsStart
+ );
+
+ expect(services[g]()).toBeDefined();
+ });
+ });
+ });
});
diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts
index 07e17ad5622918..deb8387fee29c3 100644
--- a/src/legacy/ui/public/new_platform/new_platform.ts
+++ b/src/legacy/ui/public/new_platform/new_platform.ts
@@ -31,13 +31,15 @@ import {
} from '../../../../core/public';
import { Plugin as DataPlugin } from '../../../../plugins/data/public';
import {
+ setFieldFormats,
setIndexPatterns,
- setQueryService,
- setUiSettings,
setInjectedMetadata,
- setFieldFormats,
- setSearchService,
+ setHttp,
+ setNotifications,
setOverlays,
+ setQueryService,
+ setSearchService,
+ setUiSettings,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../plugins/data/public/services';
import { Plugin as ExpressionsPlugin } from '../../../../plugins/expressions/public';
@@ -141,12 +143,14 @@ export function __start__(coreStart: LegacyCoreStart, plugins: PluginsStart) {
// Services that need to be set in the legacy platform since the legacy data plugin
// which previously provided them has been removed.
+ setHttp(npStart.core.http);
+ setNotifications(npStart.core.notifications);
+ setOverlays(npStart.core.overlays);
setUiSettings(npStart.core.uiSettings);
- setQueryService(npStart.plugins.data.query);
- setIndexPatterns(npStart.plugins.data.indexPatterns);
setFieldFormats(npStart.plugins.data.fieldFormats);
+ setIndexPatterns(npStart.plugins.data.indexPatterns);
+ setQueryService(npStart.plugins.data.query);
setSearchService(npStart.plugins.data.search);
- setOverlays(npStart.core.overlays);
}
/** Flag used to ensure `legacyAppRegister` is only called once. */
diff --git a/src/legacy/ui/public/vis/map/service_settings.js b/src/legacy/ui/public/vis/map/service_settings.js
index 233ee526c439ba..9f3d21831e3dab 100644
--- a/src/legacy/ui/public/vis/map/service_settings.js
+++ b/src/legacy/ui/public/vis/map/service_settings.js
@@ -47,7 +47,8 @@ uiModules
this._showZoomMessage = true;
this._emsClient = new EMSClient({
language: i18n.getLocale(),
- kbnVersion: kbnVersion,
+ appVersion: kbnVersion,
+ appName: 'kibana',
fileApiUrl: mapConfig.emsFileApiUrl,
tileApiUrl: mapConfig.emsTileApiUrl,
htmlSanitizer: $sanitize,
diff --git a/src/plugins/console/public/lib/kb/kb.js b/src/plugins/console/public/lib/kb/kb.js
index 95896bed029881..053b82bd81d0a5 100644
--- a/src/plugins/console/public/lib/kb/kb.js
+++ b/src/plugins/console/public/lib/kb/kb.js
@@ -147,13 +147,9 @@ function loadApisFromJson(
}
export function setActiveApi(api) {
- if (_.isString(api)) {
+ if (!api) {
$.ajax({
- url:
- '../api/console/api_server?sense_version=' +
- encodeURIComponent('@@SENSE_VERSION') +
- '&apis=' +
- encodeURIComponent(api),
+ url: '../api/console/api_server',
dataType: 'json', // disable automatic guessing
}).then(
function(data) {
@@ -169,7 +165,7 @@ export function setActiveApi(api) {
ACTIVE_API = api;
}
-setActiveApi('es_6_0');
+setActiveApi();
export const _test = {
loadApisFromJson: loadApisFromJson,
diff --git a/src/plugins/console/server/lib/index.ts b/src/plugins/console/server/lib/index.ts
index 98004768f880b7..2347084b73a667 100644
--- a/src/plugins/console/server/lib/index.ts
+++ b/src/plugins/console/server/lib/index.ts
@@ -22,4 +22,4 @@ export { ProxyConfigCollection } from './proxy_config_collection';
export { proxyRequest } from './proxy_request';
export { getElasticsearchProxyConfig } from './elasticsearch_proxy_config';
export { setHeaders } from './set_headers';
-export { addProcessorDefinition, addExtensionSpecFilePath } from './spec_definitions';
+export { addProcessorDefinition, addExtensionSpecFilePath, loadSpec } from './spec_definitions';
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0.js b/src/plugins/console/server/lib/spec_definitions/es.js
similarity index 54%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0.js
rename to src/plugins/console/server/lib/spec_definitions/es.js
index 171d232407956d..fc24a64f8a6f44 100644
--- a/src/plugins/console/server/lib/spec_definitions/es_6_0.js
+++ b/src/plugins/console/server/lib/spec_definitions/es.js
@@ -18,26 +18,30 @@
*/
import Api from './api';
-import { getSpec } from './spec';
-import { register } from './es_6_0/ingest';
-const ES_6_0 = new Api('es_6_0');
-const spec = getSpec();
+import { getSpec } from './json';
+import { register } from './js/ingest';
+const ES = new Api('es');
-// adding generated specs
-Object.keys(spec).forEach(endpoint => {
- ES_6_0.addEndpointDescription(endpoint, spec[endpoint]);
-});
+export const loadSpec = () => {
+ const spec = getSpec();
-//adding globals and custom API definitions
-require('./es_6_0/aliases')(ES_6_0);
-require('./es_6_0/aggregations')(ES_6_0);
-require('./es_6_0/document')(ES_6_0);
-require('./es_6_0/filter')(ES_6_0);
-require('./es_6_0/globals')(ES_6_0);
-register(ES_6_0);
-require('./es_6_0/mappings')(ES_6_0);
-require('./es_6_0/query')(ES_6_0);
-require('./es_6_0/reindex')(ES_6_0);
-require('./es_6_0/search')(ES_6_0);
+ // adding generated specs
+ Object.keys(spec).forEach(endpoint => {
+ ES.addEndpointDescription(endpoint, spec[endpoint]);
+ });
-export default ES_6_0;
+ // adding globals and custom API definitions
+ require('./js/aliases')(ES);
+ require('./js/aggregations')(ES);
+ require('./js/document')(ES);
+ require('./js/filter')(ES);
+ require('./js/globals')(ES);
+ register(ES);
+ require('./js/mappings')(ES);
+ require('./js/settings')(ES);
+ require('./js/query')(ES);
+ require('./js/reindex')(ES);
+ require('./js/search')(ES);
+};
+
+export default ES;
diff --git a/src/plugins/console/server/lib/spec_definitions/index.d.ts b/src/plugins/console/server/lib/spec_definitions/index.d.ts
index 0a79d3fb386f1c..da0125a186c152 100644
--- a/src/plugins/console/server/lib/spec_definitions/index.d.ts
+++ b/src/plugins/console/server/lib/spec_definitions/index.d.ts
@@ -19,6 +19,13 @@
export declare function addProcessorDefinition(...args: any[]): any;
-export declare function resolveApi(senseVersion: string, apis: string[]): object;
+export declare function resolveApi(): object;
export declare function addExtensionSpecFilePath(...args: any[]): any;
+
+/**
+ * A function that synchronously reads files JSON from disk and builds
+ * the autocomplete structures served to the client. This must be called
+ * after any extensions have been loaded.
+ */
+export declare function loadSpec(): any;
diff --git a/src/plugins/console/server/lib/spec_definitions/index.js b/src/plugins/console/server/lib/spec_definitions/index.js
index 3fe1913d5a193a..abf55639fbee8d 100644
--- a/src/plugins/console/server/lib/spec_definitions/index.js
+++ b/src/plugins/console/server/lib/spec_definitions/index.js
@@ -17,8 +17,10 @@
* under the License.
*/
-export { addProcessorDefinition } from './es_6_0/ingest';
+export { addProcessorDefinition } from './js/ingest';
-export { addExtensionSpecFilePath } from './spec';
+export { addExtensionSpecFilePath } from './json';
+
+export { loadSpec } from './es';
export { resolveApi } from './server';
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/aggregations.js b/src/plugins/console/server/lib/spec_definitions/js/aggregations.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/aggregations.js
rename to src/plugins/console/server/lib/spec_definitions/js/aggregations.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/aliases.js b/src/plugins/console/server/lib/spec_definitions/js/aliases.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/aliases.js
rename to src/plugins/console/server/lib/spec_definitions/js/aliases.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/document.js b/src/plugins/console/server/lib/spec_definitions/js/document.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/document.js
rename to src/plugins/console/server/lib/spec_definitions/js/document.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/filter.js b/src/plugins/console/server/lib/spec_definitions/js/filter.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/filter.js
rename to src/plugins/console/server/lib/spec_definitions/js/filter.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/globals.js b/src/plugins/console/server/lib/spec_definitions/js/globals.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/globals.js
rename to src/plugins/console/server/lib/spec_definitions/js/globals.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/ingest.js b/src/plugins/console/server/lib/spec_definitions/js/ingest.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/ingest.js
rename to src/plugins/console/server/lib/spec_definitions/js/ingest.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/mappings.js b/src/plugins/console/server/lib/spec_definitions/js/mappings.js
similarity index 99%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/mappings.js
rename to src/plugins/console/server/lib/spec_definitions/js/mappings.js
index 8c31e5bc6fbb25..5884d14d4dc8b1 100644
--- a/src/plugins/console/server/lib/spec_definitions/es_6_0/mappings.js
+++ b/src/plugins/console/server/lib/spec_definitions/js/mappings.js
@@ -19,9 +19,7 @@
const _ = require('lodash');
-const BOOLEAN = {
- __one_of: [true, false],
-};
+import { BOOLEAN } from './shared';
export default function(api) {
api.addEndpointDescription('put_mapping', {
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/query/dsl.js b/src/plugins/console/server/lib/spec_definitions/js/query/dsl.js
similarity index 99%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/query/dsl.js
rename to src/plugins/console/server/lib/spec_definitions/js/query/dsl.js
index a5f0d15dee0e9b..16b952fe0fe4ff 100644
--- a/src/plugins/console/server/lib/spec_definitions/es_6_0/query/dsl.js
+++ b/src/plugins/console/server/lib/spec_definitions/js/query/dsl.js
@@ -281,9 +281,11 @@ export function queryDsl(api) {
__scope_link: '.',
},
],
- filter: {
- __scope_link: 'GLOBAL.filter',
- },
+ filter: [
+ {
+ __scope_link: 'GLOBAL.filter',
+ },
+ ],
minimum_should_match: 1,
boost: 1.0,
},
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/query/index.js b/src/plugins/console/server/lib/spec_definitions/js/query/index.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/query/index.js
rename to src/plugins/console/server/lib/spec_definitions/js/query/index.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/query/templates.js b/src/plugins/console/server/lib/spec_definitions/js/query/templates.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/query/templates.js
rename to src/plugins/console/server/lib/spec_definitions/js/query/templates.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/reindex.js b/src/plugins/console/server/lib/spec_definitions/js/reindex.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/reindex.js
rename to src/plugins/console/server/lib/spec_definitions/js/reindex.js
diff --git a/src/plugins/console/server/lib/spec_definitions/es_6_0/search.js b/src/plugins/console/server/lib/spec_definitions/js/search.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/es_6_0/search.js
rename to src/plugins/console/server/lib/spec_definitions/js/search.js
diff --git a/src/plugins/console/server/lib/spec_definitions/js/settings.js b/src/plugins/console/server/lib/spec_definitions/js/settings.js
new file mode 100644
index 00000000000000..26cd0987c34a5b
--- /dev/null
+++ b/src/plugins/console/server/lib/spec_definitions/js/settings.js
@@ -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 { BOOLEAN } from './shared';
+
+export default function(api) {
+ api.addEndpointDescription('put_settings', {
+ data_autocomplete_rules: {
+ refresh_interval: '1s',
+ number_of_shards: 1,
+ number_of_replicas: 1,
+ 'blocks.read_only': BOOLEAN,
+ 'blocks.read': BOOLEAN,
+ 'blocks.write': BOOLEAN,
+ 'blocks.metadata': BOOLEAN,
+ term_index_interval: 32,
+ term_index_divisor: 1,
+ 'translog.flush_threshold_ops': 5000,
+ 'translog.flush_threshold_size': '200mb',
+ 'translog.flush_threshold_period': '30m',
+ 'translog.disable_flush': BOOLEAN,
+ 'cache.filter.max_size': '2gb',
+ 'cache.filter.expire': '2h',
+ 'gateway.snapshot_interval': '10s',
+ routing: {
+ allocation: {
+ include: {
+ tag: '',
+ },
+ exclude: {
+ tag: '',
+ },
+ require: {
+ tag: '',
+ },
+ total_shards_per_node: -1,
+ },
+ },
+ 'recovery.initial_shards': {
+ __one_of: ['quorum', 'quorum-1', 'half', 'full', 'full-1'],
+ },
+ 'ttl.disable_purge': BOOLEAN,
+ analysis: {
+ analyzer: {},
+ tokenizer: {},
+ filter: {},
+ char_filter: {},
+ },
+ 'cache.query.enable': BOOLEAN,
+ shadow_replicas: BOOLEAN,
+ shared_filesystem: BOOLEAN,
+ data_path: 'path',
+ codec: {
+ __one_of: ['default', 'best_compression', 'lucene_default'],
+ },
+ },
+ });
+}
diff --git a/src/plugins/console/server/lib/spec_definitions/js/shared.js b/src/plugins/console/server/lib/spec_definitions/js/shared.js
new file mode 100644
index 00000000000000..ace189e2d09138
--- /dev/null
+++ b/src/plugins/console/server/lib/spec_definitions/js/shared.js
@@ -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 const BOOLEAN = Object.freeze({
+ __one_of: [true, false],
+});
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/.eslintrc b/src/plugins/console/server/lib/spec_definitions/json/.eslintrc
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/.eslintrc
rename to src/plugins/console/server/lib/spec_definitions/json/.eslintrc
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/_common.json b/src/plugins/console/server/lib/spec_definitions/json/generated/_common.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/_common.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/_common.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/bulk.json b/src/plugins/console/server/lib/spec_definitions/json/generated/bulk.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/bulk.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/bulk.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.aliases.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.aliases.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.aliases.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.allocation.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.allocation.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.allocation.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.allocation.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.count.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.count.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.count.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.count.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.fielddata.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.fielddata.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.fielddata.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.fielddata.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.health.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.health.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.health.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.health.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.help.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.help.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.help.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.help.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.indices.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.indices.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.indices.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.master.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.master.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.master.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.master.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.nodeattrs.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.nodeattrs.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.nodeattrs.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.nodes.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.nodes.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.nodes.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.nodes.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.pending_tasks.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.pending_tasks.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.pending_tasks.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.plugins.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.plugins.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.plugins.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.plugins.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.recovery.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.recovery.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.recovery.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.recovery.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.repositories.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.repositories.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.repositories.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.repositories.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.segments.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.segments.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.segments.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.segments.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.shards.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.shards.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.shards.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.shards.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.snapshots.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.snapshots.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.snapshots.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.snapshots.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.tasks.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.tasks.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.tasks.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.tasks.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.templates.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.templates.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.templates.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.templates.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cat.thread_pool.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cat.thread_pool.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cat.thread_pool.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/clear_scroll.json b/src/plugins/console/server/lib/spec_definitions/json/generated/clear_scroll.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/clear_scroll.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/clear_scroll.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.allocation_explain.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.allocation_explain.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.allocation_explain.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.get_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.get_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.get_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.get_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.health.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.health.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.health.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.pending_tasks.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.pending_tasks.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.pending_tasks.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.pending_tasks.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.put_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.put_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.put_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.remote_info.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.remote_info.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.remote_info.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.remote_info.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.reroute.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.reroute.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.reroute.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.reroute.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.state.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.state.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.state.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.stats.json b/src/plugins/console/server/lib/spec_definitions/json/generated/cluster.stats.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/cluster.stats.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/cluster.stats.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/count.json b/src/plugins/console/server/lib/spec_definitions/json/generated/count.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/count.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/count.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/create.json b/src/plugins/console/server/lib/spec_definitions/json/generated/create.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/create.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/create.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/delete.json b/src/plugins/console/server/lib/spec_definitions/json/generated/delete.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/delete.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/delete.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/delete_by_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/delete_by_query.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/delete_by_query_rethrottle.json b/src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query_rethrottle.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/delete_by_query_rethrottle.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/delete_by_query_rethrottle.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/delete_script.json b/src/plugins/console/server/lib/spec_definitions/json/generated/delete_script.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/delete_script.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/delete_script.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/exists.json b/src/plugins/console/server/lib/spec_definitions/json/generated/exists.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/exists.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/exists.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/exists_source.json b/src/plugins/console/server/lib/spec_definitions/json/generated/exists_source.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/exists_source.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/exists_source.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/explain.json b/src/plugins/console/server/lib/spec_definitions/json/generated/explain.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/explain.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/explain.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/field_caps.json b/src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/field_caps.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/field_caps.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/get.json b/src/plugins/console/server/lib/spec_definitions/json/generated/get.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/get.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/get.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/get_script.json b/src/plugins/console/server/lib/spec_definitions/json/generated/get_script.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/get_script.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/get_script.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/get_script_context.json b/src/plugins/console/server/lib/spec_definitions/json/generated/get_script_context.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/get_script_context.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/get_script_context.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/get_script_languages.json b/src/plugins/console/server/lib/spec_definitions/json/generated/get_script_languages.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/get_script_languages.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/get_script_languages.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/get_source.json b/src/plugins/console/server/lib/spec_definitions/json/generated/get_source.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/get_source.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/get_source.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/index.json b/src/plugins/console/server/lib/spec_definitions/json/generated/index.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/index.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/index.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.analyze.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.analyze.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.analyze.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.analyze.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.clear_cache.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.clear_cache.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.clear_cache.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.clone.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.clone.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.clone.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.clone.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.close.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.close.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.close.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.create.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.create.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.create.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete_alias.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete_alias.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.delete_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.delete_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_alias.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_alias.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_type.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.exists_type.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.exists_type.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.flush.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.flush.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.flush_synced.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush_synced.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.flush_synced.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.flush_synced.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.forcemerge.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.forcemerge.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.forcemerge.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_alias.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_alias.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_field_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_field_mapping.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_field_mapping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_mapping.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_mapping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_upgrade.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.get_upgrade.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.get_upgrade.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.open.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.open.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.open.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_alias.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_alias.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_alias.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_alias.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_mapping.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_mapping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.put_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.put_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.recovery.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.recovery.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.recovery.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.recovery.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.refresh.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.refresh.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.refresh.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.rollover.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.rollover.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.rollover.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.segments.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.segments.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.segments.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.shard_stores.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.shard_stores.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.shard_stores.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.shrink.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.shrink.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.shrink.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.shrink.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.split.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.split.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.split.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.split.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.stats.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.stats.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.stats.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.update_aliases.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.update_aliases.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.update_aliases.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.update_aliases.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.upgrade.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.upgrade.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.upgrade.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/indices.validate_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/indices.validate_query.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/indices.validate_query.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/info.json b/src/plugins/console/server/lib/spec_definitions/json/generated/info.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/info.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/info.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.delete_pipeline.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ingest.delete_pipeline.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.delete_pipeline.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ingest.delete_pipeline.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.get_pipeline.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ingest.get_pipeline.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.get_pipeline.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ingest.get_pipeline.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.processor_grok.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ingest.processor_grok.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.processor_grok.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ingest.processor_grok.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.put_pipeline.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ingest.put_pipeline.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.put_pipeline.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ingest.put_pipeline.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.simulate.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ingest.simulate.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ingest.simulate.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ingest.simulate.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/mget.json b/src/plugins/console/server/lib/spec_definitions/json/generated/mget.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/mget.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/mget.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/msearch.json b/src/plugins/console/server/lib/spec_definitions/json/generated/msearch.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/msearch.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/msearch.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/msearch_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/msearch_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/msearch_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/mtermvectors.json b/src/plugins/console/server/lib/spec_definitions/json/generated/mtermvectors.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/mtermvectors.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/mtermvectors.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.hot_threads.json b/src/plugins/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.hot_threads.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/nodes.hot_threads.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.info.json b/src/plugins/console/server/lib/spec_definitions/json/generated/nodes.info.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.info.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/nodes.info.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.reload_secure_settings.json b/src/plugins/console/server/lib/spec_definitions/json/generated/nodes.reload_secure_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.reload_secure_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/nodes.reload_secure_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.stats.json b/src/plugins/console/server/lib/spec_definitions/json/generated/nodes.stats.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.stats.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/nodes.stats.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.usage.json b/src/plugins/console/server/lib/spec_definitions/json/generated/nodes.usage.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/nodes.usage.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/nodes.usage.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/ping.json b/src/plugins/console/server/lib/spec_definitions/json/generated/ping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/ping.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/ping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/put_script.json b/src/plugins/console/server/lib/spec_definitions/json/generated/put_script.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/put_script.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/put_script.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/rank_eval.json b/src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/rank_eval.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/rank_eval.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/reindex.json b/src/plugins/console/server/lib/spec_definitions/json/generated/reindex.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/reindex.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/reindex.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/reindex_rethrottle.json b/src/plugins/console/server/lib/spec_definitions/json/generated/reindex_rethrottle.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/reindex_rethrottle.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/reindex_rethrottle.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/render_search_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/render_search_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/render_search_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/render_search_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/scripts_painless_execute.json b/src/plugins/console/server/lib/spec_definitions/json/generated/scripts_painless_execute.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/scripts_painless_execute.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/scripts_painless_execute.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/scroll.json b/src/plugins/console/server/lib/spec_definitions/json/generated/scroll.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/scroll.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/scroll.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/search.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/search.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/search.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/search_shards.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/search_shards.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/search_shards.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/search_template.json b/src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/search_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/search_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.cleanup_repository.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.cleanup_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.cleanup_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.create.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.create.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.create.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.create.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.create_repository.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.create_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.create_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.delete.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.delete.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.delete.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.delete.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.delete_repository.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.delete_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.delete_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.get.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.get.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.get.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.get.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.get_repository.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.get_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.get_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.restore.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.restore.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.restore.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.restore.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.status.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.status.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.status.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.status.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.verify_repository.json b/src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/snapshot.verify_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/snapshot.verify_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.cancel.json b/src/plugins/console/server/lib/spec_definitions/json/generated/tasks.cancel.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.cancel.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/tasks.cancel.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.get.json b/src/plugins/console/server/lib/spec_definitions/json/generated/tasks.get.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.get.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/tasks.get.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.list.json b/src/plugins/console/server/lib/spec_definitions/json/generated/tasks.list.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/tasks.list.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/tasks.list.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/termvectors.json b/src/plugins/console/server/lib/spec_definitions/json/generated/termvectors.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/termvectors.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/termvectors.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/update.json b/src/plugins/console/server/lib/spec_definitions/json/generated/update.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/update.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/update.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/update_by_query.json b/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/update_by_query.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/generated/update_by_query_rethrottle.json b/src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query_rethrottle.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/generated/update_by_query_rethrottle.json
rename to src/plugins/console/server/lib/spec_definitions/json/generated/update_by_query_rethrottle.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/index.js b/src/plugins/console/server/lib/spec_definitions/json/index.js
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/index.js
rename to src/plugins/console/server/lib/spec_definitions/json/index.js
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/clear_scroll.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/clear_scroll.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/clear_scroll.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/clear_scroll.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.health.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.health.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.health.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.put_settings.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.put_settings.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.reroute.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.reroute.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/cluster.reroute.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/cluster.reroute.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/count.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/count.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/count.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/count.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.analyze.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.analyze.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.analyze.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.analyze.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.clone.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.clone.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.clone.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.clone.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.create.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.create.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.create.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.create.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.delete_template.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.delete_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.delete_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.delete_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.exists_template.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.exists_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.exists_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.exists_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_field_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_field_mapping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_field_mapping.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_field_mapping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_mapping.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_mapping.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_mapping.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_mapping.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_template.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.get_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.get_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_alias.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_alias.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_alias.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_alias.json
diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_settings.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_settings.json
new file mode 100644
index 00000000000000..2ae8fd82be4d8a
--- /dev/null
+++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_settings.json
@@ -0,0 +1,7 @@
+{
+ "indices.put_settings": {
+ "data_autocomplete_rules": {
+ "__scope_link": "put_settings"
+ }
+ }
+}
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_template.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_template.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_template.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_template.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.rollover.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.rollover.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.rollover.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.rollover.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.update_aliases.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.update_aliases.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.update_aliases.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.update_aliases.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.validate_query.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.validate_query.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.validate_query.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/indices.validate_query.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.create.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.create.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.create_repository.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create_repository.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.create_repository.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create_repository.json
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.restore.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.restore.json
similarity index 100%
rename from src/plugins/console/server/lib/spec_definitions/spec/overrides/snapshot.restore.json
rename to src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.restore.json
diff --git a/src/plugins/console/server/lib/spec_definitions/server.js b/src/plugins/console/server/lib/spec_definitions/server.js
index dd700bf0195075..cb855958d403a5 100644
--- a/src/plugins/console/server/lib/spec_definitions/server.js
+++ b/src/plugins/console/server/lib/spec_definitions/server.js
@@ -17,21 +17,10 @@
* under the License.
*/
-import _ from 'lodash';
+import es from './es';
-const KNOWN_APIS = ['es_6_0'];
-
-export function resolveApi(senseVersion, apis) {
- const result = {};
- _.each(apis, function(name) {
- {
- if (KNOWN_APIS.includes(name)) {
- // for now we ignore sense_version. might add it in the api name later
- const api = require('./' + name); // eslint-disable-line import/no-dynamic-require
- result[name] = api.asJson();
- }
- }
- });
-
- return result;
+export function resolveApi() {
+ return {
+ es: es.asJson(),
+ };
}
diff --git a/src/plugins/console/server/lib/spec_definitions/server.test.js b/src/plugins/console/server/lib/spec_definitions/server.test.js
deleted file mode 100644
index 747689237c1777..00000000000000
--- a/src/plugins/console/server/lib/spec_definitions/server.test.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { resolveApi } from './server';
-
-describe('resolveApi', () => {
- it('allows known APIs to be resolved', () => {
- const mockReply = jest.fn(result => ({ type: () => result }));
- const result = resolveApi('Sense Version', ['es_6_0'], { response: mockReply });
- expect(result).toMatchObject({
- es_6_0: {
- endpoints: expect.any(Object),
- globals: expect.any(Object),
- name: expect.any(String),
- },
- });
- });
-
- it('does not resolve APIs that are not known', () => {
- const mockReply = jest.fn(result => ({ type: () => result }));
- const result = resolveApi('Sense Version', ['unknown'], { response: mockReply });
- expect(result).toEqual({});
- });
-
- it('handles request for apis that are known and unknown', () => {
- const mockReply = jest.fn(result => ({ type: () => result }));
- const result = resolveApi('Sense Version', ['es_6_0'], { response: mockReply });
- expect(result).toMatchObject({
- es_6_0: {
- endpoints: expect.any(Object),
- globals: expect.any(Object),
- name: expect.any(String),
- },
- });
- });
-});
diff --git a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_settings.json b/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_settings.json
deleted file mode 100644
index 2e1e3024665a4a..00000000000000
--- a/src/plugins/console/server/lib/spec_definitions/spec/overrides/indices.put_settings.json
+++ /dev/null
@@ -1,108 +0,0 @@
-{
- "indices.put_settings": {
- "data_autocomplete_rules": {
- "refresh_interval": "1s",
- "number_of_shards": 1,
- "number_of_replicas": 1,
- "blocks.read_only": {
- "__one_of": [
- false,
- true
- ]
- },
- "blocks.read": {
- "__one_of": [
- true,
- false
- ]
- },
- "blocks.write": {
- "__one_of": [
- true,
- false
- ]
- },
- "blocks.metadata": {
- "__one_of": [
- true,
- false
- ]
- },
- "term_index_interval": 32,
- "term_index_divisor": 1,
- "translog.flush_threshold_ops": 5000,
- "translog.flush_threshold_size": "200mb",
- "translog.flush_threshold_period": "30m",
- "translog.disable_flush": {
- "__one_of": [
- true,
- false
- ]
- },
- "cache.filter.max_size": "2gb",
- "cache.filter.expire": "2h",
- "gateway.snapshot_interval": "10s",
- "routing": {
- "allocation": {
- "include": {
- "tag": ""
- },
- "exclude": {
- "tag": ""
- },
- "require": {
- "tag": ""
- },
- "total_shards_per_node": -1
- }
- },
- "recovery.initial_shards": {
- "__one_of": [
- "quorum",
- "quorum-1",
- "half",
- "full",
- "full-1"
- ]
- },
- "ttl.disable_purge": {
- "__one_of": [
- true,
- false
- ]
- },
- "analysis": {
- "analyzer": {},
- "tokenizer": {},
- "filter": {},
- "char_filter": {}
- },
- "cache.query.enable": {
- "__one_of": [
- true,
- false
- ]
- },
- "shadow_replicas": {
- "__one_of": [
- true,
- false
- ]
- },
- "shared_filesystem": {
- "__one_of": [
- true,
- false
- ]
- },
- "data_path": "path",
- "codec": {
- "__one_of": [
- "default",
- "best_compression",
- "lucene_default"
- ]
- }
- }
- }
-}
diff --git a/src/plugins/console/server/plugin.ts b/src/plugins/console/server/plugin.ts
index 65647bd5acb7c5..1954918f4d74f6 100644
--- a/src/plugins/console/server/plugin.ts
+++ b/src/plugins/console/server/plugin.ts
@@ -21,7 +21,12 @@ import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/serv
import { readLegacyEsConfig } from '../../../legacy/core_plugins/console_legacy';
-import { ProxyConfigCollection, addExtensionSpecFilePath, addProcessorDefinition } from './lib';
+import {
+ ProxyConfigCollection,
+ addExtensionSpecFilePath,
+ addProcessorDefinition,
+ loadSpec,
+} from './lib';
import { ConfigType } from './config';
import { registerProxyRoute } from './routes/api/console/proxy';
import { registerSpecDefinitionsRoute } from './routes/api/console/spec_definitions';
@@ -75,5 +80,7 @@ export class ConsoleServerPlugin implements Plugin {
};
}
- start() {}
+ start() {
+ loadSpec();
+ }
}
diff --git a/src/plugins/console/server/routes/api/console/spec_definitions/index.ts b/src/plugins/console/server/routes/api/console/spec_definitions/index.ts
index e2ece37f407acf..88bc250bbfce60 100644
--- a/src/plugins/console/server/routes/api/console/spec_definitions/index.ts
+++ b/src/plugins/console/server/routes/api/console/spec_definitions/index.ts
@@ -16,33 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { schema, TypeOf } from '@kbn/config-schema';
import { IRouter, RequestHandler } from 'kibana/server';
import { resolveApi } from '../../../../lib/spec_definitions';
export const registerSpecDefinitionsRoute = ({ router }: { router: IRouter }) => {
- const handler: RequestHandler> = async (
- ctx,
- request,
- response
- ) => {
- const { sense_version: version, apis } = request.query;
-
+ const handler: RequestHandler = async (ctx, request, response) => {
return response.ok({
- body: resolveApi(version, apis.split(',')),
+ body: resolveApi(),
headers: {
'Content-Type': 'application/json',
},
});
};
- const validate = {
- query: schema.object({
- sense_version: schema.string({ defaultValue: '' }),
- apis: schema.string(),
- }),
- };
-
- router.get({ path: '/api/console/api_server', validate }, handler);
- router.post({ path: '/api/console/api_server', validate }, handler);
+ router.get({ path: '/api/console/api_server', validate: false }, handler);
+ router.post({ path: '/api/console/api_server', validate: false }, handler);
};
diff --git a/src/plugins/data/README.md b/src/plugins/data/README.md
index 53618ec049e7c4..0fa304c9889359 100644
--- a/src/plugins/data/README.md
+++ b/src/plugins/data/README.md
@@ -6,4 +6,4 @@
- `filter`
- `index_patterns`
- `query`
-- `search`
+- `search`
\ No newline at end of file
diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts
index cf8c0bfe3d4345..e4a663a1599f12 100644
--- a/src/plugins/data/common/index.ts
+++ b/src/plugins/data/common/index.ts
@@ -26,3 +26,4 @@ export * from './query';
export * from './search';
export * from './search/aggs';
export * from './types';
+export * from './utils';
diff --git a/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts b/src/plugins/data/common/query/filter_manager/compare_filters.test.ts
similarity index 99%
rename from src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
rename to src/plugins/data/common/query/filter_manager/compare_filters.test.ts
index da8f5b3564948e..b0bb2f754d6cf0 100644
--- a/src/plugins/data/public/query/filter_manager/lib/compare_filters.test.ts
+++ b/src/plugins/data/common/query/filter_manager/compare_filters.test.ts
@@ -18,7 +18,7 @@
*/
import { compareFilters, COMPARE_ALL_OPTIONS } from './compare_filters';
-import { buildEmptyFilter, buildQueryFilter, FilterStateStore } from '../../../../common';
+import { buildEmptyFilter, buildQueryFilter, FilterStateStore } from '../../es_query';
describe('filter manager utilities', () => {
describe('compare filters', () => {
diff --git a/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts b/src/plugins/data/common/query/filter_manager/compare_filters.ts
similarity index 98%
rename from src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
rename to src/plugins/data/common/query/filter_manager/compare_filters.ts
index a2105fdc1d3efb..e047d5e0665d5a 100644
--- a/src/plugins/data/public/query/filter_manager/lib/compare_filters.ts
+++ b/src/plugins/data/common/query/filter_manager/compare_filters.ts
@@ -18,7 +18,7 @@
*/
import { defaults, isEqual, omit, map } from 'lodash';
-import { FilterMeta, Filter } from '../../../../common';
+import { FilterMeta, Filter } from '../../es_query';
export interface FilterCompareOptions {
disabled?: boolean;
diff --git a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts b/src/plugins/data/common/query/filter_manager/dedup_filters.test.ts
similarity index 95%
rename from src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
rename to src/plugins/data/common/query/filter_manager/dedup_filters.test.ts
index ecc0ec94e07c8e..228489de37daae 100644
--- a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.test.ts
+++ b/src/plugins/data/common/query/filter_manager/dedup_filters.test.ts
@@ -18,14 +18,8 @@
*/
import { dedupFilters } from './dedup_filters';
-import {
- Filter,
- IIndexPattern,
- IFieldType,
- buildRangeFilter,
- buildQueryFilter,
- FilterStateStore,
-} from '../../../../common';
+import { Filter, buildRangeFilter, buildQueryFilter, FilterStateStore } from '../../es_query';
+import { IIndexPattern, IFieldType } from '../../index_patterns';
describe('filter manager utilities', () => {
let indexPattern: IIndexPattern;
diff --git a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts b/src/plugins/data/common/query/filter_manager/dedup_filters.ts
similarity index 97%
rename from src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
rename to src/plugins/data/common/query/filter_manager/dedup_filters.ts
index d5d0e70504b412..7d1b00ac10c0dd 100644
--- a/src/plugins/data/public/query/filter_manager/lib/dedup_filters.ts
+++ b/src/plugins/data/common/query/filter_manager/dedup_filters.ts
@@ -19,7 +19,7 @@
import { filter, find } from 'lodash';
import { compareFilters, FilterCompareOptions } from './compare_filters';
-import { Filter } from '../../../../common';
+import { Filter } from '../../es_query';
/**
* Combine 2 filter collections, removing duplicates
diff --git a/src/plugins/data/common/query/filter_manager/index.ts b/src/plugins/data/common/query/filter_manager/index.ts
new file mode 100644
index 00000000000000..315c124f083a89
--- /dev/null
+++ b/src/plugins/data/common/query/filter_manager/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 { dedupFilters } from './dedup_filters';
+export { uniqFilters } from './uniq_filters';
+export { compareFilters, COMPARE_ALL_OPTIONS, FilterCompareOptions } from './compare_filters';
diff --git a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts b/src/plugins/data/common/query/filter_manager/uniq_filters.test.ts
similarity index 99%
rename from src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
rename to src/plugins/data/common/query/filter_manager/uniq_filters.test.ts
index 8b525a3d2a2e40..5a35e85c95eaa0 100644
--- a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.test.ts
+++ b/src/plugins/data/common/query/filter_manager/uniq_filters.test.ts
@@ -18,7 +18,7 @@
*/
import { uniqFilters } from './uniq_filters';
-import { buildQueryFilter, Filter, FilterStateStore } from '../../../../common';
+import { buildQueryFilter, Filter, FilterStateStore } from '../../es_query';
describe('filter manager utilities', () => {
describe('niqFilter', () => {
diff --git a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts b/src/plugins/data/common/query/filter_manager/uniq_filters.ts
similarity index 96%
rename from src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
rename to src/plugins/data/common/query/filter_manager/uniq_filters.ts
index 44c102d7ab15d4..683cbf7c78a899 100644
--- a/src/plugins/data/public/query/filter_manager/lib/uniq_filters.ts
+++ b/src/plugins/data/common/query/filter_manager/uniq_filters.ts
@@ -17,8 +17,8 @@
* under the License.
*/
import { each, union } from 'lodash';
+import { Filter } from '../../es_query';
import { dedupFilters } from './dedup_filters';
-import { Filter } from '../../../../common';
/**
* Remove duplicate filters from an array of filters
diff --git a/src/plugins/data/common/query/index.ts b/src/plugins/data/common/query/index.ts
index d8f7b5091eb8f6..421cc4f63e4efb 100644
--- a/src/plugins/data/common/query/index.ts
+++ b/src/plugins/data/common/query/index.ts
@@ -17,4 +17,5 @@
* under the License.
*/
+export * from './filter_manager';
export * from './types';
diff --git a/src/plugins/data/common/utils/abort_utils.test.ts b/src/plugins/data/common/utils/abort_utils.test.ts
new file mode 100644
index 00000000000000..d2a25f2c2dd527
--- /dev/null
+++ b/src/plugins/data/common/utils/abort_utils.test.ts
@@ -0,0 +1,114 @@
+/*
+ * 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 { AbortError, toPromise, getCombinedSignal } from './abort_utils';
+
+jest.useFakeTimers();
+
+const flushPromises = () => new Promise(resolve => setImmediate(resolve));
+
+describe('AbortUtils', () => {
+ describe('AbortError', () => {
+ test('should preserve `message`', () => {
+ const message = 'my error message';
+ const error = new AbortError(message);
+ expect(error.message).toBe(message);
+ });
+
+ test('should have a name of "AbortError"', () => {
+ const error = new AbortError();
+ expect(error.name).toBe('AbortError');
+ });
+ });
+
+ describe('toPromise', () => {
+ describe('resolves', () => {
+ test('should not resolve if the signal does not abort', async () => {
+ const controller = new AbortController();
+ const promise = toPromise(controller.signal);
+ const whenResolved = jest.fn();
+ promise.then(whenResolved);
+ await flushPromises();
+ expect(whenResolved).not.toBeCalled();
+ });
+
+ test('should resolve if the signal does abort', async () => {
+ const controller = new AbortController();
+ const promise = toPromise(controller.signal);
+ const whenResolved = jest.fn();
+ promise.then(whenResolved);
+ controller.abort();
+ await flushPromises();
+ expect(whenResolved).toBeCalled();
+ });
+ });
+
+ describe('rejects', () => {
+ test('should not reject if the signal does not abort', async () => {
+ const controller = new AbortController();
+ const promise = toPromise(controller.signal, true);
+ const whenRejected = jest.fn();
+ promise.catch(whenRejected);
+ await flushPromises();
+ expect(whenRejected).not.toBeCalled();
+ });
+
+ test('should reject if the signal does abort', async () => {
+ const controller = new AbortController();
+ const promise = toPromise(controller.signal, true);
+ const whenRejected = jest.fn();
+ promise.catch(whenRejected);
+ controller.abort();
+ await flushPromises();
+ expect(whenRejected).toBeCalled();
+ });
+ });
+ });
+
+ describe('getCombinedSignal', () => {
+ test('should return an AbortSignal', () => {
+ const signal = getCombinedSignal([]);
+ expect(signal instanceof AbortSignal).toBe(true);
+ });
+
+ test('should not abort if none of the signals abort', async () => {
+ const controller1 = new AbortController();
+ const controller2 = new AbortController();
+ setTimeout(() => controller1.abort(), 2000);
+ setTimeout(() => controller2.abort(), 1000);
+ const signal = getCombinedSignal([controller1.signal, controller2.signal]);
+ expect(signal.aborted).toBe(false);
+ jest.advanceTimersByTime(500);
+ await flushPromises();
+ expect(signal.aborted).toBe(false);
+ });
+
+ test('should abort when the first signal aborts', async () => {
+ const controller1 = new AbortController();
+ const controller2 = new AbortController();
+ setTimeout(() => controller1.abort(), 2000);
+ setTimeout(() => controller2.abort(), 1000);
+ const signal = getCombinedSignal([controller1.signal, controller2.signal]);
+ expect(signal.aborted).toBe(false);
+ jest.advanceTimersByTime(1000);
+ await flushPromises();
+ expect(signal.aborted).toBe(true);
+ });
+ });
+});
diff --git a/src/plugins/data/common/utils/abort_utils.ts b/src/plugins/data/common/utils/abort_utils.ts
new file mode 100644
index 00000000000000..5051515f3a8265
--- /dev/null
+++ b/src/plugins/data/common/utils/abort_utils.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Class used to signify that something was aborted. Useful for applications to conditionally handle
+ * this type of error differently than other errors.
+ */
+export class AbortError extends Error {
+ constructor(message = 'Aborted') {
+ super(message);
+ this.message = message;
+ this.name = 'AbortError';
+ }
+}
+
+/**
+ * Returns a `Promise` corresponding with when the given `AbortSignal` is aborted. Useful for
+ * situations when you might need to `Promise.race` multiple `AbortSignal`s, or an `AbortSignal`
+ * with any other expected errors (or completions).
+ * @param signal The `AbortSignal` to generate the `Promise` from
+ * @param shouldReject If `false`, the promise will be resolved, otherwise it will be rejected
+ */
+export function toPromise(signal: AbortSignal, shouldReject = false) {
+ return new Promise((resolve, reject) => {
+ const action = shouldReject ? reject : resolve;
+ if (signal.aborted) action();
+ signal.addEventListener('abort', action);
+ });
+}
+
+/**
+ * Returns an `AbortSignal` that will be aborted when the first of the given signals aborts.
+ * @param signals
+ */
+export function getCombinedSignal(signals: AbortSignal[]) {
+ const promises = signals.map(signal => toPromise(signal));
+ const controller = new AbortController();
+ Promise.race(promises).then(() => controller.abort());
+ return controller.signal;
+}
diff --git a/src/plugins/data/common/utils/index.ts b/src/plugins/data/common/utils/index.ts
index 8b8686c51b9c19..33989f3ad50a7a 100644
--- a/src/plugins/data/common/utils/index.ts
+++ b/src/plugins/data/common/utils/index.ts
@@ -19,3 +19,4 @@
/** @internal */
export { shortenDottedString } from './shorten_dotted_string';
+export { AbortError, toPromise, getCombinedSignal } from './abort_utils';
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 58bd9a5ab05d73..339a5fea91c5f3 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -47,13 +47,13 @@ import {
isQueryStringFilter,
isRangeFilter,
toggleFilterNegated,
+ compareFilters,
+ COMPARE_ALL_OPTIONS,
} from '../common';
import { FilterLabel } from './ui/filter_bar';
import {
- compareFilters,
- COMPARE_ALL_OPTIONS,
generateFilters,
onlyDisabledFiltersChanged,
changeTimeFilter,
diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts
index b6ca91169a9335..305aa8575e4d78 100644
--- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts
+++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts
@@ -18,6 +18,8 @@
*/
import { defaults, pluck, last, get } from 'lodash';
+
+jest.mock('../../../../kibana_utils/public/history');
import { IndexPattern } from './index_pattern';
import { DuplicateField } from '../../../../kibana_utils/public';
diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts
index c5cff1c5c68d91..e3fc0e97af09b3 100644
--- a/src/plugins/data/public/mocks.ts
+++ b/src/plugins/data/public/mocks.ts
@@ -19,9 +19,7 @@
import { Plugin, DataPublicPluginSetup, DataPublicPluginStart, IndexPatternsContract } from '.';
import { fieldFormatsMock } from '../common/field_formats/mocks';
-import { searchSetupMock } from './search/mocks';
-import { AggTypeFieldFilters } from './search/aggs';
-import { searchAggsStartMock } from './search/aggs/mocks';
+import { searchSetupMock, searchStartMock } from './search/mocks';
import { queryServiceMock } from './query/mocks';
export type Setup = jest.Mocked>;
@@ -35,59 +33,28 @@ const autocompleteMock: any = {
const createSetupContract = (): Setup => {
const querySetupMock = queryServiceMock.createSetupContract();
- const setupContract = {
+ return {
autocomplete: autocompleteMock,
search: searchSetupMock,
fieldFormats: fieldFormatsMock as DataPublicPluginSetup['fieldFormats'],
query: querySetupMock,
- __LEGACY: {
- esClient: {
- search: jest.fn(),
- msearch: jest.fn(),
- },
- },
};
-
- return setupContract;
};
const createStartContract = (): Start => {
const queryStartMock = queryServiceMock.createStartContract();
- const startContract = {
+ return {
actions: {
createFiltersFromEvent: jest.fn().mockResolvedValue(['yes']),
},
autocomplete: autocompleteMock,
- getSuggestions: jest.fn(),
- search: {
- aggs: searchAggsStartMock(),
- search: jest.fn(),
- __LEGACY: {
- AggConfig: jest.fn() as any,
- AggType: jest.fn(),
- aggTypeFieldFilters: new AggTypeFieldFilters(),
- FieldParamType: jest.fn(),
- MetricAggType: jest.fn(),
- parentPipelineAggHelper: jest.fn() as any,
- siblingPipelineAggHelper: jest.fn() as any,
- esClient: {
- search: jest.fn(),
- msearch: jest.fn(),
- },
- },
- },
+ search: searchStartMock,
fieldFormats: fieldFormatsMock as DataPublicPluginStart['fieldFormats'],
query: queryStartMock,
ui: {
IndexPatternSelect: jest.fn(),
SearchBar: jest.fn(),
},
- __LEGACY: {
- esClient: {
- search: jest.fn(),
- msearch: jest.fn(),
- },
- },
indexPatterns: ({
make: () => ({
fieldsFetcher: {
@@ -97,7 +64,6 @@ const createStartContract = (): Start => {
get: jest.fn().mockReturnValue(Promise.resolve({})),
} as unknown) as IndexPatternsContract,
};
- return startContract;
};
export { searchSourceMock } from './search/mocks';
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index a01c1337122068..fc5dde94fa851f 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -39,6 +39,7 @@ import { createIndexPatternSelect } from './ui/index_pattern_select';
import { IndexPatternsService } from './index_patterns';
import {
setFieldFormats,
+ setHttp,
setIndexPatterns,
setInjectedMetadata,
setNotifications,
@@ -128,6 +129,7 @@ export class DataPublicPlugin implements Plugin string;
getPhraseFilterValue: (filter: import("../common").PhraseFilter) => string | number | boolean;
getDisplayValueFromFilter: typeof getDisplayValueFromFilter;
- compareFilters: (first: import("../common").Filter | import("../common").Filter[], second: import("../common").Filter | import("../common").Filter[], comparatorOptions?: import("./query/filter_manager/lib/compare_filters").FilterCompareOptions) => boolean;
- COMPARE_ALL_OPTIONS: import("./query/filter_manager/lib/compare_filters").FilterCompareOptions;
+ compareFilters: (first: import("../common").Filter | import("../common").Filter[], second: import("../common").Filter | import("../common").Filter[], comparatorOptions?: import("../common").FilterCompareOptions) => boolean;
+ COMPARE_ALL_OPTIONS: import("../common").FilterCompareOptions;
generateFilters: typeof generateFilters;
onlyDisabledFiltersChanged: (newFilters?: import("../common").Filter[] | undefined, oldFilters?: import("../common").Filter[] | undefined) => boolean;
changeTimeFilter: typeof changeTimeFilter;
@@ -1843,8 +1843,8 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:38:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromEvent" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:60:5 - (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.ts b/src/plugins/data/public/query/filter_manager/filter_manager.ts
index c951953b26555d..fba1866ebd6154 100644
--- a/src/plugins/data/public/query/filter_manager/filter_manager.ts
+++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts
@@ -22,13 +22,19 @@ import { Subject } from 'rxjs';
import { IUiSettingsClient } from 'src/core/public';
-import { COMPARE_ALL_OPTIONS, compareFilters } from './lib/compare_filters';
import { sortFilters } from './lib/sort_filters';
import { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
-import { uniqFilters } from './lib/uniq_filters';
import { onlyDisabledFiltersChanged } from './lib/only_disabled';
import { PartitionedFilters } from './types';
-import { FilterStateStore, Filter, isFilterPinned } from '../../../common';
+
+import {
+ FilterStateStore,
+ Filter,
+ uniqFilters,
+ isFilterPinned,
+ compareFilters,
+ COMPARE_ALL_OPTIONS,
+} from '../../../common';
export class FilterManager {
private filters: Filter[] = [];
diff --git a/src/plugins/data/public/query/filter_manager/index.ts b/src/plugins/data/public/query/filter_manager/index.ts
index 09990adacde458..be512c503d5316 100644
--- a/src/plugins/data/public/query/filter_manager/index.ts
+++ b/src/plugins/data/public/query/filter_manager/index.ts
@@ -19,8 +19,6 @@
export { FilterManager } from './filter_manager';
-export { uniqFilters } from './lib/uniq_filters';
export { mapAndFlattenFilters } from './lib/map_and_flatten_filters';
export { onlyDisabledFiltersChanged } from './lib/only_disabled';
export { generateFilters } from './lib/generate_filters';
-export { compareFilters, COMPARE_ALL_OPTIONS } from './lib/compare_filters';
diff --git a/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
index 34e1ac38ae95ff..18c51ebeabe545 100644
--- a/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
+++ b/src/plugins/data/public/query/filter_manager/lib/only_disabled.ts
@@ -18,8 +18,7 @@
*/
import { filter } from 'lodash';
-import { Filter } from '../../../../common';
-import { compareFilters, COMPARE_ALL_OPTIONS } from './compare_filters';
+import { Filter, compareFilters, COMPARE_ALL_OPTIONS } from '../../../../common';
const isEnabled = (f: Filter) => f && f.meta && !f.meta.disabled;
diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.ts
index a22e66860c7658..331d8969f24834 100644
--- a/src/plugins/data/public/query/state_sync/connect_to_query_state.ts
+++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.ts
@@ -21,10 +21,9 @@ import { Subscription } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import _ from 'lodash';
import { BaseStateContainer } from '../../../../kibana_utils/public';
-import { COMPARE_ALL_OPTIONS, compareFilters } from '../filter_manager/lib/compare_filters';
import { QuerySetup, QueryStart } from '../query_service';
import { QueryState, QueryStateChange } from './types';
-import { FilterStateStore } from '../../../common/es_query/filters';
+import { FilterStateStore, COMPARE_ALL_OPTIONS, compareFilters } from '../../../common';
/**
* Helper to setup two-way syncing of global data and a state container
diff --git a/src/plugins/data/public/query/state_sync/create_global_query_observable.ts b/src/plugins/data/public/query/state_sync/create_global_query_observable.ts
index d0d97bfaaeb362..dd075f9be7d94c 100644
--- a/src/plugins/data/public/query/state_sync/create_global_query_observable.ts
+++ b/src/plugins/data/public/query/state_sync/create_global_query_observable.ts
@@ -20,10 +20,10 @@
import { Observable, Subscription } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { TimefilterSetup } from '../timefilter';
-import { COMPARE_ALL_OPTIONS, compareFilters, FilterManager } from '../filter_manager';
+import { FilterManager } from '../filter_manager';
import { QueryState, QueryStateChange } from './index';
import { createStateContainer } from '../../../../kibana_utils/public';
-import { isFilterPinned } from '../../../common/es_query/filters';
+import { isFilterPinned, compareFilters, COMPARE_ALL_OPTIONS } from '../../../common';
export function createQueryStateObservable({
timefilter: { timefilter },
diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts
index ac72cfd6f62ca9..f3d2d99af59989 100644
--- a/src/plugins/data/public/search/index.ts
+++ b/src/plugins/data/public/search/index.ts
@@ -56,4 +56,6 @@ export {
SortDirection,
} from './search_source';
+export { SearchInterceptor } from './search_interceptor';
+
export { FetchOptions } from './fetch';
diff --git a/src/plugins/data/public/search/mocks.ts b/src/plugins/data/public/search/mocks.ts
index 71b4eece91cefe..12cf258759a99c 100644
--- a/src/plugins/data/public/search/mocks.ts
+++ b/src/plugins/data/public/search/mocks.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-import { searchAggsSetupMock } from './aggs/mocks';
+import { searchAggsSetupMock, searchAggsStartMock } from './aggs/mocks';
+import { AggTypeFieldFilters } from './aggs/param_types/filter';
+import { ISearchStart } from './types';
export * from './search_source/mocks';
@@ -26,3 +28,24 @@ export const searchSetupMock = {
registerSearchStrategyContext: jest.fn(),
registerSearchStrategyProvider: jest.fn(),
};
+
+export const searchStartMock: jest.Mocked = {
+ aggs: searchAggsStartMock(),
+ search: jest.fn(),
+ cancel: jest.fn(),
+ getPendingCount$: jest.fn(),
+ runBeyondTimeout: jest.fn(),
+ __LEGACY: {
+ AggConfig: jest.fn() as any,
+ AggType: jest.fn(),
+ aggTypeFieldFilters: new AggTypeFieldFilters(),
+ FieldParamType: jest.fn(),
+ MetricAggType: jest.fn(),
+ parentPipelineAggHelper: jest.fn() as any,
+ siblingPipelineAggHelper: jest.fn() as any,
+ esClient: {
+ search: jest.fn(),
+ msearch: jest.fn(),
+ },
+ },
+};
diff --git a/src/plugins/data/public/search/request_timeout_error.ts b/src/plugins/data/public/search/request_timeout_error.ts
new file mode 100644
index 00000000000000..92894deb4f0ffa
--- /dev/null
+++ b/src/plugins/data/public/search/request_timeout_error.ts
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+/**
+ * Class used to signify that a request timed out. Useful for applications to conditionally handle
+ * this type of error differently than other errors.
+ */
+export class RequestTimeoutError extends Error {
+ constructor(message = 'Request timed out') {
+ super(message);
+ this.message = message;
+ this.name = 'RequestTimeoutError';
+ }
+}
diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts
new file mode 100644
index 00000000000000..a89d17464b9e0c
--- /dev/null
+++ b/src/plugins/data/public/search/search_interceptor.test.ts
@@ -0,0 +1,157 @@
+/*
+ * 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 { Observable, Subject } from 'rxjs';
+import { IKibanaSearchRequest } from '../../common/search';
+import { RequestTimeoutError } from './request_timeout_error';
+import { SearchInterceptor } from './search_interceptor';
+
+jest.useFakeTimers();
+
+const flushPromises = () => new Promise(resolve => setImmediate(resolve));
+const mockSearch = jest.fn();
+let searchInterceptor: SearchInterceptor;
+
+describe('SearchInterceptor', () => {
+ beforeEach(() => {
+ mockSearch.mockClear();
+ searchInterceptor = new SearchInterceptor(1000);
+ });
+
+ describe('search', () => {
+ test('should invoke `search` with the request', () => {
+ mockSearch.mockReturnValue(new Observable());
+ const mockRequest: IKibanaSearchRequest = {};
+ searchInterceptor.search(mockSearch, mockRequest);
+ expect(mockSearch.mock.calls[0][0]).toBe(mockRequest);
+ });
+
+ test('should mirror the observable to completion if the request does not time out', () => {
+ const mockResponse = new Subject();
+ mockSearch.mockReturnValue(mockResponse.asObservable());
+ const response = searchInterceptor.search(mockSearch, {});
+
+ setTimeout(() => mockResponse.next('hi'), 250);
+ setTimeout(() => mockResponse.complete(), 500);
+
+ const next = jest.fn();
+ const complete = jest.fn();
+ response.subscribe({ next, complete });
+
+ jest.advanceTimersByTime(1000);
+
+ expect(next).toHaveBeenCalledWith('hi');
+ expect(complete).toHaveBeenCalled();
+ });
+
+ test('should mirror the observable to error if the request does not time out', () => {
+ const mockResponse = new Subject();
+ mockSearch.mockReturnValue(mockResponse.asObservable());
+ const response = searchInterceptor.search(mockSearch, {});
+
+ setTimeout(() => mockResponse.next('hi'), 250);
+ setTimeout(() => mockResponse.error('error'), 500);
+
+ const next = jest.fn();
+ const error = jest.fn();
+ response.subscribe({ next, error });
+
+ jest.advanceTimersByTime(1000);
+
+ expect(next).toHaveBeenCalledWith('hi');
+ expect(error).toHaveBeenCalledWith('error');
+ });
+
+ test('should return a `RequestTimeoutError` if the request times out', () => {
+ mockSearch.mockReturnValue(new Observable());
+ const response = searchInterceptor.search(mockSearch, {});
+
+ const error = jest.fn();
+ response.subscribe({ error });
+
+ jest.advanceTimersByTime(1000);
+
+ expect(error).toHaveBeenCalled();
+ expect(error.mock.calls[0][0] instanceof RequestTimeoutError).toBe(true);
+ });
+ });
+
+ describe('cancelPending', () => {
+ test('should abort all pending requests', async () => {
+ mockSearch.mockReturnValue(new Observable());
+
+ searchInterceptor.search(mockSearch, {});
+ searchInterceptor.search(mockSearch, {});
+ searchInterceptor.cancelPending();
+
+ await flushPromises();
+
+ const areAllRequestsAborted = mockSearch.mock.calls.every(([, { signal }]) => signal.aborted);
+ expect(areAllRequestsAborted).toBe(true);
+ });
+ });
+
+ describe('runBeyondTimeout', () => {
+ test('should prevent the request from timing out', () => {
+ const mockResponse = new Subject();
+ mockSearch.mockReturnValue(mockResponse.asObservable());
+ const response = searchInterceptor.search(mockSearch, {});
+
+ setTimeout(searchInterceptor.runBeyondTimeout, 500);
+ setTimeout(() => mockResponse.next('hi'), 250);
+ setTimeout(() => mockResponse.complete(), 2000);
+
+ const next = jest.fn();
+ const complete = jest.fn();
+ const error = jest.fn();
+ response.subscribe({ next, error, complete });
+
+ jest.advanceTimersByTime(2000);
+
+ expect(next).toHaveBeenCalledWith('hi');
+ expect(error).not.toHaveBeenCalled();
+ expect(complete).toHaveBeenCalled();
+ });
+ });
+
+ describe('getPendingCount$', () => {
+ test('should observe the number of pending requests', () => {
+ let i = 0;
+ const mockResponses = [new Subject(), new Subject()];
+ mockSearch.mockImplementation(() => mockResponses[i++]);
+
+ const pendingCount$ = searchInterceptor.getPendingCount$();
+
+ const next = jest.fn();
+ pendingCount$.subscribe(next);
+
+ const error = jest.fn();
+ searchInterceptor.search(mockSearch, {}).subscribe({ error });
+ searchInterceptor.search(mockSearch, {}).subscribe({ error });
+
+ setTimeout(() => mockResponses[0].complete(), 250);
+ setTimeout(() => mockResponses[1].error('error'), 500);
+
+ jest.advanceTimersByTime(500);
+
+ expect(next).toHaveBeenCalled();
+ expect(next.mock.calls).toEqual([[0], [1], [2], [1], [0]]);
+ });
+ });
+});
diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts
new file mode 100644
index 00000000000000..3f83214f6050c3
--- /dev/null
+++ b/src/plugins/data/public/search/search_interceptor.ts
@@ -0,0 +1,121 @@
+/*
+ * 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 { BehaviorSubject, fromEvent, throwError } from 'rxjs';
+import { mergeMap, takeUntil, finalize } from 'rxjs/operators';
+import { getCombinedSignal } from '../../common/utils';
+import { IKibanaSearchRequest } from '../../common/search';
+import { ISearchGeneric, ISearchOptions } from './i_search';
+import { RequestTimeoutError } from './request_timeout_error';
+
+export class SearchInterceptor {
+ /**
+ * `abortController` used to signal all searches to abort.
+ */
+ private abortController = new AbortController();
+
+ /**
+ * Observable that emits when the number of pending requests changes.
+ */
+ private pendingCount$ = new BehaviorSubject(0);
+
+ /**
+ * The IDs from `setTimeout` when scheduling the automatic timeout for each request.
+ */
+ private timeoutIds: Set = new Set();
+
+ /**
+ * This class should be instantiated with a `requestTimeout` corresponding with how many ms after
+ * requests are initiated that they should automatically cancel.
+ * @param requestTimeout Usually config value `elasticsearch.requestTimeout`
+ */
+ constructor(private readonly requestTimeout?: number) {}
+
+ /**
+ * Abort our `AbortController`, which in turn aborts any intercepted searches.
+ */
+ public cancelPending = () => {
+ this.abortController.abort();
+ this.abortController = new AbortController();
+ };
+
+ /**
+ * Un-schedule timing out all of the searches intercepted.
+ */
+ public runBeyondTimeout = () => {
+ this.timeoutIds.forEach(clearTimeout);
+ this.timeoutIds.clear();
+ };
+
+ /**
+ * Returns an `Observable` over the current number of pending searches. This could mean that one
+ * of the search requests is still in flight, or that it has only received partial responses.
+ */
+ public getPendingCount$ = () => {
+ return this.pendingCount$.asObservable();
+ };
+
+ /**
+ * Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort
+ * either when `cancelPending` is called, when the request times out, or when the original
+ * `AbortSignal` is aborted. Updates the `pendingCount` when the request is started/finalized.
+ */
+ public search = (
+ search: ISearchGeneric,
+ request: IKibanaSearchRequest,
+ options?: ISearchOptions
+ ) => {
+ // Schedule this request to automatically timeout after some interval
+ const timeoutController = new AbortController();
+ const { signal: timeoutSignal } = timeoutController;
+ const timeoutId = window.setTimeout(() => {
+ timeoutController.abort();
+ }, this.requestTimeout);
+ this.addTimeoutId(timeoutId);
+
+ // Get a combined `AbortSignal` that will be aborted whenever the first of the following occurs:
+ // 1. The user manually aborts (via `cancelPending`)
+ // 2. The request times out
+ // 3. The passed-in signal aborts (e.g. when re-fetching, or whenever the app determines)
+ const signals = [this.abortController.signal, timeoutSignal, options?.signal].filter(
+ Boolean
+ ) as AbortSignal[];
+ const combinedSignal = getCombinedSignal(signals);
+
+ // If the request timed out, throw a `RequestTimeoutError`
+ const timeoutError$ = fromEvent(timeoutSignal, 'abort').pipe(
+ mergeMap(() => throwError(new RequestTimeoutError()))
+ );
+
+ return search(request as any, { ...options, signal: combinedSignal }).pipe(
+ takeUntil(timeoutError$),
+ finalize(() => this.removeTimeoutId(timeoutId))
+ );
+ };
+
+ private addTimeoutId(id: number) {
+ this.timeoutIds.add(id);
+ this.pendingCount$.next(this.timeoutIds.size);
+ }
+
+ private removeTimeoutId(id: number) {
+ this.timeoutIds.delete(id);
+ this.pendingCount$.next(this.timeoutIds.size);
+ }
+}
diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts
index 691c8aa0e984db..62c7e0468bb886 100644
--- a/src/plugins/data/public/search/search_service.ts
+++ b/src/plugins/data/public/search/search_service.ts
@@ -25,6 +25,7 @@ import { TStrategyTypes } from './strategy_types';
import { getEsClient, LegacyApiCaller } from './es_client';
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
import { esSearchStrategyProvider } from './es_search/es_search_strategy';
+import { SearchInterceptor } from './search_interceptor';
import {
getAggTypes,
AggType,
@@ -91,6 +92,16 @@ export class SearchService implements Plugin {
}
public start(core: CoreStart): ISearchStart {
+ /**
+ * A global object that intercepts all searches and provides convenience methods for cancelling
+ * all pending search requests, as well as getting the number of pending search requests.
+ * TODO: Make this modular so that apps can opt in/out of search collection, or even provide
+ * their own search collector instances
+ */
+ const searchInterceptor = new SearchInterceptor(
+ core.injectedMetadata.getInjectedVar('esRequestTimeout') as number
+ );
+
const aggTypesStart = this.aggTypesRegistry.start();
return {
@@ -103,13 +114,16 @@ export class SearchService implements Plugin {
},
types: aggTypesStart,
},
+ cancel: () => searchInterceptor.cancelPending(),
+ getPendingCount$: () => searchInterceptor.getPendingCount$(),
+ runBeyondTimeout: () => searchInterceptor.runBeyondTimeout(),
search: (request, options, strategyName) => {
const strategyProvider = this.getSearchStrategy(strategyName || DEFAULT_SEARCH_STRATEGY);
const { search } = strategyProvider({
core,
getSearchStrategy: this.getSearchStrategy,
});
- return search(request as any, options);
+ return searchInterceptor.search(search as any, request, options);
},
__LEGACY: {
esClient: this.esClient!,
diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts
index d2b8308bfb258f..fcd116a3f41211 100644
--- a/src/plugins/data/public/search/search_source/search_source.test.ts
+++ b/src/plugins/data/public/search/search_source/search_source.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { SearchSource } from '../search_source';
+import { SearchSource } from './search_source';
import { IndexPattern } from '../..';
import { mockDataServices } from '../aggs/test_helpers';
diff --git a/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts
index e4f492c89e0efd..210a0e5fd1ac78 100644
--- a/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts
+++ b/src/plugins/data/public/search/search_strategy/default_search_strategy.test.ts
@@ -18,9 +18,9 @@
*/
import { IUiSettingsClient } from '../../../../../core/public';
-import { ISearchStart } from '../types';
import { SearchStrategySearchParams } from './types';
import { defaultSearchStrategy } from './default_search_strategy';
+import { searchStartMock } from '../mocks';
const { search } = defaultSearchStrategy;
@@ -56,6 +56,12 @@ describe('defaultSearchStrategy', function() {
searchMockResponse.abort.mockClear();
searchMock.mockClear();
+ const searchService = searchStartMock;
+ searchService.aggs.calculateAutoTimeExpression = jest.fn().mockReturnValue('1d');
+ searchService.search = newSearchMock;
+ searchService.__LEGACY.esClient.search = searchMock;
+ searchService.__LEGACY.esClient.msearch = msearchMock;
+
searchArgs = {
searchRequests: [
{
@@ -63,15 +69,7 @@ describe('defaultSearchStrategy', function() {
},
],
esShardTimeout: 0,
- searchService: ({
- search: newSearchMock,
- __LEGACY: {
- esClient: {
- search: searchMock,
- msearch: msearchMock,
- },
- },
- } as unknown) as jest.Mocked,
+ searchService,
};
es = searchArgs.searchService.__LEGACY.esClient;
diff --git a/src/plugins/data/public/search/types.ts b/src/plugins/data/public/search/types.ts
index 1732c384b1a856..1b551f978b9716 100644
--- a/src/plugins/data/public/search/types.ts
+++ b/src/plugins/data/public/search/types.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import { Observable } from 'rxjs';
import { CoreStart } from 'kibana/public';
import { SearchAggsSetup, SearchAggsStart, SearchAggsStartLegacy } from './aggs';
import { ISearch, ISearchGeneric } from './i_search';
@@ -86,6 +87,9 @@ export interface ISearchSetup {
export interface ISearchStart {
aggs: SearchAggsStart;
+ cancel: () => void;
+ getPendingCount$: () => Observable;
+ runBeyondTimeout: () => void;
search: ISearchGeneric;
__LEGACY: ISearchStartLegacy & SearchAggsStartLegacy;
}
diff --git a/src/plugins/data/server/autocomplete/value_suggestions_route.ts b/src/plugins/data/server/autocomplete/value_suggestions_route.ts
index 03dbd409844126..b7569a22e9fc9b 100644
--- a/src/plugins/data/server/autocomplete/value_suggestions_route.ts
+++ b/src/plugins/data/server/autocomplete/value_suggestions_route.ts
@@ -39,7 +39,7 @@ export function registerValueSuggestionsRoute(
{
index: schema.string(),
},
- { allowUnknowns: false }
+ { unknowns: 'allow' }
),
body: schema.object(
{
@@ -47,7 +47,7 @@ export function registerValueSuggestionsRoute(
query: schema.string(),
boolFilter: schema.maybe(schema.any()),
},
- { allowUnknowns: false }
+ { unknowns: 'allow' }
),
},
},
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index 0165486fc2de71..5038b4226fad87 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -166,7 +166,7 @@ export { ParsedInterval } from '../common';
export {
ISearch,
- ICancel,
+ ISearchCancel,
ISearchOptions,
IRequestTypesMap,
IResponseTypesMap,
diff --git a/src/plugins/data/server/search/i_route_handler_search_context.ts b/src/plugins/data/server/search/i_route_handler_search_context.ts
index 89862781b826e7..9888c774ea104c 100644
--- a/src/plugins/data/server/search/i_route_handler_search_context.ts
+++ b/src/plugins/data/server/search/i_route_handler_search_context.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { ISearchGeneric, ICancelGeneric } from './i_search';
+import { ISearchGeneric, ISearchCancelGeneric } from './i_search';
export interface IRouteHandlerSearchContext {
search: ISearchGeneric;
- cancel: ICancelGeneric;
+ cancel: ISearchCancelGeneric;
}
diff --git a/src/plugins/data/server/search/i_search.ts b/src/plugins/data/server/search/i_search.ts
index ea014c5e136d92..fa4aa72ac7287e 100644
--- a/src/plugins/data/server/search/i_search.ts
+++ b/src/plugins/data/server/search/i_search.ts
@@ -42,7 +42,7 @@ export type ISearchGeneric = Promise;
-export type ICancelGeneric = (
+export type ISearchCancelGeneric = (
id: string,
strategy?: T
) => Promise;
@@ -52,4 +52,4 @@ export type ISearch = (
options?: ISearchOptions
) => Promise;
-export type ICancel = (id: string) => Promise;
+export type ISearchCancel = (id: string) => Promise;
diff --git a/src/plugins/data/server/search/i_search_strategy.ts b/src/plugins/data/server/search/i_search_strategy.ts
index 4cfc9608383a90..9b405034f883f7 100644
--- a/src/plugins/data/server/search/i_search_strategy.ts
+++ b/src/plugins/data/server/search/i_search_strategy.ts
@@ -18,7 +18,7 @@
*/
import { APICaller } from 'kibana/server';
-import { ISearch, ICancel, ISearchGeneric } from './i_search';
+import { ISearch, ISearchCancel, ISearchGeneric } from './i_search';
import { TStrategyTypes } from './strategy_types';
import { ISearchContext } from './i_search_context';
@@ -28,7 +28,7 @@ import { ISearchContext } from './i_search_context';
*/
export interface ISearchStrategy {
search: ISearch;
- cancel?: ICancel;
+ cancel?: ISearchCancel;
}
/**
diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts
index 385e96ee803b64..15738a3befb275 100644
--- a/src/plugins/data/server/search/index.ts
+++ b/src/plugins/data/server/search/index.ts
@@ -21,7 +21,13 @@ export { ISearchSetup } from './i_search_setup';
export { ISearchContext } from './i_search_context';
-export { ISearch, ICancel, ISearchOptions, IRequestTypesMap, IResponseTypesMap } from './i_search';
+export {
+ ISearch,
+ ISearchCancel,
+ ISearchOptions,
+ IRequestTypesMap,
+ IResponseTypesMap,
+} from './i_search';
export { TStrategyTypes } from './strategy_types';
diff --git a/src/plugins/data/server/search/routes.ts b/src/plugins/data/server/search/routes.ts
index e618f99084aed2..b90d7d4ff80cea 100644
--- a/src/plugins/data/server/search/routes.ts
+++ b/src/plugins/data/server/search/routes.ts
@@ -28,9 +28,9 @@ export function registerSearchRoute(router: IRouter): void {
validate: {
params: schema.object({ strategy: schema.string() }),
- query: schema.object({}, { allowUnknowns: true }),
+ query: schema.object({}, { unknowns: 'allow' }),
- body: schema.object({}, { allowUnknowns: true }),
+ body: schema.object({}, { unknowns: 'allow' }),
},
},
async (context, request, res) => {
@@ -64,7 +64,7 @@ export function registerSearchRoute(router: IRouter): void {
id: schema.string(),
}),
- query: schema.object({}, { allowUnknowns: true }),
+ query: schema.object({}, { unknowns: 'allow' }),
},
},
async (context, request, res) => {
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index 2a2d9bb414c14f..178b2949a94569 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -329,12 +329,6 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): {
restTotalHitsAsInt: boolean;
};
-// Warning: (ae-forgotten-export) The symbol "TStrategyTypes" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ICancel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export type ICancel = (id: string) => Promise;
-
// Warning: (ae-missing-release-tag) "IFieldFormatsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -507,11 +501,17 @@ export interface IResponseTypesMap {
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
}
+// Warning: (ae-forgotten-export) The symbol "TStrategyTypes" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "ISearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ISearch = (request: IRequestTypesMap[T], options?: ISearchOptions) => Promise;
+// Warning: (ae-missing-release-tag) "ISearchCancel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export type ISearchCancel = (id: string) => Promise;
+
// Warning: (ae-missing-release-tag) "ISearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts
index 2925e5e16458e6..8ed01b9b61c7e2 100644
--- a/src/plugins/es_ui_shared/public/index.ts
+++ b/src/plugins/es_ui_shared/public/index.ts
@@ -27,3 +27,5 @@ export {
sendRequest,
useRequest,
} from './request/np_ready_request';
+
+export { indices } from './indices';
diff --git a/src/legacy/ui/public/indices/constants/index.js b/src/plugins/es_ui_shared/public/indices/constants/index.ts
similarity index 94%
rename from src/legacy/ui/public/indices/constants/index.js
rename to src/plugins/es_ui_shared/public/indices/constants/index.ts
index 72ecc2e4c87de2..825975fa161b55 100644
--- a/src/legacy/ui/public/indices/constants/index.js
+++ b/src/plugins/es_ui_shared/public/indices/constants/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { indexPatterns } from '../../../../../plugins/data/public';
+import { indexPatterns } from '../../../../data/public';
export const INDEX_ILLEGAL_CHARACTERS_VISIBLE = [...indexPatterns.ILLEGAL_CHARACTERS_VISIBLE, '*'];
diff --git a/src/plugins/es_ui_shared/public/indices/index.ts b/src/plugins/es_ui_shared/public/indices/index.ts
new file mode 100644
index 00000000000000..a6d279a5c2b4f0
--- /dev/null
+++ b/src/plugins/es_ui_shared/public/indices/index.ts
@@ -0,0 +1,33 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from './constants';
+
+import {
+ indexNameBeginsWithPeriod,
+ findIllegalCharactersInIndexName,
+ indexNameContainsSpaces,
+} from './validate';
+
+export const indices = {
+ INDEX_ILLEGAL_CHARACTERS_VISIBLE,
+ indexNameBeginsWithPeriod,
+ findIllegalCharactersInIndexName,
+ indexNameContainsSpaces,
+};
diff --git a/src/legacy/ui/public/indices/validate/index.js b/src/plugins/es_ui_shared/public/indices/validate/index.ts
similarity index 100%
rename from src/legacy/ui/public/indices/validate/index.js
rename to src/plugins/es_ui_shared/public/indices/validate/index.ts
diff --git a/src/legacy/ui/public/indices/validate/validate_index.test.js b/src/plugins/es_ui_shared/public/indices/validate/validate_index.test.ts
similarity index 100%
rename from src/legacy/ui/public/indices/validate/validate_index.test.js
rename to src/plugins/es_ui_shared/public/indices/validate/validate_index.test.ts
diff --git a/src/legacy/ui/public/indices/validate/validate_index.js b/src/plugins/es_ui_shared/public/indices/validate/validate_index.ts
similarity index 67%
rename from src/legacy/ui/public/indices/validate/validate_index.js
rename to src/plugins/es_ui_shared/public/indices/validate/validate_index.ts
index 5deaa83a807d98..00ac1342400ace 100644
--- a/src/legacy/ui/public/indices/validate/validate_index.js
+++ b/src/plugins/es_ui_shared/public/indices/validate/validate_index.ts
@@ -19,23 +19,29 @@
import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from '../constants';
-// Names beginning with periods are reserved for system indices.
-export function indexNameBeginsWithPeriod(indexName = '') {
+// Names beginning with periods are reserved for hidden indices.
+export function indexNameBeginsWithPeriod(indexName?: string): boolean {
+ if (indexName === undefined) {
+ return false;
+ }
return indexName[0] === '.';
}
-export function findIllegalCharactersInIndexName(indexName) {
- const illegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.reduce((chars, char) => {
- if (indexName.includes(char)) {
- chars.push(char);
- }
+export function findIllegalCharactersInIndexName(indexName: string): string[] {
+ const illegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.reduce(
+ (chars: string[], char: string): string[] => {
+ if (indexName.includes(char)) {
+ chars.push(char);
+ }
- return chars;
- }, []);
+ return chars;
+ },
+ []
+ );
return illegalCharacters;
}
-export function indexNameContainsSpaces(indexName) {
+export function indexNameContainsSpaces(indexName: string): boolean {
return indexName.includes(' ');
}
diff --git a/src/plugins/es_ui_shared/static/forms/helpers/field_validators/index_name.ts b/src/plugins/es_ui_shared/static/forms/helpers/field_validators/index_name.ts
index 524cac27341abd..5e969fa7151724 100644
--- a/src/plugins/es_ui_shared/static/forms/helpers/field_validators/index_name.ts
+++ b/src/plugins/es_ui_shared/static/forms/helpers/field_validators/index_name.ts
@@ -17,14 +17,11 @@
* under the License.
*/
-// Note: we can't import from "ui/indices" as the TS Type definition don't exist
-// import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
+import { indices } from '../../../../public';
import { ValidationFunc } from '../../hook_form_lib';
import { startsWith, containsChars } from '../../../validators/string';
import { ERROR_CODE } from './types';
-const INDEX_ILLEGAL_CHARACTERS = ['\\', '/', '?', '"', '<', '>', '|', '*'];
-
export const indexNameField = (i18n: any) => (
...args: Parameters
): ReturnType> => {
@@ -51,7 +48,9 @@ export const indexNameField = (i18n: any) => (
};
}
- const { charsFound, doesContain } = containsChars(INDEX_ILLEGAL_CHARACTERS)(value as string);
+ const { charsFound, doesContain } = containsChars(indices.INDEX_ILLEGAL_CHARACTERS_VISIBLE)(
+ value as string
+ );
if (doesContain) {
return {
message: i18n.translate('esUi.forms.fieldValidation.indexNameInvalidCharactersError', {
diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts
index f70a32f2f09c12..d0ab178296408a 100644
--- a/src/plugins/expressions/common/execution/execution.ts
+++ b/src/plugins/expressions/common/execution/execution.ts
@@ -22,6 +22,7 @@ import { Executor } from '../executor';
import { createExecutionContainer, ExecutionContainer } from './container';
import { createError } from '../util';
import { Defer, now } from '../../../kibana_utils/common';
+import { AbortError } from '../../../data/common';
import { RequestAdapter, DataAdapter } from '../../../inspector/common';
import { isExpressionValueError, ExpressionValueError } from '../expression_types/specs/error';
import {
@@ -190,10 +191,7 @@ export class Execution<
for (const link of chainArr) {
// if execution was aborted return error
if (this.context.abortSignal && this.context.abortSignal.aborted) {
- return createError({
- message: 'The expression was aborted.',
- name: 'AbortError',
- });
+ return createError(new AbortError('The expression was aborted.'));
}
const { function: fnName, arguments: fnArgs } = link;
diff --git a/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts b/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts
index 4092dfbba00d51..b8be273d7bbd32 100644
--- a/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts
+++ b/src/plugins/expressions/common/expression_functions/specs/kibana_context.ts
@@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+import { uniq } from 'lodash';
import { i18n } from '@kbn/i18n';
import { ExpressionFunctionDefinition } from '../../expression_functions';
import { KibanaContext } from '../../expression_types';
+import { Query, uniqFilters } from '../../../../data/common';
interface Arguments {
q?: string | null;
@@ -35,6 +36,15 @@ export type ExpressionFunctionKibanaContext = ExpressionFunctionDefinition<
Promise
>;
+const getParsedValue = (data: any, defaultValue: any) =>
+ typeof data === 'string' && data.length ? JSON.parse(data) || defaultValue : defaultValue;
+
+const mergeQueries = (first: Query | Query[] = [], second: Query | Query[]) =>
+ uniq(
+ [...(Array.isArray(first) ? first : [first]), ...(Array.isArray(second) ? second : [second])],
+ (n: any) => JSON.stringify(n.query)
+ );
+
export const kibanaContextFunction: ExpressionFunctionKibanaContext = {
name: 'kibana_context',
type: 'kibana_context',
@@ -75,9 +85,9 @@ export const kibanaContextFunction: ExpressionFunctionKibanaContext = {
},
async fn(input, args, { getSavedObject }) {
- const queryArg = args.q ? JSON.parse(args.q) : [];
- let queries = Array.isArray(queryArg) ? queryArg : [queryArg];
- let filters = args.filters ? JSON.parse(args.filters) : [];
+ const timeRange = getParsedValue(args.timeRange, input?.timeRange);
+ let queries = mergeQueries(input?.query, getParsedValue(args?.q, []));
+ let filters = [...(input?.filters || []), ...getParsedValue(args?.filters, [])];
if (args.savedSearchId) {
if (typeof getSavedObject !== 'function') {
@@ -89,29 +99,20 @@ export const kibanaContextFunction: ExpressionFunctionKibanaContext = {
}
const obj = await getSavedObject('search', args.savedSearchId);
const search = obj.attributes.kibanaSavedObjectMeta as { searchSourceJSON: string };
- const data = JSON.parse(search.searchSourceJSON) as { query: string; filter: any[] };
- queries = queries.concat(data.query);
- filters = filters.concat(data.filter);
- }
+ const { query, filter } = getParsedValue(search.searchSourceJSON, {});
- if (input && input.query) {
- queries = queries.concat(input.query);
- }
-
- if (input && input.filters) {
- filters = filters.concat(input.filters).filter((f: any) => !f.meta.disabled);
+ if (query) {
+ queries = mergeQueries(queries, query);
+ }
+ if (filter) {
+ filters = [...filters, ...(Array.isArray(filter) ? filter : [filter])];
+ }
}
- const timeRange = args.timeRange
- ? JSON.parse(args.timeRange)
- : input
- ? input.timeRange
- : undefined;
-
return {
type: 'kibana_context',
query: queries,
- filters,
+ filters: uniqFilters(filters).filter((f: any) => !f.meta?.disabled),
timeRange,
};
},
diff --git a/src/plugins/kibana_legacy/public/angular/index.ts b/src/plugins/kibana_legacy/public/angular/index.ts
index 5fc37ac39612a4..16bae6c4cffe06 100644
--- a/src/plugins/kibana_legacy/public/angular/index.ts
+++ b/src/plugins/kibana_legacy/public/angular/index.ts
@@ -21,7 +21,6 @@ export { PromiseServiceCreator } from './promises';
// @ts-ignore
export { watchMultiDecorator } from './watch_multi';
export * from './angular_config';
-export { ensureDefaultIndexPattern } from './ensure_default_index_pattern';
// @ts-ignore
export { createTopNavDirective, createTopNavHelper, loadKbnTopNavDirectives } from './kbn_top_nav';
export { subscribeWithScope } from './subscribe_with_scope';
diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap b/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap
index 39bd66ff71c617..ee97a5acfd3d23 100644
--- a/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap
+++ b/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap
@@ -17,27 +17,88 @@ exports[`is rendered 1`] = `
-
-
- Exit full screen
-
-
-
-
+
+
+
+
+
+
+
+
+ Elastic Kibana
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss b/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss
index e810fe0ccdba6f..a2e951cb5b775c 100644
--- a/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss
+++ b/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss
@@ -4,66 +4,40 @@
*/
.dshExitFullScreenButton {
- height: $euiSizeXXL;
- left: 0;
- bottom: 0;
+ @include euiBottomShadow;
+
+ left: $euiSizeS;
+ bottom: $euiSizeS;
position: fixed;
display: block;
padding: 0;
border: none;
background: none;
z-index: 5;
+ background: $euiColorFullShade;
+ padding: $euiSizeXS;
+ border-radius: $euiBorderRadius;
+ text-align: left;
- &:hover,
- &:focus {
- transition: all $euiAnimSpeedExtraSlow $euiAnimSlightResistance;
- z-index: 10 !important; /* 1 */
+ &:hover {
+ background: $euiColorFullShade;
- .dshExitFullScreenButton__text {
- transition: all $euiAnimSpeedNormal $euiAnimSlightResistance;
- transform: translateX(-$euiSize);
+ .dshExitFullScreenButton__icon {
+ color: $euiColorEmptyShade;
}
}
}
-.dshExitFullScreenButton__logo {
- display: block;
- // Just darken the background for all themes because the logo is always white
- background-color: shade($euiColorPrimary, 25%);
- height: $euiSizeXXL;
-
- // These numbers are very specific to the Kibana logo size
- width: 92px;
- background-image: url('ui/assets/images/kibana.svg');
- background-position: 8px 5px;
- background-size: 72px 30px;
- background-repeat: no-repeat;
-
- z-index: $euiZLevel1;
+.dshExitFullScreenButton__title {
+ line-height: 1.2;
+ color: $euiColorEmptyShade;
}
-/**
- * 1. Calc made to allow caret in text to peek out / animate.
- */
-
.dshExitFullScreenButton__text {
- background: $euiColorPrimary;
- color: $euiColorEmptyShade;
- line-height: $euiSizeXXL;
- display: inline-block;
- font-size: $euiFontSizeS;
- height: $euiSizeXXL;
- position: absolute;
- left: calc(100% + #{$euiSize}); /* 1 */
- top: 0px;
- bottom: 0px;
- white-space: nowrap;
- padding: 0px $euiSizeXS 0px $euiSizeM;
- transition: all .2s ease;
- transform: translateX(-100%);
- z-index: -1;
-
- .euiIcon {
- margin-left: $euiSizeXS;
- }
+ line-height: 1.2;
+ color: makeHighContrastColor($euiColorMediumShade, $euiColorFullShade);
+}
+
+.dshExitFullScreenButton__icon {
+ color: makeHighContrastColor($euiColorMediumShade, $euiColorFullShade);
}
diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
index 5ce508ec1ed5b2..97fc02ac64e124 100644
--- a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
+++ b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx
@@ -20,7 +20,7 @@
import { i18n } from '@kbn/i18n';
import React, { PureComponent } from 'react';
import { EuiScreenReaderOnly, keyCodes } from '@elastic/eui';
-import { EuiIcon } from '@elastic/eui';
+import { EuiIcon, EuiTitle, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
export interface ExitFullScreenButtonProps {
onExitFullScreenMode: () => void;
@@ -61,17 +61,40 @@ class ExitFullScreenButtonUi extends PureComponent {
)}
className="dshExitFullScreenButton"
onClick={this.props.onExitFullScreenMode}
+ data-test-subj="exitFullScreenModeLogo"
>
-
-
- {i18n.translate('kibana-react.exitFullScreenButton.exitFullScreenModeButtonLabel', {
- defaultMessage: 'Exit full screen',
- })}
-
-
+
+
+
+
+
+
+
+
+ {i18n.translate(
+ 'kibana-react.exitFullScreenButton.exitFullScreenModeButtonTitle',
+ {
+ defaultMessage: 'Elastic Kibana',
+ }
+ )}
+
+
+
+
+ {i18n.translate(
+ 'kibana-react.exitFullScreenButton.exitFullScreenModeButtonText',
+ {
+ defaultMessage: 'Exit full screen',
+ }
+ )}
+
+
+
+
+
+
+
+
diff --git a/src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx b/src/plugins/kibana_utils/public/history/ensure_default_index_pattern.tsx
similarity index 67%
rename from src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx
rename to src/plugins/kibana_utils/public/history/ensure_default_index_pattern.tsx
index 1a3bb84ae75751..7992f650cb372d 100644
--- a/src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx
+++ b/src/plugins/kibana_utils/public/history/ensure_default_index_pattern.tsx
@@ -18,14 +18,13 @@
*/
import { contains } from 'lodash';
-import { IRootScopeService } from 'angular';
import React from 'react';
-import ReactDOM from 'react-dom';
+import { History } from 'history';
import { i18n } from '@kbn/i18n';
-import { I18nProvider } from '@kbn/i18n/react';
import { EuiCallOut } from '@elastic/eui';
import { CoreStart } from 'kibana/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
+import { toMountPoint } from '../../../kibana_react/public';
let bannerId: string;
let timeoutId: NodeJS.Timeout | undefined;
@@ -39,18 +38,17 @@ let timeoutId: NodeJS.Timeout | undefined;
* resolve to wait for the URL change to happen.
*/
export async function ensureDefaultIndexPattern(
- newPlatform: CoreStart,
+ core: CoreStart,
data: DataPublicPluginStart,
- $rootScope: IRootScopeService,
- kbnUrl: any
+ history: History
) {
const patterns = await data.indexPatterns.getIds();
- let defaultId = newPlatform.uiSettings.get('defaultIndex');
+ let defaultId = core.uiSettings.get('defaultIndex');
let defined = !!defaultId;
const exists = contains(patterns, defaultId);
if (defined && !exists) {
- newPlatform.uiSettings.remove('defaultIndex');
+ core.uiSettings.remove('defaultIndex');
defaultId = defined = false;
}
@@ -61,10 +59,9 @@ export async function ensureDefaultIndexPattern(
// If there is any index pattern created, set the first as default
if (patterns.length >= 1) {
defaultId = patterns[0];
- newPlatform.uiSettings.set('defaultIndex', defaultId);
+ core.uiSettings.set('defaultIndex', defaultId);
} else {
- const canManageIndexPatterns =
- newPlatform.application.capabilities.management.kibana.index_patterns;
+ const canManageIndexPatterns = core.application.capabilities.management.kibana.index_patterns;
const redirectTarget = canManageIndexPatterns ? '/management/kibana/index_pattern' : '/home';
if (timeoutId) {
@@ -73,31 +70,27 @@ export async function ensureDefaultIndexPattern(
// Avoid being hostile to new users who don't have an index pattern setup yet
// give them a friendly info message instead of a terse error message
- bannerId = newPlatform.overlays.banners.replace(bannerId, (element: HTMLElement) => {
- ReactDOM.render(
-
-
- ,
- element
- );
- return () => ReactDOM.unmountComponentAtNode(element);
- });
+ bannerId = core.overlays.banners.replace(
+ bannerId,
+ toMountPoint(
+
+ )
+ );
// hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around
timeoutId = setTimeout(() => {
- newPlatform.overlays.banners.remove(bannerId);
+ core.overlays.banners.remove(bannerId);
timeoutId = undefined;
}, 15000);
- kbnUrl.change(redirectTarget);
- $rootScope.$digest();
+ history.push(redirectTarget);
// return never-resolving promise to stop resolving and wait for the url change
return new Promise(() => {});
diff --git a/src/plugins/kibana_utils/public/history/index.ts b/src/plugins/kibana_utils/public/history/index.ts
index b4b5658c1c886e..1a73bbb6b04a1b 100644
--- a/src/plugins/kibana_utils/public/history/index.ts
+++ b/src/plugins/kibana_utils/public/history/index.ts
@@ -18,3 +18,5 @@
*/
export { removeQueryParam } from './remove_query_param';
+export { redirectWhenMissing } from './redirect_when_missing';
+export { ensureDefaultIndexPattern } from './ensure_default_index_pattern';
diff --git a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx
new file mode 100644
index 00000000000000..cbdeef6fbe96ca
--- /dev/null
+++ b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx
@@ -0,0 +1,80 @@
+/*
+ * 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 { History } from 'history';
+import { i18n } from '@kbn/i18n';
+
+import { ToastsSetup } from 'kibana/public';
+import { MarkdownSimple, toMountPoint } from '../../../kibana_react/public';
+import { SavedObjectNotFound } from '../errors';
+
+interface Mapping {
+ [key: string]: string;
+}
+
+/**
+ * Creates an error handler that will redirect to a url when a SavedObjectNotFound
+ * error is thrown
+ */
+export function redirectWhenMissing({
+ history,
+ mapping,
+ toastNotifications,
+}: {
+ history: History;
+ /**
+ * a mapping of url's to redirect to based on the saved object that
+ * couldn't be found, or just a string that will be used for all types
+ */
+ mapping: string | Mapping;
+ /**
+ * Toast notifications service to show toasts in error cases.
+ */
+ toastNotifications: ToastsSetup;
+}) {
+ let localMappingObject: Mapping;
+
+ if (typeof mapping === 'string') {
+ localMappingObject = { '*': mapping };
+ } else {
+ localMappingObject = mapping;
+ }
+
+ return (error: SavedObjectNotFound) => {
+ // if this error is not "404", rethrow
+ // we can't check "error instanceof SavedObjectNotFound" since this class can live in a separate bundle
+ // and the error will be an instance of other class with the same interface (actually the copy of SavedObjectNotFound class)
+ if (!error.savedObjectType) {
+ throw error;
+ }
+
+ let url = localMappingObject[error.savedObjectType] || localMappingObject['*'] || '/';
+ url += (url.indexOf('?') >= 0 ? '&' : '?') + `notFound=${error.savedObjectType}`;
+
+ toastNotifications.addWarning({
+ title: i18n.translate('kibana_utils.history.savedObjectIsMissingNotificationMessage', {
+ defaultMessage: 'Saved object is missing',
+ }),
+ text: toMountPoint({error.message} ),
+ });
+
+ history.replace(url);
+ };
+}
diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts
index ee38d5e8111c92..1876e688c989ac 100644
--- a/src/plugins/kibana_utils/public/index.ts
+++ b/src/plugins/kibana_utils/public/index.ts
@@ -73,5 +73,5 @@ export {
StartSyncStateFnType,
StopSyncStateFnType,
} from './state_sync';
-export { removeQueryParam } from './history';
+export { removeQueryParam, redirectWhenMissing, ensureDefaultIndexPattern } from './history';
export { applyDiff } from './state_management/utils/diff_object';
diff --git a/src/plugins/timelion/config.ts b/src/plugins/timelion/config.ts
index 561fb4de9f58db..eaea1aaca1b7b7 100644
--- a/src/plugins/timelion/config.ts
+++ b/src/plugins/timelion/config.ts
@@ -25,7 +25,7 @@ export const configSchema = schema.object(
graphiteUrls: schema.maybe(schema.arrayOf(schema.string())),
},
// This option should be removed as soon as we entirely migrate config from legacy Timelion plugin.
- { allowUnknowns: true }
+ { unknowns: 'allow' }
);
export type ConfigSchema = TypeOf;
diff --git a/src/plugins/timelion/server/routes/run.ts b/src/plugins/timelion/server/routes/run.ts
index b7a4179da768ea..b773bba68ea818 100644
--- a/src/plugins/timelion/server/routes/run.ts
+++ b/src/plugins/timelion/server/routes/run.ts
@@ -78,15 +78,11 @@ export function runRoute(
es: schema.object({
filter: schema.object({
bool: schema.object({
- filter: schema.maybe(
- schema.arrayOf(schema.object({}, { allowUnknowns: true }))
- ),
- must: schema.maybe(schema.arrayOf(schema.object({}, { allowUnknowns: true }))),
- should: schema.maybe(
- schema.arrayOf(schema.object({}, { allowUnknowns: true }))
- ),
+ filter: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
+ must: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
+ should: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))),
must_not: schema.maybe(
- schema.arrayOf(schema.object({}, { allowUnknowns: true }))
+ schema.arrayOf(schema.object({}, { unknowns: 'allow' }))
),
}),
}),
diff --git a/src/plugins/vis_type_timeseries/server/routes/vis.ts b/src/plugins/vis_type_timeseries/server/routes/vis.ts
index e2d1e4d114ad5d..9abbc4ad617dc2 100644
--- a/src/plugins/vis_type_timeseries/server/routes/vis.ts
+++ b/src/plugins/vis_type_timeseries/server/routes/vis.ts
@@ -23,7 +23,7 @@ import { getVisData, GetVisDataOptions } from '../lib/get_vis_data';
import { visPayloadSchema } from './post_vis_schema';
import { Framework, ValidationTelemetryServiceSetup } from '../index';
-const escapeHatch = schema.object({}, { allowUnknowns: true });
+const escapeHatch = schema.object({}, { unknowns: 'allow' });
export const visDataRoutes = (
router: IRouter,
diff --git a/src/setup_node_env/exit_on_warning.js b/src/setup_node_env/exit_on_warning.js
index 5be5ccd72bd024..6321cd7ba8db0f 100644
--- a/src/setup_node_env/exit_on_warning.js
+++ b/src/setup_node_env/exit_on_warning.js
@@ -35,4 +35,16 @@ if (process.noProcessWarnings !== true) {
process.exit(1);
});
+
+ // While the above warning listener would also be called on
+ // unhandledRejection warnings, we can give a better error message if we
+ // handle them separately:
+ process.on('unhandledRejection', function(reason) {
+ console.error('Unhandled Promise rejection detected:');
+ console.error();
+ console.error(reason);
+ console.error();
+ console.error('Terminating process...');
+ process.exit(1);
+ });
}
diff --git a/test/common/services/security/role.ts b/test/common/services/security/role.ts
index 0e7572882f80d2..dfc6ff9b164e50 100644
--- a/test/common/services/security/role.ts
+++ b/test/common/services/security/role.ts
@@ -43,7 +43,6 @@ export class Role {
`Expected status code of 204, received ${status} ${statusText}: ${util.inspect(data)}`
);
}
- this.log.debug(`created role ${name}`);
}
public async delete(name: string) {
@@ -56,6 +55,5 @@ export class Role {
)}`
);
}
- this.log.debug(`deleted role ${name}`);
}
}
diff --git a/test/common/services/security/security.ts b/test/common/services/security/security.ts
index 4eebb7b6697e01..6ad0933a2a5a23 100644
--- a/test/common/services/security/security.ts
+++ b/test/common/services/security/security.ts
@@ -23,15 +23,21 @@ import { Role } from './role';
import { User } from './user';
import { RoleMappings } from './role_mappings';
import { FtrProviderContext } from '../../ftr_provider_context';
+import { createTestUserService } from './test_user';
-export function SecurityServiceProvider({ getService }: FtrProviderContext) {
+export async function SecurityServiceProvider(context: FtrProviderContext) {
+ const { getService } = context;
const log = getService('log');
const config = getService('config');
const url = formatUrl(config.get('servers.kibana'));
+ const role = new Role(url, log);
+ const user = new User(url, log);
+ const testUser = await createTestUserService(role, user, context);
return new (class SecurityService {
- role = new Role(url, log);
roleMappings = new RoleMappings(url, log);
- user = new User(url, log);
+ testUser = testUser;
+ role = role;
+ user = user;
})();
}
diff --git a/test/common/services/security/test_user.ts b/test/common/services/security/test_user.ts
new file mode 100644
index 00000000000000..7f01c64d291a53
--- /dev/null
+++ b/test/common/services/security/test_user.ts
@@ -0,0 +1,92 @@
+/*
+ * 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 { Role } from './role';
+import { User } from './user';
+import { FtrProviderContext } from '../../ftr_provider_context';
+import { Browser } from '../../../functional/services/browser';
+import { TestSubjects } from '../../../functional/services/test_subjects';
+
+export async function createTestUserService(
+ role: Role,
+ user: User,
+ { getService, hasService }: FtrProviderContext
+) {
+ const log = getService('log');
+ const config = getService('config');
+ // @ts-ignore browser service is not normally available in common.
+ const browser: Browser | void = hasService('browser') && getService('browser');
+ const testSubjects: TestSubjects | void =
+ // @ts-ignore testSubject service is not normally available in common.
+ hasService('testSubjects') && getService('testSubjects');
+ const kibanaServer = getService('kibanaServer');
+
+ const enabledPlugins = config.get('security.disableTestUser')
+ ? []
+ : await kibanaServer.plugins.getEnabledIds();
+ const isEnabled = () => {
+ return enabledPlugins.includes('security') && !config.get('security.disableTestUser');
+ };
+ if (isEnabled()) {
+ log.debug('===============creating roles and users===============');
+ for (const [name, definition] of Object.entries(config.get('security.roles'))) {
+ // create the defined roles (need to map array to create roles)
+ await role.create(name, definition);
+ }
+ try {
+ // delete the test_user if present (will it error if the user doesn't exist?)
+ await user.delete('test_user');
+ } catch (exception) {
+ log.debug('no test user to delete');
+ }
+
+ // create test_user with username and pwd
+ log.debug(`default roles = ${config.get('security.defaultRoles')}`);
+ await user.create('test_user', {
+ password: 'changeme',
+ roles: config.get('security.defaultRoles'),
+ full_name: 'test user',
+ });
+ }
+
+ return new (class TestUser {
+ async restoreDefaults() {
+ if (isEnabled()) {
+ await this.setRoles(config.get('security.defaultRoles'));
+ }
+ }
+
+ async setRoles(roles: string[]) {
+ if (isEnabled()) {
+ log.debug(`set roles = ${roles}`);
+ await user.create('test_user', {
+ password: 'changeme',
+ roles,
+ full_name: 'test user',
+ });
+
+ if (browser && testSubjects) {
+ if (await testSubjects.exists('kibanaChrome', { allowHidden: true })) {
+ await browser.refresh();
+ await testSubjects.find('kibanaChrome', config.get('timeouts.find') * 10);
+ }
+ }
+ }
+ }
+ })();
+}
diff --git a/test/functional/apps/context/_date_nanos.js b/test/functional/apps/context/_date_nanos.js
index d4acdb0b4d5c07..bd132e3745caab 100644
--- a/test/functional/apps/context/_date_nanos.js
+++ b/test/functional/apps/context/_date_nanos.js
@@ -26,11 +26,13 @@ const TEST_STEP_SIZE = 3;
export default function({ getService, getPageObjects }) {
const kibanaServer = getService('kibanaServer');
const docTable = getService('docTable');
+ const security = getService('security');
const PageObjects = getPageObjects(['common', 'context', 'timePicker', 'discover']);
const esArchiver = getService('esArchiver');
describe('context view for date_nanos', () => {
before(async function() {
+ await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos']);
await esArchiver.loadIfNeeded('date_nanos');
await kibanaServer.uiSettings.replace({ defaultIndex: TEST_INDEX_PATTERN });
await kibanaServer.uiSettings.update({
@@ -39,8 +41,9 @@ export default function({ getService, getPageObjects }) {
});
});
- after(function unloadMakelogs() {
- return esArchiver.unload('date_nanos');
+ after(async function unloadMakelogs() {
+ await security.testUser.restoreDefaults();
+ await esArchiver.unload('date_nanos');
});
it('displays predessors - anchor - successors in right order ', async function() {
diff --git a/test/functional/apps/context/_date_nanos_custom_timestamp.js b/test/functional/apps/context/_date_nanos_custom_timestamp.js
index 046cca0aba8c6d..7834b29931a650 100644
--- a/test/functional/apps/context/_date_nanos_custom_timestamp.js
+++ b/test/functional/apps/context/_date_nanos_custom_timestamp.js
@@ -26,12 +26,14 @@ const TEST_STEP_SIZE = 3;
export default function({ getService, getPageObjects }) {
const kibanaServer = getService('kibanaServer');
const docTable = getService('docTable');
+ const security = getService('security');
const PageObjects = getPageObjects(['common', 'context', 'timePicker', 'discover']);
const esArchiver = getService('esArchiver');
// skipped due to a recent change in ES that caused search_after queries with data containing
// custom timestamp formats like in the testdata to fail
describe.skip('context view for date_nanos with custom timestamp', () => {
before(async function() {
+ await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos_custom']);
await esArchiver.loadIfNeeded('date_nanos_custom');
await kibanaServer.uiSettings.replace({ defaultIndex: TEST_INDEX_PATTERN });
await kibanaServer.uiSettings.update({
@@ -40,10 +42,6 @@ export default function({ getService, getPageObjects }) {
});
});
- after(function unloadMakelogs() {
- return esArchiver.unload('date_nanos_custom');
- });
-
it('displays predessors - anchor - successors in right order ', async function() {
await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, '1');
const actualRowsText = await docTable.getRowsText();
@@ -54,5 +52,10 @@ export default function({ getService, getPageObjects }) {
];
expect(actualRowsText).to.eql(expectedRowsText);
});
+
+ after(async function() {
+ await security.testUser.restoreDefaults();
+ await esArchiver.unload('date_nanos_custom');
+ });
});
}
diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js
index ec8a48ca74911c..f388993dcaf7dc 100644
--- a/test/functional/apps/dashboard/dashboard_filtering.js
+++ b/test/functional/apps/dashboard/dashboard_filtering.js
@@ -33,6 +33,7 @@ export default function({ getService, getPageObjects }) {
const filterBar = getService('filterBar');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
+ const security = getService('security');
const dashboardPanelActions = getService('dashboardPanelActions');
const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']);
@@ -41,6 +42,7 @@ export default function({ getService, getPageObjects }) {
before(async () => {
await esArchiver.load('dashboard/current/kibana');
+ await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader', 'animals']);
await kibanaServer.uiSettings.replace({
defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c',
});
@@ -49,6 +51,10 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.gotoDashboardLandingPage();
});
+ after(async () => {
+ await security.testUser.restoreDefaults();
+ });
+
describe('adding a filter that excludes all data', () => {
before(async () => {
await PageObjects.dashboard.clickNewDashboard();
diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js
index 13e8631445393a..5e96a55b190149 100644
--- a/test/functional/apps/dashboard/index.js
+++ b/test/functional/apps/dashboard/index.js
@@ -23,6 +23,7 @@ export default function({ getService, loadTestFile }) {
async function loadCurrentData() {
await browser.setWindowSize(1300, 900);
+ await esArchiver.unload('logstash_functional');
await esArchiver.loadIfNeeded('dashboard/current/data');
}
diff --git a/test/functional/apps/dashboard/time_zones.js b/test/functional/apps/dashboard/time_zones.js
index f374d6526fcf11..b7698a7d6ac4be 100644
--- a/test/functional/apps/dashboard/time_zones.js
+++ b/test/functional/apps/dashboard/time_zones.js
@@ -22,7 +22,6 @@ import expect from '@kbn/expect';
export default function({ getService, getPageObjects }) {
const pieChart = getService('pieChart');
- const browser = getService('browser');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['dashboard', 'timePicker', 'settings', 'common']);
@@ -48,7 +47,6 @@ export default function({ getService, getPageObjects }) {
after(async () => {
await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC' });
- await browser.refresh();
});
it('Exported dashboard adjusts EST time to UTC', async () => {
diff --git a/test/functional/apps/discover/_date_nanos.js b/test/functional/apps/discover/_date_nanos.js
index 9b06b9ac84cfdb..99a37cc18feaa8 100644
--- a/test/functional/apps/discover/_date_nanos.js
+++ b/test/functional/apps/discover/_date_nanos.js
@@ -23,6 +23,7 @@ export default function({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
const PageObjects = getPageObjects(['common', 'timePicker', 'discover']);
const kibanaServer = getService('kibanaServer');
+ const security = getService('security');
const fromTime = 'Sep 22, 2019 @ 20:31:44.000';
const toTime = 'Sep 23, 2019 @ 03:31:44.000';
@@ -30,12 +31,14 @@ export default function({ getService, getPageObjects }) {
before(async function() {
await esArchiver.loadIfNeeded('date_nanos');
await kibanaServer.uiSettings.replace({ defaultIndex: 'date-nanos' });
+ await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos']);
await PageObjects.common.navigateToApp('discover');
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
});
- after(function unloadMakelogs() {
- return esArchiver.unload('date_nanos');
+ after(async function unloadMakelogs() {
+ await security.testUser.restoreDefaults();
+ await esArchiver.unload('date_nanos');
});
it('should show a timestamp with nanoseconds in the first result row', async function() {
diff --git a/test/functional/apps/discover/_date_nanos_mixed.js b/test/functional/apps/discover/_date_nanos_mixed.js
index 0bb6848db4d102..b88ae87601cc5c 100644
--- a/test/functional/apps/discover/_date_nanos_mixed.js
+++ b/test/functional/apps/discover/_date_nanos_mixed.js
@@ -23,6 +23,7 @@ export default function({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
const PageObjects = getPageObjects(['common', 'timePicker', 'discover']);
const kibanaServer = getService('kibanaServer');
+ const security = getService('security');
const fromTime = 'Jan 1, 2019 @ 00:00:00.000';
const toTime = 'Jan 1, 2019 @ 23:59:59.999';
@@ -30,12 +31,14 @@ export default function({ getService, getPageObjects }) {
before(async function() {
await esArchiver.loadIfNeeded('date_nanos_mixed');
await kibanaServer.uiSettings.replace({ defaultIndex: 'timestamp-*' });
+ await security.testUser.setRoles(['kibana_admin', 'kibana_date_nanos_mixed']);
await PageObjects.common.navigateToApp('discover');
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
});
- after(function unloadMakelogs() {
- return esArchiver.unload('date_nanos_mixed');
+ after(async () => {
+ await security.testUser.restoreDefaults();
+ esArchiver.unload('date_nanos_mixed');
});
it('shows a list of records of indices with date & date_nanos fields in the right order', async function() {
diff --git a/test/functional/apps/discover/_discover_histogram.js b/test/functional/apps/discover/_discover_histogram.js
index 93108386662566..f815c505a8c277 100644
--- a/test/functional/apps/discover/_discover_histogram.js
+++ b/test/functional/apps/discover/_discover_histogram.js
@@ -25,6 +25,7 @@ export default function({ getService, getPageObjects }) {
const browser = getService('browser');
const elasticChart = getService('elasticChart');
const kibanaServer = getService('kibanaServer');
+ const security = getService('security');
const PageObjects = getPageObjects(['settings', 'common', 'discover', 'header', 'timePicker']);
const defaultSettings = {
defaultIndex: 'long-window-logstash-*',
@@ -35,6 +36,11 @@ export default function({ getService, getPageObjects }) {
before(async function() {
log.debug('load kibana index with default index pattern');
await PageObjects.common.navigateToApp('home');
+ await security.testUser.setRoles([
+ 'kibana_admin',
+ 'test_logstash_reader',
+ 'long_window_logstash',
+ ]);
await esArchiver.loadIfNeeded('logstash_functional');
await esArchiver.load('long_window_logstash');
await esArchiver.load('visualize');
@@ -56,6 +62,7 @@ export default function({ getService, getPageObjects }) {
await esArchiver.unload('long_window_logstash');
await esArchiver.unload('visualize');
await esArchiver.unload('discover');
+ await security.testUser.restoreDefaults();
});
it('should visualize monthly data with different day intervals', async () => {
diff --git a/test/functional/apps/discover/_large_string.js b/test/functional/apps/discover/_large_string.js
index a5052b2403074c..5e9048e2bc481a 100644
--- a/test/functional/apps/discover/_large_string.js
+++ b/test/functional/apps/discover/_large_string.js
@@ -25,10 +25,12 @@ export default function({ getService, getPageObjects }) {
const retry = getService('retry');
const kibanaServer = getService('kibanaServer');
const queryBar = getService('queryBar');
+ const security = getService('security');
const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover']);
describe('test large strings', function() {
before(async function() {
+ await security.testUser.setRoles(['kibana_admin', 'kibana_large_strings']);
await esArchiver.load('empty_kibana');
await esArchiver.loadIfNeeded('hamlet');
await kibanaServer.uiSettings.replace({ defaultIndex: 'testlargestring' });
@@ -77,6 +79,7 @@ export default function({ getService, getPageObjects }) {
});
after(async () => {
+ await security.testUser.restoreDefaults();
await esArchiver.unload('hamlet');
});
});
diff --git a/test/functional/apps/getting_started/_shakespeare.js b/test/functional/apps/getting_started/_shakespeare.js
index 5af1676cf423fb..ded4eca908410d 100644
--- a/test/functional/apps/getting_started/_shakespeare.js
+++ b/test/functional/apps/getting_started/_shakespeare.js
@@ -23,6 +23,7 @@ export default function({ getService, getPageObjects }) {
const log = getService('log');
const esArchiver = getService('esArchiver');
const retry = getService('retry');
+ const security = getService('security');
const PageObjects = getPageObjects([
'console',
'common',
@@ -46,11 +47,16 @@ export default function({ getService, getPageObjects }) {
'Load empty_kibana and Shakespeare Getting Started data\n' +
'https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html'
);
+ await security.testUser.setRoles(['kibana_admin', 'test_shakespeare_reader']);
await esArchiver.load('empty_kibana', { skipExisting: true });
log.debug('Load shakespeare data');
await esArchiver.loadIfNeeded('getting_started/shakespeare');
});
+ after(async () => {
+ await security.testUser.restoreDefaults();
+ });
+
it('should create shakespeare index pattern', async function() {
log.debug('Create shakespeare index pattern');
await PageObjects.settings.createIndexPattern('shakes', null);
diff --git a/test/functional/apps/home/_sample_data.ts b/test/functional/apps/home/_sample_data.ts
index 8bc528e045566a..5812b9b96e42a1 100644
--- a/test/functional/apps/home/_sample_data.ts
+++ b/test/functional/apps/home/_sample_data.ts
@@ -25,6 +25,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
const find = getService('find');
const log = getService('log');
+ const security = getService('security');
const pieChart = getService('pieChart');
const renderable = getService('renderable');
const dashboardExpect = getService('dashboardExpect');
@@ -34,10 +35,15 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
this.tags('smoke');
before(async () => {
+ await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']);
await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData');
await PageObjects.header.waitUntilLoadingHasFinished();
});
+ after(async () => {
+ await security.testUser.restoreDefaults();
+ });
+
it('should display registered flights sample data sets', async () => {
await retry.try(async () => {
const exists = await PageObjects.home.doesSampleDataSetExist('flights');
diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js
index 55f6b56d9f0d1d..4ef02f6c9e8730 100644
--- a/test/functional/apps/management/_handle_alias.js
+++ b/test/functional/apps/management/_handle_alias.js
@@ -23,11 +23,13 @@ export default function({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
const es = getService('legacyEs');
const retry = getService('retry');
+ const security = getService('security');
const PageObjects = getPageObjects(['common', 'home', 'settings', 'discover', 'timePicker']);
// FLAKY: https://github.com/elastic/kibana/issues/59717
describe.skip('Index patterns on aliases', function() {
before(async function() {
+ await security.testUser.setRoles(['kibana_admin', 'test_alias_reader']);
await esArchiver.loadIfNeeded('alias');
await esArchiver.load('empty_kibana');
await es.indices.updateAliases({
@@ -84,6 +86,7 @@ export default function({ getService, getPageObjects }) {
});
after(async () => {
+ await security.testUser.restoreDefaults();
await esArchiver.unload('alias');
});
});
diff --git a/test/functional/apps/management/_test_huge_fields.js b/test/functional/apps/management/_test_huge_fields.js
index 643cbcbe894822..bc280e51ae048c 100644
--- a/test/functional/apps/management/_test_huge_fields.js
+++ b/test/functional/apps/management/_test_huge_fields.js
@@ -21,6 +21,7 @@ import expect from '@kbn/expect';
export default function({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
+ const security = getService('security');
const PageObjects = getPageObjects(['common', 'home', 'settings']);
describe('test large number of fields', function() {
@@ -28,6 +29,7 @@ export default function({ getService, getPageObjects }) {
const EXPECTED_FIELD_COUNT = '10006';
before(async function() {
+ await security.testUser.setRoles(['kibana_admin', 'test_testhuge_reader']);
await esArchiver.loadIfNeeded('large_fields');
await PageObjects.settings.createIndexPattern('testhuge', 'date');
});
@@ -38,6 +40,7 @@ export default function({ getService, getPageObjects }) {
});
after(async () => {
+ await security.testUser.restoreDefaults();
await esArchiver.unload('large_fields');
});
});
diff --git a/test/functional/apps/saved_objects_management/edit_saved_object.ts b/test/functional/apps/saved_objects_management/edit_saved_object.ts
new file mode 100644
index 00000000000000..c001613f09f499
--- /dev/null
+++ b/test/functional/apps/saved_objects_management/edit_saved_object.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 expect from '@kbn/expect';
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
+
+export default function({ getPageObjects, getService }: FtrProviderContext) {
+ const esArchiver = getService('esArchiver');
+ const testSubjects = getService('testSubjects');
+ const PageObjects = getPageObjects(['common', 'settings']);
+
+ const setFieldValue = async (fieldName: string, value: string) => {
+ return testSubjects.setValue(`savedObjects-editField-${fieldName}`, value);
+ };
+
+ const getFieldValue = async (fieldName: string) => {
+ return testSubjects.getAttribute(`savedObjects-editField-${fieldName}`, 'value');
+ };
+
+ const focusAndClickButton = async (buttonSubject: string) => {
+ const button = await testSubjects.find(buttonSubject);
+ await button.scrollIntoViewIfNecessary();
+ await delay(10);
+ await button.focus();
+ await delay(10);
+ await button.click();
+ };
+
+ describe('TOTO saved objects edition page', () => {
+ beforeEach(async () => {
+ await esArchiver.load('saved_objects_management/edit_saved_object');
+ });
+
+ afterEach(async () => {
+ await esArchiver.unload('saved_objects_management/edit_saved_object');
+ });
+
+ it('allows to update the saved object when submitting', async () => {
+ await PageObjects.settings.navigateTo();
+ await PageObjects.settings.clickKibanaSavedObjects();
+
+ let objects = await PageObjects.settings.getSavedObjectsInTable();
+ expect(objects.includes('A Dashboard')).to.be(true);
+
+ await PageObjects.common.navigateToActualUrl(
+ 'kibana',
+ '/management/kibana/objects/savedDashboards/i-exist'
+ );
+
+ await testSubjects.existOrFail('savedObjectEditSave');
+
+ expect(await getFieldValue('title')).to.eql('A Dashboard');
+
+ await setFieldValue('title', 'Edited Dashboard');
+ await setFieldValue('description', 'Some description');
+
+ await focusAndClickButton('savedObjectEditSave');
+
+ objects = await PageObjects.settings.getSavedObjectsInTable();
+ expect(objects.includes('A Dashboard')).to.be(false);
+ expect(objects.includes('Edited Dashboard')).to.be(true);
+
+ await PageObjects.common.navigateToActualUrl(
+ 'kibana',
+ '/management/kibana/objects/savedDashboards/i-exist'
+ );
+
+ expect(await getFieldValue('title')).to.eql('Edited Dashboard');
+ expect(await getFieldValue('description')).to.eql('Some description');
+ });
+
+ it('allows to delete a saved object', async () => {
+ await PageObjects.common.navigateToActualUrl(
+ 'kibana',
+ '/management/kibana/objects/savedDashboards/i-exist'
+ );
+
+ await focusAndClickButton('savedObjectEditDelete');
+ await PageObjects.common.clickConfirmOnModal();
+
+ const objects = await PageObjects.settings.getSavedObjectsInTable();
+ expect(objects.includes('A Dashboard')).to.be(false);
+ });
+ });
+}
diff --git a/test/functional/apps/saved_objects_management/index.ts b/test/functional/apps/saved_objects_management/index.ts
new file mode 100644
index 00000000000000..ab43e18735ee77
--- /dev/null
+++ b/test/functional/apps/saved_objects_management/index.ts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function savedObjectsManagementApp({ loadTestFile }: FtrProviderContext) {
+ describe('saved objects management', function savedObjectsManagementAppTestSuite() {
+ this.tags('ciGroup7');
+ loadTestFile(require.resolve('./edit_saved_object'));
+ });
+}
diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js
index 101b2d4f547dd7..bf836cfe778b46 100644
--- a/test/functional/apps/visualize/_area_chart.js
+++ b/test/functional/apps/visualize/_area_chart.js
@@ -24,6 +24,7 @@ export default function({ getService, getPageObjects }) {
const inspector = getService('inspector');
const browser = getService('browser');
const retry = getService('retry');
+ const security = getService('security');
const PageObjects = getPageObjects([
'common',
'visualize',
@@ -58,7 +59,14 @@ export default function({ getService, getPageObjects }) {
return PageObjects.visEditor.clickGo();
};
- before(initAreaChart);
+ before(async function() {
+ await security.testUser.setRoles([
+ 'kibana_admin',
+ 'long_window_logstash',
+ 'test_logstash_reader',
+ ]);
+ await initAreaChart();
+ });
it('should save and load with special characters', async function() {
const vizNamewithSpecialChars = vizName1 + '/?&=%';
@@ -284,6 +292,7 @@ export default function({ getService, getPageObjects }) {
.pop()
.replace('embed=true', '');
await PageObjects.common.navigateToUrl('visualize', embedUrl);
+ await security.testUser.restoreDefaults();
});
});
diff --git a/test/functional/apps/visualize/_experimental_vis.js b/test/functional/apps/visualize/_experimental_vis.js
index 2ce15cf913eff1..c45a95abab86ee 100644
--- a/test/functional/apps/visualize/_experimental_vis.js
+++ b/test/functional/apps/visualize/_experimental_vis.js
@@ -23,7 +23,7 @@ export default ({ getService, getPageObjects }) => {
const log = getService('log');
const PageObjects = getPageObjects(['visualize']);
- describe('visualize app', function() {
+ describe('experimental visualizations in visualize app ', function() {
this.tags('smoke');
describe('experimental visualizations', () => {
diff --git a/test/functional/apps/visualize/_linked_saved_searches.ts b/test/functional/apps/visualize/_linked_saved_searches.ts
index 345987a803394a..ea42f7c6719856 100644
--- a/test/functional/apps/visualize/_linked_saved_searches.ts
+++ b/test/functional/apps/visualize/_linked_saved_searches.ts
@@ -32,7 +32,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
'visChart',
]);
- describe('visualize app', function describeIndexTests() {
+ describe('saved search visualizations from visualize app', function describeIndexTests() {
describe('linked saved searched', () => {
const savedSearchName = 'vis_saved_search';
diff --git a/test/functional/apps/visualize/_markdown_vis.js b/test/functional/apps/visualize/_markdown_vis.js
index fee6c074af5d25..649fe0a8e4c2e1 100644
--- a/test/functional/apps/visualize/_markdown_vis.js
+++ b/test/functional/apps/visualize/_markdown_vis.js
@@ -29,7 +29,7 @@ export default function({ getPageObjects, getService }) {
Inline HTML that should not be rendered as html
`;
- describe('visualize app', () => {
+ describe('markdown app in visualize app', () => {
before(async function() {
await PageObjects.visualize.navigateToNewVisualization();
await PageObjects.visualize.clickMarkdownWidget();
diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts
index 6a4bed3ba5892a..867db66ac81dcd 100644
--- a/test/functional/apps/visualize/_tsvb_chart.ts
+++ b/test/functional/apps/visualize/_tsvb_chart.ts
@@ -25,11 +25,13 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const log = getService('log');
const inspector = getService('inspector');
+ const security = getService('security');
const PageObjects = getPageObjects(['visualize', 'visualBuilder', 'timePicker', 'visChart']);
describe('visual builder', function describeIndexTests() {
this.tags('smoke');
beforeEach(async () => {
+ await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
await PageObjects.visualize.navigateToNewVisualization();
await PageObjects.visualize.clickVisualBuilder();
await PageObjects.visualBuilder.checkVisualBuilderIsPresent();
@@ -111,8 +113,10 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visualBuilder.resetPage();
await PageObjects.visualBuilder.clickMetric();
await PageObjects.visualBuilder.checkMetricTabIsPresent();
+ await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']);
});
after(async () => {
+ await security.testUser.restoreDefaults();
await esArchiver.unload('kibana_sample_data_flights');
});
diff --git a/test/functional/apps/visualize/_vega_chart.js b/test/functional/apps/visualize/_vega_chart.js
index df0603c7f95f51..7a19bde341cdd4 100644
--- a/test/functional/apps/visualize/_vega_chart.js
+++ b/test/functional/apps/visualize/_vega_chart.js
@@ -25,7 +25,7 @@ export default function({ getService, getPageObjects }) {
const inspector = getService('inspector');
const log = getService('log');
- describe('visualize app', () => {
+ describe('vega chart in visualize app', () => {
before(async () => {
log.debug('navigateToApp visualize');
await PageObjects.visualize.navigateToNewVisualization();
diff --git a/test/functional/apps/visualize/input_control_vis/input_control_range.ts b/test/functional/apps/visualize/input_control_vis/input_control_range.ts
index f48ba7b54daf16..8f079f5cc430d9 100644
--- a/test/functional/apps/visualize/input_control_vis/input_control_range.ts
+++ b/test/functional/apps/visualize/input_control_vis/input_control_range.ts
@@ -25,10 +25,12 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const find = getService('find');
+ const security = getService('security');
const { visualize, visEditor } = getPageObjects(['visualize', 'visEditor']);
describe('input control range', () => {
before(async () => {
+ await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']);
await esArchiver.load('kibana_sample_data_flights_index_pattern');
await visualize.navigateToNewVisualization();
await visualize.clickInputControlVis();
@@ -63,6 +65,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
await esArchiver.loadIfNeeded('long_window_logstash');
await esArchiver.load('visualize');
await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' });
+ await security.testUser.restoreDefaults();
});
});
}
diff --git a/test/functional/config.js b/test/functional/config.js
index e84b7e0a98a683..0fbde95afe12c7 100644
--- a/test/functional/config.js
+++ b/test/functional/config.js
@@ -32,6 +32,7 @@ export default async function({ readConfigFile }) {
require.resolve('./apps/discover'),
require.resolve('./apps/home'),
require.resolve('./apps/management'),
+ require.resolve('./apps/saved_objects_management'),
require.resolve('./apps/status_page'),
require.resolve('./apps/timelion'),
require.resolve('./apps/visualize'),
@@ -103,5 +104,172 @@ export default async function({ readConfigFile }) {
browser: {
type: 'chrome',
},
+
+ security: {
+ roles: {
+ test_logstash_reader: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['logstash*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+ test_shakespeare_reader: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['shakes*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+ test_testhuge_reader: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['testhuge*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+ test_alias_reader: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['alias*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+ //for sample data - can remove but not add sample data.( not ml)- for ml use built in role.
+ kibana_sample_admin: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['kibana_sample*'],
+ privileges: ['read', 'view_index_metadata', 'manage', 'create_index', 'index'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ kibana_date_nanos: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['date-nanos'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ kibana_date_nanos_custom: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['date_nanos_custom_timestamp'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ kibana_date_nanos_mixed: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['date_nanos_mixed', 'timestamp-*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ kibana_large_strings: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['testlargestring'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ long_window_logstash: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['long-window-logstash-*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+
+ animals: {
+ elasticsearch: {
+ cluster: [],
+ indices: [
+ {
+ names: ['animals-*'],
+ privileges: ['read', 'view_index_metadata'],
+ field_security: { grant: ['*'], except: [] },
+ },
+ ],
+ run_as: [],
+ },
+ kibana: [],
+ },
+ },
+ defaultRoles: ['test_logstash_reader', 'kibana_admin'],
+ },
};
}
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/data.json b/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/data.json
new file mode 100644
index 00000000000000..f085bad4c507ec
--- /dev/null
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/data.json
@@ -0,0 +1,85 @@
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "type": "doc",
+ "id": "index-pattern:logstash-*",
+ "source": {
+ "index-pattern": {
+ "title": "logstash-*",
+ "timeFieldName": "@timestamp",
+ "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]"
+ },
+ "type": "index-pattern",
+ "migrationVersion": {
+ "index-pattern": "6.5.0"
+ },
+ "updated_at": "2018-12-21T00:43:07.096Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "type": "doc",
+ "id": "visualization:75c3e060-1e7c-11e9-8488-65449e65d0ed",
+ "source": {
+ "visualization": {
+ "title": "A Pie",
+ "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}",
+ "uiStateJSON": "{}",
+ "description": "",
+ "version": 1,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
+ }
+ },
+ "type": "visualization",
+ "updated_at": "2019-01-22T19:32:31.206Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "type": "doc",
+ "id": "dashboard:i-exist",
+ "source": {
+ "dashboard": {
+ "title": "A Dashboard",
+ "hits": 0,
+ "description": "",
+ "panelsJSON": "[{\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"version\":\"7.0.0\",\"panelIndex\":\"1\",\"type\":\"visualization\",\"id\":\"75c3e060-1e7c-11e9-8488-65449e65d0ed\",\"embeddableConfig\":{}}]",
+ "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}",
+ "version": 1,
+ "timeRestore": false,
+ "kibanaSavedObjectMeta": {
+ "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
+ }
+ },
+ "type": "dashboard",
+ "updated_at": "2019-01-22T19:32:47.232Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "index": ".kibana",
+ "type": "doc",
+ "id": "config:6.0.0",
+ "source": {
+ "config": {
+ "buildNum": 9007199254740991,
+ "defaultIndex": "logstash-*"
+ },
+ "type": "config",
+ "updated_at": "2019-01-22T19:32:02.235Z"
+ }
+ }
+}
diff --git a/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/mappings.json b/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/mappings.json
new file mode 100644
index 00000000000000..96e6b7c0a19f14
--- /dev/null
+++ b/test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object/mappings.json
@@ -0,0 +1,459 @@
+{
+ "type": "index",
+ "value": {
+ "index": ".kibana",
+ "settings": {
+ "index": {
+ "number_of_shards": "1",
+ "auto_expand_replicas": "0-1",
+ "number_of_replicas": "0"
+ }
+ },
+ "mappings": {
+ "dynamic": "strict",
+ "properties": {
+ "apm-telemetry": {
+ "properties": {
+ "has_any_services": {
+ "type": "boolean"
+ },
+ "services_per_agent": {
+ "properties": {
+ "go": {
+ "type": "long",
+ "null_value": 0
+ },
+ "java": {
+ "type": "long",
+ "null_value": 0
+ },
+ "js-base": {
+ "type": "long",
+ "null_value": 0
+ },
+ "nodejs": {
+ "type": "long",
+ "null_value": 0
+ },
+ "python": {
+ "type": "long",
+ "null_value": 0
+ },
+ "ruby": {
+ "type": "long",
+ "null_value": 0
+ }
+ }
+ }
+ }
+ },
+ "canvas-workpad": {
+ "dynamic": "false",
+ "properties": {
+ "@created": {
+ "type": "date"
+ },
+ "@timestamp": {
+ "type": "date"
+ },
+ "id": {
+ "type": "text",
+ "index": false
+ },
+ "name": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword"
+ }
+ }
+ }
+ }
+ },
+ "config": {
+ "dynamic": "true",
+ "properties": {
+ "accessibility:disableAnimations": {
+ "type": "boolean"
+ },
+ "buildNum": {
+ "type": "keyword"
+ },
+ "dateFormat:tz": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ },
+ "defaultIndex": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ },
+ "telemetry:optIn": {
+ "type": "boolean"
+ }
+ }
+ },
+ "dashboard": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "optionsJSON": {
+ "type": "text"
+ },
+ "panelsJSON": {
+ "type": "text"
+ },
+ "refreshInterval": {
+ "properties": {
+ "display": {
+ "type": "keyword"
+ },
+ "pause": {
+ "type": "boolean"
+ },
+ "section": {
+ "type": "integer"
+ },
+ "value": {
+ "type": "integer"
+ }
+ }
+ },
+ "timeFrom": {
+ "type": "keyword"
+ },
+ "timeRestore": {
+ "type": "boolean"
+ },
+ "timeTo": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "map": {
+ "properties": {
+ "bounds": {
+ "type": "geo_shape",
+ "tree": "quadtree"
+ },
+ "description": {
+ "type": "text"
+ },
+ "layerListJSON": {
+ "type": "text"
+ },
+ "mapStateJSON": {
+ "type": "text"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "graph-workspace": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "numLinks": {
+ "type": "integer"
+ },
+ "numVertices": {
+ "type": "integer"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "wsState": {
+ "type": "text"
+ }
+ }
+ },
+ "index-pattern": {
+ "properties": {
+ "fieldFormatMap": {
+ "type": "text"
+ },
+ "fields": {
+ "type": "text"
+ },
+ "intervalName": {
+ "type": "keyword"
+ },
+ "notExpandable": {
+ "type": "boolean"
+ },
+ "sourceFilters": {
+ "type": "text"
+ },
+ "timeFieldName": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "type": {
+ "type": "keyword"
+ },
+ "typeMeta": {
+ "type": "keyword"
+ }
+ }
+ },
+ "kql-telemetry": {
+ "properties": {
+ "optInCount": {
+ "type": "long"
+ },
+ "optOutCount": {
+ "type": "long"
+ }
+ }
+ },
+ "migrationVersion": {
+ "dynamic": "true",
+ "properties": {
+ "index-pattern": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ },
+ "space": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 256
+ }
+ }
+ }
+ }
+ },
+ "namespace": {
+ "type": "keyword"
+ },
+ "search": {
+ "properties": {
+ "columns": {
+ "type": "keyword"
+ },
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "sort": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "server": {
+ "properties": {
+ "uuid": {
+ "type": "keyword"
+ }
+ }
+ },
+ "space": {
+ "properties": {
+ "_reserved": {
+ "type": "boolean"
+ },
+ "color": {
+ "type": "keyword"
+ },
+ "description": {
+ "type": "text"
+ },
+ "disabledFeatures": {
+ "type": "keyword"
+ },
+ "initials": {
+ "type": "keyword"
+ },
+ "name": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 2048
+ }
+ }
+ }
+ }
+ },
+ "spaceId": {
+ "type": "keyword"
+ },
+ "telemetry": {
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ }
+ }
+ },
+ "timelion-sheet": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "hits": {
+ "type": "integer"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "timelion_chart_height": {
+ "type": "integer"
+ },
+ "timelion_columns": {
+ "type": "integer"
+ },
+ "timelion_interval": {
+ "type": "keyword"
+ },
+ "timelion_other_interval": {
+ "type": "keyword"
+ },
+ "timelion_rows": {
+ "type": "integer"
+ },
+ "timelion_sheet": {
+ "type": "text"
+ },
+ "title": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "type": {
+ "type": "keyword"
+ },
+ "updated_at": {
+ "type": "date"
+ },
+ "url": {
+ "properties": {
+ "accessCount": {
+ "type": "long"
+ },
+ "accessDate": {
+ "type": "date"
+ },
+ "createDate": {
+ "type": "date"
+ },
+ "url": {
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword",
+ "ignore_above": 2048
+ }
+ }
+ }
+ }
+ },
+ "visualization": {
+ "properties": {
+ "description": {
+ "type": "text"
+ },
+ "kibanaSavedObjectMeta": {
+ "properties": {
+ "searchSourceJSON": {
+ "type": "text"
+ }
+ }
+ },
+ "savedSearchId": {
+ "type": "keyword"
+ },
+ "title": {
+ "type": "text"
+ },
+ "uiStateJSON": {
+ "type": "text"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "visState": {
+ "type": "text"
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts
index 60966511c1f99e..6895034f22ed54 100644
--- a/test/functional/page_objects/common_page.ts
+++ b/test/functional/page_objects/common_page.ts
@@ -105,13 +105,16 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
const wantedLoginPage = appUrl.includes('/login') || appUrl.includes('/logout');
if (loginPage && !wantedLoginPage) {
- log.debug(
- `Found login page. Logging in with username = ${config.get('servers.kibana.username')}`
- );
- await PageObjects.shield.login(
- config.get('servers.kibana.username'),
- config.get('servers.kibana.password')
- );
+ log.debug('Found login page');
+ if (config.get('security.disableTestUser')) {
+ await PageObjects.shield.login(
+ config.get('servers.kibana.username'),
+ config.get('servers.kibana.password')
+ );
+ } else {
+ await PageObjects.shield.login('test_user', 'changeme');
+ }
+
await find.byCssSelector(
'[data-test-subj="kibanaChrome"] nav:not(.ng-hide)',
6 * defaultFindTimeout
@@ -511,6 +514,12 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
}
});
}
+
+ async setFileInputPath(path: string) {
+ log.debug(`Setting the path '${path}' on the file input`);
+ const input = await find.byCssSelector('.euiFilePicker__input');
+ await input.type(path);
+ }
}
return new CommonPage();
diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts
index c244deba5f17ea..0ad1a1dc513213 100644
--- a/test/functional/page_objects/settings_page.ts
+++ b/test/functional/page_objects/settings_page.ts
@@ -612,9 +612,7 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider
log.debug(`Clicking importObjects`);
await testSubjects.click('importObjects');
- log.debug(`Setting the path on the file input`);
- const input = await find.byCssSelector('.euiFilePicker__input');
- await input.type(path);
+ await PageObjects.common.setFileInputPath(path);
if (!overwriteAll) {
log.debug(`Toggling overwriteAll`);
diff --git a/test/functional/screenshots/baseline/area_chart.png b/test/functional/screenshots/baseline/area_chart.png
index 2c2d599139100d..1a381d61dd9f18 100644
Binary files a/test/functional/screenshots/baseline/area_chart.png and b/test/functional/screenshots/baseline/area_chart.png differ
diff --git a/test/functional/screenshots/baseline/tsvb_dashboard.png b/test/functional/screenshots/baseline/tsvb_dashboard.png
index d703be89b7460c..f5ebccbcb96c6b 100644
Binary files a/test/functional/screenshots/baseline/tsvb_dashboard.png and b/test/functional/screenshots/baseline/tsvb_dashboard.png differ
diff --git a/test/functional/services/browser.ts b/test/functional/services/browser.ts
index 02349b4e6cca2c..5017947e95d03b 100644
--- a/test/functional/services/browser.ts
+++ b/test/functional/services/browser.ts
@@ -21,6 +21,7 @@ import { cloneDeep } from 'lodash';
import { Key, Origin } from 'selenium-webdriver';
// @ts-ignore internal modules are not typed
import { LegacyActionSequence } from 'selenium-webdriver/lib/actions';
+import { ProvidedType } from '@kbn/test/types/ftr';
import Jimp from 'jimp';
import { modifyUrl } from '../../../src/core/utils';
@@ -28,6 +29,7 @@ import { WebElementWrapper } from './lib/web_element_wrapper';
import { FtrProviderContext } from '../ftr_provider_context';
import { Browsers } from './remote/browsers';
+export type Browser = ProvidedType;
export async function BrowserProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const { driver, browserType } = await getService('__webdriver__').init();
diff --git a/test/functional/services/test_subjects.ts b/test/functional/services/test_subjects.ts
index d47b838c8d72a5..e5c2e61c48a0b4 100644
--- a/test/functional/services/test_subjects.ts
+++ b/test/functional/services/test_subjects.ts
@@ -19,6 +19,7 @@
import testSubjSelector from '@kbn/test-subj-selector';
import { map as mapAsync } from 'bluebird';
+import { ProvidedType } from '@kbn/test/types/ftr';
import { WebElementWrapper } from './lib/web_element_wrapper';
import { FtrProviderContext } from '../ftr_provider_context';
@@ -32,6 +33,7 @@ interface SetValueOptions {
typeCharByChar?: boolean;
}
+export type TestSubjects = ProvidedType;
export function TestSubjectsProvider({ getService }: FtrProviderContext) {
const log = getService('log');
const retry = getService('retry');
diff --git a/test/plugin_functional/plugins/rendering_plugin/server/plugin.ts b/test/plugin_functional/plugins/rendering_plugin/server/plugin.ts
index fad19728b75143..3f6a8e8773e04d 100644
--- a/test/plugin_functional/plugins/rendering_plugin/server/plugin.ts
+++ b/test/plugin_functional/plugins/rendering_plugin/server/plugin.ts
@@ -33,7 +33,7 @@ export class RenderingPlugin implements Plugin {
{
includeUserSettings: schema.boolean({ defaultValue: true }),
},
- { allowUnknowns: true }
+ { unknowns: 'allow' }
),
params: schema.object({
id: schema.maybe(schema.string()),
diff --git a/test/scripts/jenkins_xpack_build_kibana.sh b/test/scripts/jenkins_xpack_build_kibana.sh
index f87d6e1102c45e..2bf9d2d9c158b5 100755
--- a/test/scripts/jenkins_xpack_build_kibana.sh
+++ b/test/scripts/jenkins_xpack_build_kibana.sh
@@ -6,6 +6,7 @@ source src/dev/ci_setup/setup_env.sh
echo " -> building kibana platform plugins"
node scripts/build_kibana_platform_plugins \
--scan-dir "$XPACK_DIR/test/plugin_functional/plugins" \
+ --scan-dir "$XPACK_DIR/test/functional_with_es_ssl/fixtures/plugins" \
--verbose;
# doesn't persist, also set in kibanaPipeline.groovy
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 60a8d1fcbf2295..1564eb94a69039 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -22,7 +22,7 @@
"xpack.infra": "plugins/infra",
"xpack.ingestManager": "plugins/ingest_manager",
"xpack.lens": "legacy/plugins/lens",
- "xpack.licenseMgmt": "legacy/plugins/license_management",
+ "xpack.licenseMgmt": "plugins/license_management",
"xpack.licensing": "plugins/licensing",
"xpack.logstash": "legacy/plugins/logstash",
"xpack.main": "legacy/plugins/xpack_main",
diff --git a/x-pack/index.js b/x-pack/index.js
index ab31d40c5d7183..fb14b3dc10a4db 100644
--- a/x-pack/index.js
+++ b/x-pack/index.js
@@ -16,7 +16,6 @@ import { logstash } from './legacy/plugins/logstash';
import { beats } from './legacy/plugins/beats_management';
import { apm } from './legacy/plugins/apm';
import { maps } from './legacy/plugins/maps';
-import { licenseManagement } from './legacy/plugins/license_management';
import { indexManagement } from './legacy/plugins/index_management';
import { indexLifecycleManagement } from './legacy/plugins/index_lifecycle_management';
import { spaces } from './legacy/plugins/spaces';
@@ -52,7 +51,6 @@ module.exports = function(kibana) {
apm(kibana),
maps(kibana),
canvas(kibana),
- licenseManagement(kibana),
indexManagement(kibana),
indexLifecycleManagement(kibana),
infra(kibana),
diff --git a/x-pack/legacy/plugins/actions/server/mappings.json b/x-pack/legacy/plugins/actions/server/mappings.json
index a9c4d80b00af10..ef6a0c9919920f 100644
--- a/x-pack/legacy/plugins/actions/server/mappings.json
+++ b/x-pack/legacy/plugins/actions/server/mappings.json
@@ -2,7 +2,12 @@
"action": {
"properties": {
"name": {
- "type": "text"
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword"
+ }
+ }
},
"actionTypeId": {
"type": "keyword"
diff --git a/x-pack/legacy/plugins/alerting/server/mappings.json b/x-pack/legacy/plugins/alerting/server/mappings.json
index 31733f44e7ce6e..a7e85febf2446b 100644
--- a/x-pack/legacy/plugins/alerting/server/mappings.json
+++ b/x-pack/legacy/plugins/alerting/server/mappings.json
@@ -5,7 +5,12 @@
"type": "boolean"
},
"name": {
- "type": "text"
+ "type": "text",
+ "fields": {
+ "keyword": {
+ "type": "keyword"
+ }
+ }
},
"tags": {
"type": "keyword"
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/view.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/view.tsx
index 31fc4db8f1a2f0..cff190cd98a11a 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/view.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/view.tsx
@@ -209,7 +209,7 @@ export function MachineLearningFlyoutView({
{i18n.translate(
'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.createNewJobButtonLabel',
{
- defaultMessage: 'Create new job'
+ defaultMessage: 'Create job'
}
)}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx
index 6f7b743d8b7795..b18f462b541710 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx
@@ -13,7 +13,7 @@ import { getCytoscapeElements } from './get_cytoscape_elements';
import serviceMapResponse from './cytoscape-layout-test-response.json';
import { iconForNode } from './icons';
-const elementsFromResponses = getCytoscapeElements([serviceMapResponse], '');
+const elementsFromResponses = getCytoscapeElements(serviceMapResponse, '');
storiesOf('app/ServiceMap/Cytoscape', module).add(
'example',
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.test.tsx
new file mode 100644
index 00000000000000..d61dea80666a00
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.test.tsx
@@ -0,0 +1,62 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 { act, render, wait } from '@testing-library/react';
+import cytoscape from 'cytoscape';
+import React, { FunctionComponent } from 'react';
+import { MockApmPluginContextWrapper } from '../../../utils/testHelpers';
+import { CytoscapeContext } from './Cytoscape';
+import { EmptyBanner } from './EmptyBanner';
+
+const cy = cytoscape({});
+
+const wrapper: FunctionComponent = ({ children }) => (
+
+ {children}
+
+);
+
+describe('EmptyBanner', () => {
+ describe('when cy is undefined', () => {
+ it('renders null', () => {
+ const noCytoscapeWrapper: FunctionComponent = ({ children }) => (
+
+
+ {children}
+
+
+ );
+ const component = render( , {
+ wrapper: noCytoscapeWrapper
+ });
+
+ expect(component.container.children).toHaveLength(0);
+ });
+ });
+
+ describe('with no nodes', () => {
+ it('renders null', () => {
+ const component = render( , {
+ wrapper
+ });
+
+ expect(component.container.children).toHaveLength(0);
+ });
+ });
+
+ describe('with one node', () => {
+ it('does not render null', async () => {
+ const component = render( , { wrapper });
+
+ await act(async () => {
+ cy.add({ data: { id: 'test id' } });
+ await wait(() => {
+ expect(component.container.children.length).toBeGreaterThan(0);
+ });
+ });
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx
index 418430e37b21e6..464bf166eb80f5 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx
@@ -7,37 +7,70 @@
import { EuiCallOut } from '@elastic/eui';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
-import React from 'react';
+import React, { useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
+import { CytoscapeContext } from './Cytoscape';
-const EmptyBannerCallOut = styled(EuiCallOut)`
+const EmptyBannerContainer = styled.div`
margin: ${lightTheme.gutterTypes.gutterSmall};
/* Add some extra margin so it displays to the right of the controls. */
- margin-left: calc(
- ${lightTheme.gutterTypes.gutterLarge} +
- ${lightTheme.gutterTypes.gutterExtraLarge}
+ left: calc(
+ ${lightTheme.gutterTypes.gutterExtraLarge} +
+ ${lightTheme.gutterTypes.gutterSmall}
);
position: absolute;
z-index: 1;
`;
export function EmptyBanner() {
+ const cy = useContext(CytoscapeContext);
+ const [nodeCount, setNodeCount] = useState(0);
+
+ useEffect(() => {
+ const handler: cytoscape.EventHandler = event =>
+ setNodeCount(event.cy.nodes().length);
+
+ if (cy) {
+ cy.on('add remove', 'node', handler);
+ }
+
+ return () => {
+ if (cy) {
+ cy.removeListener('add remove', 'node', handler);
+ }
+ };
+ }, [cy]);
+
+ // Only show if there's a single node.
+ if (!cy || nodeCount !== 1) {
+ return null;
+ }
+
+ // Since we're absolutely positioned, we need to get the full width and
+ // subtract the space for controls and margins.
+ const width =
+ cy.width() -
+ parseInt(lightTheme.gutterTypes.gutterExtraLarge, 10) -
+ parseInt(lightTheme.gutterTypes.gutterLarge, 10);
+
return (
-
- {i18n.translate('xpack.apm.serviceMap.emptyBanner.message', {
- defaultMessage:
- "We will map out connected services and external requests if we can detect them. Please make sure you're running the latest version of the APM agent."
- })}{' '}
-
- {i18n.translate('xpack.apm.serviceMap.emptyBanner.docsLink', {
- defaultMessage: 'Learn more in the docs'
+
+
-
+ >
+ {i18n.translate('xpack.apm.serviceMap.emptyBanner.message', {
+ defaultMessage:
+ "We will map out connected services and external requests if we can detect them. Please make sure you're running the latest version of the APM agent."
+ })}{' '}
+
+ {i18n.translate('xpack.apm.serviceMap.emptyBanner.docsLink', {
+ defaultMessage: 'Learn more in the docs'
+ })}
+
+
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx
index 9213349a1492bf..77f0b64ba0fb10 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.tsx
@@ -6,10 +6,12 @@
import {
EuiButton,
- EuiEmptyPrompt,
+ EuiPanel,
EuiFlexGroup,
EuiFlexItem,
- EuiPanel
+ EuiTitle,
+ EuiText,
+ EuiSpacer
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
@@ -18,7 +20,8 @@ import { useKibanaUrl } from '../../../hooks/useKibanaUrl';
export function PlatinumLicensePrompt() {
// Set the height to give it some top margin
- const style = { height: '60vh' };
+ const flexGroupStyle = { height: '60vh' };
+ const flexItemStyle = { width: 600, textAlign: 'center' as const };
const licensePageUrl = useKibanaUrl(
'/app/kibana',
@@ -29,30 +32,41 @@ export function PlatinumLicensePrompt() {
-
-
-
- {i18n.translate(
- 'xpack.apm.serviceMap.licensePromptButtonText',
- {
- defaultMessage: 'Start 30-day Platinum trial'
- }
- )}
-
- ]}
- body={{invalidLicenseMessage}
}
- title={
+
+
+
+
+
{i18n.translate('xpack.apm.serviceMap.licensePromptTitle', {
defaultMessage: 'Service maps is available in Platinum.'
})}
- }
- />
+
+
+
+ {invalidLicenseMessage}
+
+
+
+ {i18n.translate('xpack.apm.serviceMap.licensePromptButtonText', {
+ defaultMessage: 'Start 30-day Platinum trial'
+ })}
+
+
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts
index 9ba70646598fc1..4017aa2e3cdd90 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts
@@ -4,166 +4,63 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { ValuesType } from 'utility-types';
-import { sortBy, isEqual } from 'lodash';
-import {
- Connection,
- ConnectionNode
-} from '../../../../../../../plugins/apm/common/service_map';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ServiceMapAPIResponse } from '../../../../../../../plugins/apm/server/lib/service_map/get_service_map';
import { getAPMHref } from '../../shared/Links/apm/APMLink';
-function getConnectionNodeId(node: ConnectionNode): string {
- if ('destination.address' in node) {
- // use a prefix to distinguish exernal destination ids from services
- return `>${node['destination.address']}`;
- }
- return node['service.name'];
-}
-
-function getConnectionId(connection: Connection) {
- return `${getConnectionNodeId(connection.source)}~${getConnectionNodeId(
- connection.destination
- )}`;
-}
export function getCytoscapeElements(
- responses: ServiceMapAPIResponse[],
+ response: ServiceMapAPIResponse,
search: string
) {
- const discoveredServices = responses.flatMap(
- response => response.discoveredServices
- );
-
- const serviceNodes = responses
- .flatMap(response => response.services)
- .map(service => ({
- ...service,
- id: service['service.name']
- }));
-
- // maps destination.address to service.name if possible
- function getConnectionNode(node: ConnectionNode) {
- let mappedNode: ConnectionNode | undefined;
-
- if ('destination.address' in node) {
- mappedNode = discoveredServices.find(map => isEqual(map.from, node))?.to;
- }
-
- if (!mappedNode) {
- mappedNode = node;
- }
-
- return {
- ...mappedNode,
- id: getConnectionNodeId(mappedNode)
- };
- }
-
- // build connections with mapped nodes
- const connections = responses
- .flatMap(response => response.connections)
- .map(connection => {
- const source = getConnectionNode(connection.source);
- const destination = getConnectionNode(connection.destination);
-
- return {
- source,
- destination,
- id: getConnectionId({ source, destination })
- };
- })
- .filter(connection => connection.source.id !== connection.destination.id);
-
- const nodes = connections
- .flatMap(connection => [connection.source, connection.destination])
- .concat(serviceNodes);
-
- type ConnectionWithId = ValuesType;
- type ConnectionNodeWithId = ValuesType;
-
- const connectionsById = connections.reduce((connectionMap, connection) => {
- return {
- ...connectionMap,
- [connection.id]: connection
- };
- }, {} as Record);
+ const { nodes, connections } = response;
const nodesById = nodes.reduce((nodeMap, node) => {
return {
...nodeMap,
[node.id]: node
};
- }, {} as Record);
-
- const cyNodes = (Object.values(nodesById) as ConnectionNodeWithId[]).map(
- node => {
- let data = {};
-
- if ('service.name' in node) {
- data = {
- href: getAPMHref(
- `/services/${node['service.name']}/service-map`,
- search
- ),
- agentName: node['agent.name'],
- frameworkName: node['service.framework.name'],
- type: 'service'
- };
- }
-
- if ('span.type' in node) {
- data = {
- // For nodes with span.type "db", convert it to "database". Otherwise leave it as-is.
- type: node['span.type'] === 'db' ? 'database' : node['span.type'],
- // Externals should not have a subtype so make it undefined if the type is external.
- subtype: node['span.type'] !== 'external' && node['span.subtype']
- };
- }
-
- return {
- group: 'nodes' as const,
- data: {
- id: node.id,
- label:
- 'service.name' in node
- ? node['service.name']
- : node['destination.address'],
- ...data
- }
+ }, {} as Record>);
+
+ const cyNodes = (Object.values(nodesById) as Array<
+ ValuesType
+ >).map(node => {
+ let data = {};
+
+ if ('service.name' in node) {
+ data = {
+ href: getAPMHref(
+ `/services/${node['service.name']}/service-map`,
+ search
+ ),
+ agentName: node['agent.name'],
+ frameworkName: node['service.framework.name'],
+ type: 'service'
};
}
- );
-
- // instead of adding connections in two directions,
- // we add a `bidirectional` flag to use in styling
- // and hide the inverse edge when rendering
- const dedupedConnections = (sortBy(
- Object.values(connectionsById),
- // make sure that order is stable
- 'id'
- ) as ConnectionWithId[]).reduce<
- Array<
- ConnectionWithId & { bidirectional?: boolean; isInverseEdge?: boolean }
- >
- >((prev, connection) => {
- const reversedConnection = prev.find(
- c =>
- c.destination.id === connection.source.id &&
- c.source.id === connection.destination.id
- );
- if (reversedConnection) {
- reversedConnection.bidirectional = true;
- return prev.concat({
- ...connection,
- isInverseEdge: true
- });
+ if ('span.type' in node) {
+ data = {
+ // For nodes with span.type "db", convert it to "database". Otherwise leave it as-is.
+ type: node['span.type'] === 'db' ? 'database' : node['span.type'],
+ // Externals should not have a subtype so make it undefined if the type is external.
+ subtype: node['span.type'] !== 'external' && node['span.subtype']
+ };
}
- return prev.concat(connection);
- }, []);
+ return {
+ group: 'nodes' as const,
+ data: {
+ id: node.id,
+ label:
+ 'service.name' in node
+ ? node['service.name']
+ : node['destination.address'],
+ ...data
+ }
+ };
+ });
- const cyEdges = dedupedConnections.map(connection => {
+ const cyEdges = connections.map(connection => {
return {
group: 'edges' as const,
classes: connection.isInverseEdge ? 'invisible' : undefined,
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons/dot-net.svg b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons/dot-net.svg
index 9f7427f0e10017..da7f1a8fde45da 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons/dot-net.svg
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons/dot-net.svg
@@ -1,127 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
index 2942ce64729e7d..6222a00a9e8885 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/index.tsx
@@ -4,26 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiButton } from '@elastic/eui';
+import { EuiBetaBadge } from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
-import { ElementDefinition } from 'cytoscape';
-import { find, isEqual } from 'lodash';
-import React, {
- useCallback,
- useEffect,
- useMemo,
- useRef,
- useState
-} from 'react';
-import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public';
+import React, { useMemo } from 'react';
+import styled from 'styled-components';
import { isValidPlatinumLicense } from '../../../../../../../plugins/apm/common/service_map';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { ServiceMapAPIResponse } from '../../../../../../../plugins/apm/server/lib/service_map/get_service_map';
-import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { useDeepObjectIdentity } from '../../../hooks/useDeepObjectIdentity';
+import { useFetcher } from '../../../hooks/useFetcher';
import { useLicense } from '../../../hooks/useLicense';
-import { useLoadingIndicator } from '../../../hooks/useLoadingIndicator';
import { useLocation } from '../../../hooks/useLocation';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { callApmApi } from '../../../services/rest/createCallApmApi';
@@ -58,14 +47,17 @@ ${theme.euiColorLightShade}`,
margin: `-${theme.gutterTypes.gutterLarge}`,
marginTop: 0
};
-
-const MAX_REQUESTS = 5;
+const BetaBadgeContainer = styled.div`
+ right: ${theme.gutterTypes.gutterMedium};
+ position: absolute;
+ top: ${theme.gutterTypes.gutterSmall};
+ z-index: 1; /* The element containing the cytoscape canvas has z-index = 0. */
+`;
export function ServiceMap({ serviceName }: ServiceMapProps) {
const license = useLicense();
const { search } = useLocation();
const { urlParams, uiFilters } = useUrlParams();
- const { notifications } = useApmPluginContext().core;
const params = useDeepObjectIdentity({
start: urlParams.start,
end: urlParams.end,
@@ -77,126 +69,28 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
}
});
- const renderedElements = useRef([]);
- const openToast = useRef(null);
-
- const [responses, setResponses] = useState([]);
-
- const { setIsLoading } = useLoadingIndicator();
-
- const [, _setUnusedState] = useState(false);
-
- const elements = useMemo(() => getCytoscapeElements(responses, search), [
- responses,
- search
- ]);
-
- const forceUpdate = useCallback(() => _setUnusedState(value => !value), []);
-
- const getNext = useCallback(
- async (input: { reset?: boolean; after?: string | undefined }) => {
- const { start, end, uiFilters: strippedUiFilters, ...query } = params;
-
- if (input.reset) {
- renderedElements.current = [];
- setResponses([]);
- }
-
- if (start && end) {
- setIsLoading(true);
- try {
- const data = await callApmApi({
- pathname: '/api/apm/service-map',
- params: {
- query: {
- ...query,
- start,
- end,
- uiFilters: JSON.stringify(strippedUiFilters),
- after: input.after
- }
- }
- });
- setResponses(resp => resp.concat(data));
-
- const shouldGetNext =
- responses.length + 1 < MAX_REQUESTS && data.after;
-
- if (shouldGetNext) {
- await getNext({ after: data.after });
- } else {
- setIsLoading(false);
+ const { data } = useFetcher(() => {
+ const { start, end } = params;
+ if (start && end) {
+ return callApmApi({
+ pathname: '/api/apm/service-map',
+ params: {
+ query: {
+ ...params,
+ start,
+ end,
+ uiFilters: JSON.stringify(params.uiFilters)
}
- } catch (error) {
- setIsLoading(false);
- notifications.toasts.addError(error, {
- title: i18n.translate('xpack.apm.errorServiceMapData', {
- defaultMessage: `Error loading service connections`
- })
- });
}
- }
- },
- [params, setIsLoading, responses.length, notifications.toasts]
- );
-
- useEffect(() => {
- const loadServiceMaps = async () => {
- await getNext({ reset: true });
- };
-
- loadServiceMaps();
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [params]);
-
- useEffect(() => {
- if (renderedElements.current.length === 0) {
- renderedElements.current = elements;
- return;
+ });
}
+ }, [params]);
- const newElements = elements.filter(element => {
- return !find(renderedElements.current, el => isEqual(el, element));
- });
-
- const updateMap = () => {
- renderedElements.current = elements;
- if (openToast.current) {
- notifications.toasts.remove(openToast.current);
- }
- forceUpdate();
- };
-
- if (newElements.length > 0 && renderedElements.current.length > 0) {
- openToast.current = notifications.toasts.add({
- title: i18n.translate('xpack.apm.newServiceMapData', {
- defaultMessage: `Newly discovered connections are available.`
- }),
- onClose: () => {
- openToast.current = null;
- },
- toastLifeTimeMs: 24 * 60 * 60 * 1000,
- text: toMountPoint(
-
- {i18n.translate('xpack.apm.updateServiceMap', {
- defaultMessage: 'Update map'
- })}
-
- )
- }).id;
- }
-
- return () => {
- if (openToast.current) {
- notifications.toasts.remove(openToast.current);
- }
- };
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [elements]);
+ const elements = useMemo(() => {
+ return data ? getCytoscapeElements(data as any, search) : [];
+ }, [data, search]);
- const { ref: wrapperRef, width, height } = useRefDimensions();
+ const { ref, height, width } = useRefDimensions();
if (!license) {
return null;
@@ -205,20 +99,32 @@ export function ServiceMap({ serviceName }: ServiceMapProps) {
return isValidPlatinumLicense(license) ? (
- {serviceName && renderedElements.current.length === 1 && (
-
- )}
+ {serviceName && }
+
+
+
) : (
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js
index 193d99e1c95339..faadfd4bb26d7a 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js
@@ -21,6 +21,6 @@ export const demodata = () => ({
name: 'demodata',
displayName: strings.getDisplayName(),
help: strings.getHelp(),
- image: 'logoElasticStack',
+ image: 'training',
template: templateFromReactComponent(DemodataDatasource),
});
diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/datasources/esdocs.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js
similarity index 58%
rename from x-pack/legacy/plugins/canvas/public/expression_types/datasources/esdocs.js
rename to x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js
index eacb7e891b4824..282ec17e94c9b5 100644
--- a/x-pack/legacy/plugins/canvas/public/expression_types/datasources/esdocs.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js
@@ -6,15 +6,24 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { EuiFormRow, EuiSelect, EuiTextArea, EuiCallOut, EuiSpacer } from '@elastic/eui';
-import { getSimpleArg, setSimpleArg } from '../../lib/arg_helpers';
-import { ESFieldsSelect } from '../../components/es_fields_select';
-import { ESFieldSelect } from '../../components/es_field_select';
-import { ESIndexSelect } from '../../components/es_index_select';
-import { templateFromReactComponent } from '../../lib/template_from_react_component';
-import { ExpressionDataSourceStrings } from '../../../i18n';
-
-const { ESDocs: strings } = ExpressionDataSourceStrings;
+import {
+ EuiFormRow,
+ EuiAccordion,
+ EuiSelect,
+ EuiTextArea,
+ EuiCallOut,
+ EuiSpacer,
+ EuiLink,
+ EuiText,
+} from '@elastic/eui';
+import { getSimpleArg, setSimpleArg } from '../../../public/lib/arg_helpers';
+import { ESFieldsSelect } from '../../../public/components/es_fields_select';
+import { ESFieldSelect } from '../../../public/components/es_field_select';
+import { ESIndexSelect } from '../../../public/components/es_index_select';
+import { templateFromReactComponent } from '../../../public/lib/template_from_react_component';
+import { DataSourceStrings, LUCENE_QUERY_URL } from '../../../i18n';
+
+const { ESDocs: strings } = DataSourceStrings;
const EsdocsDatasource = ({ args, updateArgs, defaultIndex }) => {
const setArg = (name, value) => {
@@ -74,12 +83,6 @@ const EsdocsDatasource = ({ args, updateArgs, defaultIndex }) => {
return (
-
- {strings.getWarning()}
-
-
-
-
{
setArg('index', index)} />
-
- setArg(getArgName(), e.target.value)}
- compressed
- />
-
-
{
/>
-
+
- setArg('sort', [field, sortOrder].join(', '))}
- />
-
+
+
+ setArg('sort', [field, sortOrder].join(', '))}
+ />
+
+
+
+ setArg('sort', [sortField, e.target.value].join(', '))}
+ options={sortOptions}
+ compressed
+ />
+
+
+
+
+ {strings.getQueryLabel()}
+
+
+ }
+ display="rowCompressed"
+ >
+ setArg(getArgName(), e.target.value)}
+ compressed
+ />
+
+
-
- setArg('sort', [sortField, e.target.value].join(', '))}
- options={sortOptions}
- compressed
- />
-
+
+
+
+ {strings.getWarning()}
+
);
};
@@ -150,6 +165,6 @@ export const esdocs = () => ({
name: 'esdocs',
displayName: strings.getDisplayName(),
help: strings.getHelp(),
- image: 'logoElasticsearch',
+ image: 'documents',
template: templateFromReactComponent(EsdocsDatasource),
});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js
index 707f2305e1368f..44e335dd7b41fc 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js
@@ -95,7 +95,6 @@ export const essql = () => ({
name: 'essql',
displayName: strings.getDisplayName(),
help: strings.getHelp(),
- // Replace this with a SQL logo when we have one in EUI
- image: 'logoElasticsearch',
+ image: 'database',
template: templateFromReactComponent(EssqlDatasource),
});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js
index 13aa2a06306a08..5bddf1d3f4b6b9 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js
@@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { demodata } from './demodata';
import { essql } from './essql';
+import { esdocs } from './esdocs';
+import { demodata } from './demodata';
import { timelion } from './timelion';
-export const datasourceSpecs = [demodata, essql, timelion];
+export const datasourceSpecs = [essql, esdocs, demodata, timelion];
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js
index b30e43c1c3c574..b36f1a747f1203 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js
@@ -13,12 +13,13 @@ import {
EuiSpacer,
EuiCode,
EuiTextArea,
+ EuiText,
+ EuiLink,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { getSimpleArg, setSimpleArg } from '../../../public/lib/arg_helpers';
import { templateFromReactComponent } from '../../../public/lib/template_from_react_component';
-import { DataSourceStrings, TIMELION, CANVAS } from '../../../i18n';
-import { TooltipIcon } from '../../../public/components/tooltip_icon';
+import { DataSourceStrings, TIMELION_QUERY_URL, TIMELION, CANVAS } from '../../../i18n';
const { Timelion: strings } = DataSourceStrings;
@@ -86,8 +87,14 @@ const TimelionDatasource = ({ args, updateArgs, defaultIndex }) => {
}
+ labelAppend={
+
+
+ {strings.queryLabel()}
+
+
+ }
+ display="rowCompressed"
>
{
rows={15}
/>
+
{
// TODO: Time timelion interval picker should be a drop down
}
@@ -124,6 +132,6 @@ export const timelion = () => ({
name: 'timelion',
displayName: TIMELION,
help: strings.getHelp(),
- image: 'timelionApp',
+ image: 'visTimelion',
template: templateFromReactComponent(TimelionDatasource),
});
diff --git a/x-pack/legacy/plugins/canvas/i18n/constants.ts b/x-pack/legacy/plugins/canvas/i18n/constants.ts
index 4cb05b0426fa11..099effc697fc56 100644
--- a/x-pack/legacy/plugins/canvas/i18n/constants.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/constants.ts
@@ -25,6 +25,7 @@ export const JS = 'JavaScript';
export const JSON = 'JSON';
export const KIBANA = 'Kibana';
export const LUCENE = 'Lucene';
+export const LUCENE_QUERY_URL = 'https://www.elastic.co/guide/en/kibana/current/lucene-query.html';
export const MARKDOWN = 'Markdown';
export const MOMENTJS = 'MomentJS';
export const MOMENTJS_TIMEZONE_URL = 'https://momentjs.com/timezone/';
@@ -37,6 +38,7 @@ export const SQL_URL =
'https://www.elastic.co/guide/en/elasticsearch/reference/current/sql-spec.html';
export const SVG = 'SVG';
export const TIMELION = 'Timelion';
+export const TIMELION_QUERY_URL = 'https://www.elastic.co/blog/timelion-tutorial-from-zero-to-hero';
export const TINYMATH = '`TinyMath`';
export const TINYMATH_URL =
'https://www.elastic.co/guide/en/kibana/current/canvas-tinymath-functions.html';
diff --git a/x-pack/legacy/plugins/canvas/i18n/expression_types.ts b/x-pack/legacy/plugins/canvas/i18n/expression_types.ts
index bdd190f26c97aa..5d3a3cd742bb4f 100644
--- a/x-pack/legacy/plugins/canvas/i18n/expression_types.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/expression_types.ts
@@ -5,7 +5,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { LUCENE, ELASTICSEARCH } from './constants';
export const ArgTypesStrings = {
Color: {
@@ -143,86 +142,3 @@ export const ArgTypesStrings = {
}),
},
};
-
-export const ExpressionDataSourceStrings = {
- ESDocs: {
- getDisplayName: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocsTitle', {
- defaultMessage: 'Elasticsearch raw documents',
- }),
- getHelp: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocsLabel', {
- defaultMessage: 'Pull back raw documents from elasticsearch',
- }),
- getWarningTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.warningTitle', {
- defaultMessage: 'Query with caution',
- }),
- getWarning: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.warningDescription', {
- defaultMessage: `
- This datasource pulls directly from {elasticsearch}
- without the use of aggregations. It is best used with low volume datasets and in
- situations where you need to view raw documents or plot exact, non-aggregated values on a
- chart.`,
- values: {
- elasticsearch: ELASTICSEARCH,
- },
- }),
- getIndexTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.indexTitle', {
- defaultMessage: 'Index',
- }),
- getIndexLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.indexLabel', {
- defaultMessage: 'Enter an index name or select an index pattern',
- }),
- getQueryTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.queryTitle', {
- defaultMessage: 'Query',
- }),
- getQueryLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.queryLabel', {
- defaultMessage: '{lucene} query string syntax',
- values: {
- lucene: LUCENE,
- },
- }),
- getSortFieldTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.sortFieldTitle', {
- defaultMessage: 'Sort Field',
- }),
- getSortFieldLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.sortFieldLabel', {
- defaultMessage: 'Document sort field',
- }),
- getSortOrderTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.sortOrderTitle', {
- defaultMessage: 'Sort Order',
- }),
- getSortOrderLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.sortOrderLabel', {
- defaultMessage: 'Document sort order',
- }),
- getFieldsTitle: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.fieldsTitle', {
- defaultMessage: 'Fields',
- }),
- getFieldsLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.fieldsLabel', {
- defaultMessage: 'The fields to extract. Kibana scripted fields are not currently available',
- }),
- getFieldsWarningLabel: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.fieldsWarningLabel', {
- defaultMessage: 'This datasource performs best with 10 or fewer fields',
- }),
- getAscendingOption: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.ascendingDropDown', {
- defaultMessage: 'Ascending',
- }),
- getDescendingOption: () =>
- i18n.translate('xpack.canvas.expressionTypes.datasources.esdocs.descendingDropDown', {
- defaultMessage: 'Descending',
- }),
- },
-};
diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts b/x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts
index 20c7a88ea4f4d5..caedbfdec5be4c 100644
--- a/x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts
@@ -13,7 +13,7 @@ import { DemoRows } from '../../../canvas_plugin_src/functions/server/demodata/g
export const help: FunctionHelp> = {
help: i18n.translate('xpack.canvas.functions.demodataHelpText', {
defaultMessage:
- 'A mock data set that includes project {ci} times with usernames, countries, and run phases.',
+ 'A sample data set that includes project {ci} times with usernames, countries, and run phases.',
values: {
ci: 'CI',
},
diff --git a/x-pack/legacy/plugins/canvas/i18n/ui.ts b/x-pack/legacy/plugins/canvas/i18n/ui.ts
index 5b94cb0435b31f..1abe56c99dc89e 100644
--- a/x-pack/legacy/plugins/canvas/i18n/ui.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/ui.ts
@@ -308,6 +308,7 @@ export const ArgumentStrings = {
};
export const DataSourceStrings = {
+ // Demo data source
DemoData: {
getDisplayName: () =>
i18n.translate('xpack.canvas.uis.dataSources.demoDataTitle', {
@@ -319,7 +320,7 @@ export const DataSourceStrings = {
}),
getHelp: () =>
i18n.translate('xpack.canvas.uis.dataSources.demoDataLabel', {
- defaultMessage: 'Mock data set with usernames, prices, projects, countries, and phases',
+ defaultMessage: 'Sample data set used to populate default elements',
}),
getDescription: () =>
i18n.translate('xpack.canvas.uis.dataSources.demoDataDescription', {
@@ -330,6 +331,88 @@ export const DataSourceStrings = {
},
}),
},
+ // Elasticsearch documents datasource
+ ESDocs: {
+ getDisplayName: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocsTitle', {
+ defaultMessage: '{elasticsearch} documents',
+ values: {
+ elasticsearch: ELASTICSEARCH,
+ },
+ }),
+ getHelp: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocsLabel', {
+ defaultMessage: 'Pull data directly from {elasticsearch} without the use of aggregations',
+ values: {
+ elasticsearch: ELASTICSEARCH,
+ },
+ }),
+ getWarningTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.warningTitle', {
+ defaultMessage: 'Query with caution',
+ }),
+ getWarning: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.warningDescription', {
+ defaultMessage: `
+ Using this data source with larger data sets can result in slower performance. Use this source only when you need exact values.`,
+ }),
+ getIndexTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.indexTitle', {
+ defaultMessage: 'Index',
+ }),
+ getIndexLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.indexLabel', {
+ defaultMessage: 'Enter an index name or select an index pattern',
+ }),
+ getQueryTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.queryTitle', {
+ defaultMessage: 'Query',
+ }),
+ getQueryLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.queryLabel', {
+ defaultMessage: '{lucene} query string syntax',
+ values: {
+ lucene: LUCENE,
+ },
+ }),
+ getSortFieldTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.sortFieldTitle', {
+ defaultMessage: 'Sort field',
+ }),
+ getSortFieldLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.sortFieldLabel', {
+ defaultMessage: 'Document sort field',
+ }),
+ getSortOrderTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.sortOrderTitle', {
+ defaultMessage: 'Sort order',
+ }),
+ getSortOrderLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.sortOrderLabel', {
+ defaultMessage: 'Document sort order',
+ }),
+ getFieldsTitle: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.fieldsTitle', {
+ defaultMessage: 'Fields',
+ }),
+ getFieldsLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.fieldsLabel', {
+ defaultMessage: 'Scripted fields are unavailable',
+ }),
+ getFieldsWarningLabel: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.fieldsWarningLabel', {
+ defaultMessage: 'This datasource performs best with 10 or fewer fields',
+ }),
+ getAscendingOption: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.ascendingDropDown', {
+ defaultMessage: 'Ascending',
+ }),
+ getDescendingOption: () =>
+ i18n.translate('xpack.canvas.uis.dataSources.esdocs.descendingDropDown', {
+ defaultMessage: 'Descending',
+ }),
+ },
+ // Elasticsearch SQL data source
Essql: {
getDisplayName: () =>
i18n.translate('xpack.canvas.uis.dataSources.essqlTitle', {
@@ -341,7 +424,7 @@ export const DataSourceStrings = {
}),
getHelp: () =>
i18n.translate('xpack.canvas.uis.dataSources.essqlLabel', {
- defaultMessage: 'Use {elasticsearch} {sql} to get a data table',
+ defaultMessage: 'Write an {elasticsearch} {sql} query to retrieve data',
values: {
elasticsearch: ELASTICSEARCH,
sql: SQL,
@@ -353,18 +436,18 @@ export const DataSourceStrings = {
}),
getLabelAppend: () =>
i18n.translate('xpack.canvas.uis.dataSources.essql.queryTitleAppend', {
- defaultMessage: 'Learn {elasticsearchShort} {sql} syntax',
+ defaultMessage: 'Learn {elasticsearchShort} {sql} query syntax',
values: {
elasticsearchShort: ELASTICSEARCH_SHORT,
sql: SQL,
},
}),
},
+ // Timelion datasource
Timelion: {
getAbout: () =>
i18n.translate('xpack.canvas.uis.dataSources.timelion.aboutDetail', {
- defaultMessage:
- 'Use {timelion} queries to pull back timeseries data that can be used with {canvas} elements.',
+ defaultMessage: 'Use {timelion} syntax in {canvas} to retrieve timeseries data',
values: {
timelion: TIMELION,
canvas: CANVAS,
@@ -372,7 +455,7 @@ export const DataSourceStrings = {
}),
getHelp: () =>
i18n.translate('xpack.canvas.uis.dataSources.timelionLabel', {
- defaultMessage: 'Use {timelion} syntax to retrieve a timeseries',
+ defaultMessage: 'Use {timelion} syntax to retrieve timeseries data',
values: {
timelion: TIMELION,
},
@@ -392,11 +475,11 @@ export const DataSourceStrings = {
i18n.translate('xpack.canvas.uis.dataSources.timelion.intervalTitle', {
defaultMessage: 'Interval',
}),
- getQueryHelp: () =>
+ queryLabel: () =>
i18n.translate('xpack.canvas.uis.dataSources.timelion.queryLabel', {
- defaultMessage: '{lucene} Query String syntax',
+ defaultMessage: '{timelion} Query String syntax',
values: {
- lucene: LUCENE,
+ timelion: TIMELION,
},
}),
getQueryLabel: () =>
diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss
index 2407dcbbce5939..52c473ac2dd387 100644
--- a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss
+++ b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss
@@ -6,8 +6,13 @@
padding: 0 $euiSizeS;
}
-.canvasDataSource__section {
- padding: $euiSizeM;
+.canvasDataSource__section,
+.canvasDataSource__list {
+ padding: $euiSizeM $euiSizeM 0;
+}
+
+.canvasDataSource__sectionFooter {
+ padding: 0 $euiSizeM;
}
.canvasDataSource__triggerButton {
@@ -19,10 +24,6 @@
margin-right: $euiSizeS;
}
-.canvasDataSource__list {
- padding: $euiSizeM;
-}
-
.canvasDataSource__card .euiCard__content {
padding-top: 0 !important; // sass-lint:disable-line no-important
}
diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js
index 8b0061e047f33f..285b69f057cd8f 100644
--- a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js
+++ b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js
@@ -153,7 +153,7 @@ export class DatasourceComponent extends PureComponent {
flush="left"
size="s"
>
-
+
{stateDatasource.displayName}
diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js
index 92f9b92cb1f06e..153a8a7ef75e62 100644
--- a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js
+++ b/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js
@@ -15,6 +15,7 @@ export const DatasourceSelector = ({ onSelect, datasources, current }) => (
key={d.name}
title={d.displayName}
titleElement="h5"
+ titleSize="xs"
icon={ }
description={d.help}
layout="horizontal"
diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts
index 7f81adad6bf9b4..949264fcc9fdb1 100644
--- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts
+++ b/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_export/index.ts
@@ -6,7 +6,7 @@
import { connect } from 'react-redux';
import { compose, withProps } from 'recompose';
-import * as jobCompletionNotifications from '../../../../../reporting/public/lib/job_completion_notifications';
+import { jobCompletionNotifications } from '../../../../../../../plugins/reporting/public';
// @ts-ignore Untyped local
import { getWorkpad, getPages } from '../../../state/selectors/workpad';
// @ts-ignore Untyped local
diff --git a/x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js b/x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js
index d6d395feade8b9..2cd7c5efb74e95 100644
--- a/x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js
+++ b/x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { datasourceRegistry } from '../expression_types/datasource';
+//import { datasourceRegistry } from '../expression_types/datasource';
import { transformRegistry } from '../expression_types/transform';
import { modelRegistry } from '../expression_types/model';
import { viewRegistry } from '../expression_types/view';
@@ -28,9 +28,6 @@ export function findExpressionType(name, type) {
case 'transform':
expression = transformRegistry.get(name);
return !expression ? acc : acc.concat(expression);
- case 'datasource':
- expression = datasourceRegistry.get(name);
- return !expression ? acc : acc.concat(expression);
default:
return acc;
}
diff --git a/x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js b/x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js
index fb23f9459d30b9..82699eb5b88fa4 100644
--- a/x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js
+++ b/x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js
@@ -5,11 +5,9 @@
*/
import { argTypeSpecs } from '../expression_types/arg_types';
-import { datasourceSpecs } from '../expression_types/datasources';
-import { argTypeRegistry, datasourceRegistry } from '../expression_types';
+import { argTypeRegistry } from '../expression_types';
export function loadExpressionTypes() {
// register default args, arg types, and expression types
argTypeSpecs.forEach(expFn => argTypeRegistry.register(expFn));
- datasourceSpecs.forEach(expFn => datasourceRegistry.register(expFn));
}
diff --git a/x-pack/legacy/plugins/canvas/public/plugin.tsx b/x-pack/legacy/plugins/canvas/public/plugin.tsx
index 0a3faca1a25224..f4a3aed28a0a45 100644
--- a/x-pack/legacy/plugins/canvas/public/plugin.tsx
+++ b/x-pack/legacy/plugins/canvas/public/plugin.tsx
@@ -11,8 +11,6 @@ import { initLoadingIndicator } from './lib/loading_indicator';
import { featureCatalogueEntry } from './feature_catalogue_entry';
import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public';
// @ts-ignore untyped local
-import { datasourceSpecs } from './expression_types/datasources';
-// @ts-ignore untyped local
import { argTypeSpecs } from './expression_types/arg_types';
import { transitions } from './transitions';
import { legacyRegistries } from './legacy_plugin_support';
@@ -90,7 +88,6 @@ export class CanvasPlugin
// Register core canvas stuff
canvasApi.addFunctions(initFunctions({ typesRegistry: plugins.expressions.__LEGACY.types }));
- canvasApi.addDatasourceUIs(datasourceSpecs);
canvasApi.addArgumentUIs(argTypeSpecs);
canvasApi.addTransitions(transitions);
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_form.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_form.js
index ebb731a1b1acaf..d4e418a964c8ff 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_form.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/auto_follow_pattern_form.js
@@ -29,7 +29,8 @@ import {
EuiTitle,
} from '@elastic/eui';
-import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
+import { indices } from '../../../../../../../src/plugins/es_ui_shared/public';
+import { indexPatterns } from '../../../../../../../src/plugins/data/public';
import routing from '../services/routing';
import { extractQueryParams } from '../services/query_params';
@@ -44,10 +45,9 @@ import {
} from '../services/auto_follow_pattern_validators';
import { AutoFollowPatternRequestFlyout } from './auto_follow_pattern_request_flyout';
-import { indexPatterns } from '../../../../../../../src/plugins/data/public';
const indexPatternIllegalCharacters = indexPatterns.ILLEGAL_CHARACTERS_VISIBLE.join(' ');
-const indexNameIllegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
+const indexNameIllegalCharacters = indices.INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
const getEmptyAutoFollowPattern = (remoteClusterName = '') => ({
name: '',
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.js
index 329ef4756133db..fc8f9398807e72 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.js
@@ -9,7 +9,6 @@ import PropTypes from 'prop-types';
import { debounce } from 'lodash';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
import { fatalError } from 'ui/notify';
import {
@@ -30,6 +29,7 @@ import {
EuiTitle,
} from '@elastic/eui';
+import { indices } from '../../../../../../../../src/plugins/es_ui_shared/public';
import { indexNameValidator, leaderIndexValidator } from '../../services/input_validation';
import routing from '../../services/routing';
import { loadIndices } from '../../services/api';
@@ -47,7 +47,7 @@ import { RemoteClustersFormField } from '../remote_clusters_form_field';
import { FollowerIndexRequestFlyout } from './follower_index_request_flyout';
-const indexNameIllegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
+const indexNameIllegalCharacters = indices.INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
const fieldToValidatorMap = advancedSettingsFields.reduce(
(map, advancedSetting) => {
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.js
index aac04270988131..93da20a8ed93c6 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/components/follower_index_form/follower_index_form.test.js
@@ -7,9 +7,6 @@
import { updateFields, updateFormErrors } from './follower_index_form';
jest.mock('ui/new_platform');
-jest.mock('ui/indices', () => ({
- INDEX_ILLEGAL_CHARACTERS_VISIBLE: [],
-}));
describe(' state transitions', () => {
it('updateFormErrors() should merge errors with existing fieldsErrors', () => {
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.js
index 18610c87c0a51a..5186a02383d33c 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/auto_follow_pattern_validators.js
@@ -8,13 +8,14 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import {
+import { indices } from '../../../../../../../src/plugins/es_ui_shared/public';
+import { indexPatterns } from '../../../../../../../src/plugins/data/public';
+
+const {
indexNameBeginsWithPeriod,
findIllegalCharactersInIndexName,
indexNameContainsSpaces,
-} from 'ui/indices';
-
-import { indexPatterns } from '../../../../../../../src/plugins/data/public';
+} = indices;
export const validateName = (name = '') => {
let errorMsg = null;
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/input_validation.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/input_validation.js
index 22f7d3be2795fb..981b3f59297513 100644
--- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/input_validation.js
+++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/services/input_validation.js
@@ -6,7 +6,7 @@
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
-import { INDEX_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/indices';
+import { indices } from '../../../../../../../src/plugins/es_ui_shared/public';
const isEmpty = value => {
return !value || !value.trim().length;
@@ -19,7 +19,7 @@ const beginsWithPeriod = value => {
};
const findIllegalCharacters = value => {
- return INDEX_ILLEGAL_CHARACTERS_VISIBLE.reduce((chars, char) => {
+ return indices.INDEX_ILLEGAL_CHARACTERS_VISIBLE.reduce((chars, char) => {
if (value.includes(char)) {
chars.push(char);
}
diff --git a/x-pack/legacy/plugins/lens/public/_config_panel.scss b/x-pack/legacy/plugins/lens/public/_config_panel.scss
deleted file mode 100644
index 5c6d25bf10818e..00000000000000
--- a/x-pack/legacy/plugins/lens/public/_config_panel.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-.lnsConfigPanel__panel {
- margin-bottom: $euiSizeS;
-}
-
-.lnsConfigPanel__axis {
- background: $euiColorLightestShade;
- padding: $euiSizeS;
- border-radius: $euiBorderRadius;
-
- // Add margin to the top of the next same panel
- & + & {
- margin-top: $euiSizeS;
- }
-}
-
-.lnsConfigPanel__addLayerBtn {
- color: transparentize($euiColorMediumShade, .3);
- // sass-lint:disable-block no-important
- box-shadow: none !important;
- border: 1px dashed currentColor;
-}
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx
index 0cba22170df1fc..e18190b6c2d692 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx
@@ -4,18 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
import { createMockDatasource } from '../editor_frame_service/mocks';
-import {
- DatatableVisualizationState,
- datatableVisualization,
- DataTableLayer,
-} from './visualization';
-import { mount } from 'enzyme';
+import { DatatableVisualizationState, datatableVisualization } from './visualization';
import { Operation, DataType, FramePublicAPI, TableSuggestionColumn } from '../types';
-import { generateId } from '../id_generator';
-
-jest.mock('../id_generator');
function mockFrame(): FramePublicAPI {
return {
@@ -34,12 +25,11 @@ function mockFrame(): FramePublicAPI {
describe('Datatable Visualization', () => {
describe('#initialize', () => {
it('should initialize from the empty state', () => {
- (generateId as jest.Mock).mockReturnValueOnce('id');
expect(datatableVisualization.initialize(mockFrame(), undefined)).toEqual({
layers: [
{
layerId: 'aaa',
- columns: ['id'],
+ columns: [],
},
],
});
@@ -88,7 +78,6 @@ describe('Datatable Visualization', () => {
describe('#clearLayer', () => {
it('should reset the layer', () => {
- (generateId as jest.Mock).mockReturnValueOnce('testid');
const state: DatatableVisualizationState = {
layers: [
{
@@ -101,7 +90,7 @@ describe('Datatable Visualization', () => {
layers: [
{
layerId: 'baz',
- columns: ['testid'],
+ columns: [],
},
],
});
@@ -214,29 +203,35 @@ describe('Datatable Visualization', () => {
});
});
- describe('DataTableLayer', () => {
- it('allows all kinds of operations', () => {
- const setState = jest.fn();
- const datasource = createMockDatasource();
- const layer = { layerId: 'a', columns: ['b', 'c'] };
+ describe('#getConfiguration', () => {
+ it('returns a single layer option', () => {
+ const datasource = createMockDatasource('test');
const frame = mockFrame();
- frame.datasourceLayers = { a: datasource.publicAPIMock };
+ frame.datasourceLayers = { first: datasource.publicAPIMock };
- mount(
- {} }}
- frame={frame}
- layer={layer}
- setState={setState}
- state={{ layers: [layer] }}
- />
- );
+ expect(
+ datatableVisualization.getConfiguration({
+ layerId: 'first',
+ state: {
+ layers: [{ layerId: 'first', columns: [] }],
+ },
+ frame,
+ }).groups
+ ).toHaveLength(1);
+ });
- expect(datasource.publicAPIMock.renderDimensionPanel).toHaveBeenCalled();
+ it('allows all kinds of operations', () => {
+ const datasource = createMockDatasource('test');
+ const frame = mockFrame();
+ frame.datasourceLayers = { first: datasource.publicAPIMock };
- const filterOperations =
- datasource.publicAPIMock.renderDimensionPanel.mock.calls[0][1].filterOperations;
+ const filterOperations = datatableVisualization.getConfiguration({
+ layerId: 'first',
+ state: {
+ layers: [{ layerId: 'first', columns: [] }],
+ },
+ frame,
+ }).groups[0].filterOperations;
const baseOperation: Operation = {
dataType: 'string',
@@ -253,108 +248,80 @@ describe('Datatable Visualization', () => {
);
});
- it('allows columns to be removed', () => {
- const setState = jest.fn();
- const datasource = createMockDatasource();
+ it('reorders the rendered colums based on the order from the datasource', () => {
+ const datasource = createMockDatasource('test');
const layer = { layerId: 'a', columns: ['b', 'c'] };
const frame = mockFrame();
frame.datasourceLayers = { a: datasource.publicAPIMock };
- const component = mount(
- {} }}
- frame={frame}
- layer={layer}
- setState={setState}
- state={{ layers: [layer] }}
- />
- );
-
- const onRemove = component
- .find('[data-test-subj="datatable_multicolumnEditor"]')
- .first()
- .prop('onRemove') as (k: string) => {};
-
- onRemove('b');
+ datasource.publicAPIMock.getTableSpec.mockReturnValue([{ columnId: 'c' }, { columnId: 'b' }]);
+
+ expect(
+ datatableVisualization.getConfiguration({
+ layerId: 'a',
+ state: { layers: [layer] },
+ frame,
+ }).groups[0].accessors
+ ).toEqual(['c', 'b']);
+ });
+ });
- expect(setState).toHaveBeenCalledWith({
+ describe('#removeDimension', () => {
+ it('allows columns to be removed', () => {
+ const layer = { layerId: 'layer1', columns: ['b', 'c'] };
+ expect(
+ datatableVisualization.removeDimension({
+ prevState: { layers: [layer] },
+ layerId: 'layer1',
+ columnId: 'b',
+ })
+ ).toEqual({
layers: [
{
- layerId: 'a',
+ layerId: 'layer1',
columns: ['c'],
},
],
});
});
+ });
+ describe('#setDimension', () => {
it('allows columns to be added', () => {
- (generateId as jest.Mock).mockReturnValueOnce('d');
- const setState = jest.fn();
- const datasource = createMockDatasource();
- const layer = { layerId: 'a', columns: ['b', 'c'] };
- const frame = mockFrame();
- frame.datasourceLayers = { a: datasource.publicAPIMock };
- const component = mount(
- {} }}
- frame={frame}
- layer={layer}
- setState={setState}
- state={{ layers: [layer] }}
- />
- );
-
- const onAdd = component
- .find('[data-test-subj="datatable_multicolumnEditor"]')
- .first()
- .prop('onAdd') as () => {};
-
- onAdd();
-
- expect(setState).toHaveBeenCalledWith({
+ const layer = { layerId: 'layer1', columns: ['b', 'c'] };
+ expect(
+ datatableVisualization.setDimension({
+ prevState: { layers: [layer] },
+ layerId: 'layer1',
+ columnId: 'd',
+ groupId: '',
+ })
+ ).toEqual({
layers: [
{
- layerId: 'a',
+ layerId: 'layer1',
columns: ['b', 'c', 'd'],
},
],
});
});
- it('reorders the rendered colums based on the order from the datasource', () => {
- const datasource = createMockDatasource();
- const layer = { layerId: 'a', columns: ['b', 'c'] };
- const frame = mockFrame();
- frame.datasourceLayers = { a: datasource.publicAPIMock };
- const component = mount(
- {} }}
- frame={frame}
- layer={layer}
- setState={jest.fn()}
- state={{ layers: [layer] }}
- />
- );
-
- const accessors = component
- .find('[data-test-subj="datatable_multicolumnEditor"]')
- .first()
- .prop('accessors') as string[];
-
- expect(accessors).toEqual(['b', 'c']);
-
- component.setProps({
- layer: { layerId: 'a', columns: ['c', 'b'] },
+ it('does not set a duplicate dimension', () => {
+ const layer = { layerId: 'layer1', columns: ['b', 'c'] };
+ expect(
+ datatableVisualization.setDimension({
+ prevState: { layers: [layer] },
+ layerId: 'layer1',
+ columnId: 'b',
+ groupId: '',
+ })
+ ).toEqual({
+ layers: [
+ {
+ layerId: 'layer1',
+ columns: ['b', 'c'],
+ },
+ ],
});
-
- const newAccessors = component
- .find('[data-test-subj="datatable_multicolumnEditor"]')
- .first()
- .prop('accessors') as string[];
-
- expect(newAccessors).toEqual(['c', 'b']);
});
});
});
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx
index 79a018635134f6..4248d722d55409 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx
@@ -4,20 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
-import { render } from 'react-dom';
-import { EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { I18nProvider } from '@kbn/i18n/react';
-import { MultiColumnEditor } from '../multi_column_editor';
-import {
- SuggestionRequest,
- Visualization,
- VisualizationLayerConfigProps,
- VisualizationSuggestion,
- Operation,
-} from '../types';
-import { generateId } from '../id_generator';
+import { SuggestionRequest, Visualization, VisualizationSuggestion, Operation } from '../types';
import chartTableSVG from '../assets/chart_datatable.svg';
export interface LayerState {
@@ -32,58 +20,10 @@ export interface DatatableVisualizationState {
function newLayerState(layerId: string): LayerState {
return {
layerId,
- columns: [generateId()],
+ columns: [],
};
}
-function updateColumns(
- state: DatatableVisualizationState,
- layer: LayerState,
- fn: (columns: string[]) => string[]
-) {
- const columns = fn(layer.columns);
- const updatedLayer = { ...layer, columns };
- const layers = state.layers.map(l => (l.layerId === layer.layerId ? updatedLayer : l));
- return { ...state, layers };
-}
-
-const allOperations = () => true;
-
-export function DataTableLayer({
- layer,
- frame,
- state,
- setState,
- dragDropContext,
-}: { layer: LayerState } & VisualizationLayerConfigProps) {
- const datasource = frame.datasourceLayers[layer.layerId];
-
- const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
- // When we add a column it could be empty, and therefore have no order
- const sortedColumns = Array.from(new Set(originalOrder.concat(layer.columns)));
-
- return (
-
- setState(updateColumns(state, layer, columns => [...columns, generateId()]))}
- onRemove={column =>
- setState(updateColumns(state, layer, columns => columns.filter(c => c !== column)))
- }
- testSubj="datatable_columns"
- data-test-subj="datatable_multicolumnEditor"
- />
-
- );
-}
-
export const datatableVisualization: Visualization<
DatatableVisualizationState,
DatatableVisualizationState
@@ -188,17 +128,56 @@ export const datatableVisualization: Visualization<
];
},
- renderLayerConfigPanel(domElement, props) {
- const layer = props.state.layers.find(l => l.layerId === props.layerId);
-
- if (layer) {
- render(
-
-
- ,
- domElement
- );
+ getConfiguration({ state, frame, layerId }) {
+ const layer = state.layers.find(l => l.layerId === layerId);
+ if (!layer) {
+ return { groups: [] };
}
+
+ const datasource = frame.datasourceLayers[layer.layerId];
+ const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
+ // When we add a column it could be empty, and therefore have no order
+ const sortedColumns = Array.from(new Set(originalOrder.concat(layer.columns)));
+
+ return {
+ groups: [
+ {
+ groupId: 'columns',
+ groupLabel: i18n.translate('xpack.lens.datatable.columns', {
+ defaultMessage: 'Columns',
+ }),
+ layerId: state.layers[0].layerId,
+ accessors: sortedColumns,
+ supportsMoreColumns: true,
+ filterOperations: () => true,
+ },
+ ],
+ };
+ },
+
+ setDimension({ prevState, layerId, columnId }) {
+ return {
+ ...prevState,
+ layers: prevState.layers.map(l => {
+ if (l.layerId !== layerId || l.columns.includes(columnId)) {
+ return l;
+ }
+ return { ...l, columns: [...l.columns, columnId] };
+ }),
+ };
+ },
+ removeDimension({ prevState, layerId, columnId }) {
+ return {
+ ...prevState,
+ layers: prevState.layers.map(l =>
+ l.layerId === layerId
+ ? {
+ ...l,
+ columns: l.columns.filter(c => c !== columnId),
+ }
+ : l
+ ),
+ };
},
toExpression(state, frame) {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss
new file mode 100644
index 00000000000000..62a7f6b023f314
--- /dev/null
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss
@@ -0,0 +1,50 @@
+.lnsConfigPanel__panel {
+ margin-bottom: $euiSizeS;
+}
+
+.lnsConfigPanel__row {
+ background: $euiColorLightestShade;
+ padding: $euiSizeS;
+ border-radius: $euiBorderRadius;
+
+ // Add margin to the top of the next same panel
+ & + & {
+ margin-top: $euiSizeS;
+ }
+}
+
+.lnsConfigPanel__addLayerBtn {
+ color: transparentize($euiColorMediumShade, .3);
+ // Remove EuiButton's default shadow to make button more subtle
+ // sass-lint:disable-block no-important
+ box-shadow: none !important;
+ border: 1px dashed currentColor;
+}
+
+.lnsConfigPanel__dimension {
+ @include euiFontSizeS;
+ background: lightOrDarkTheme($euiColorEmptyShade, $euiColorLightestShade);
+ border-radius: $euiBorderRadius;
+ display: flex;
+ align-items: center;
+ margin-top: $euiSizeXS;
+ overflow: hidden;
+}
+
+.lnsConfigPanel__trigger {
+ max-width: 100%;
+ display: block;
+}
+
+.lnsConfigPanel__triggerLink {
+ padding: $euiSizeS;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ min-height: $euiSizeXXL;
+}
+
+.lnsConfigPanel__popover {
+ line-height: 0;
+ flex-grow: 1;
+}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx
index 1b60098fd45ad1..6698c9e68b98c0 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx
@@ -84,7 +84,7 @@ describe('chart_switch', () => {
}
function mockDatasourceMap() {
- const datasource = createMockDatasource();
+ const datasource = createMockDatasource('testDatasource');
datasource.getDatasourceSuggestionsFromCurrentState.mockReturnValue([
{
state: {},
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx
index 1422ee86be3e9b..c2cd0485de67ee 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx
@@ -16,17 +16,21 @@ import {
EuiToolTip,
EuiButton,
EuiForm,
+ EuiFormRow,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
import { NativeRenderer } from '../../native_renderer';
import { Action } from './state_management';
import {
Visualization,
FramePublicAPI,
Datasource,
- VisualizationLayerConfigProps,
+ VisualizationLayerWidgetProps,
+ DatasourceDimensionEditorProps,
+ StateSetter,
} from '../../types';
-import { DragContext } from '../../drag_drop';
+import { DragContext, DragDrop, ChildDragDropProvider } from '../../drag_drop';
import { ChartSwitch } from './chart_switch';
import { trackUiEvent } from '../../lens_ui_telemetry';
import { generateId } from '../../id_generator';
@@ -47,6 +51,7 @@ interface ConfigPanelWrapperProps {
state: unknown;
}
>;
+ core: DatasourceDimensionEditorProps['core'];
}
export const ConfigPanelWrapper = memo(function ConfigPanelWrapper(props: ConfigPanelWrapperProps) {
@@ -86,8 +91,7 @@ function LayerPanels(
activeDatasourceId,
datasourceMap,
} = props;
- const dragDropContext = useContext(DragContext);
- const setState = useMemo(
+ const setVisualizationState = useMemo(
() => (newState: unknown) => {
props.dispatch({
type: 'UPDATE_VISUALIZATION_STATE',
@@ -98,6 +102,43 @@ function LayerPanels(
},
[props.dispatch, activeVisualization]
);
+ const updateDatasource = useMemo(
+ () => (datasourceId: string, newState: unknown) => {
+ props.dispatch({
+ type: 'UPDATE_DATASOURCE_STATE',
+ updater: () => newState,
+ datasourceId,
+ clearStagedPreview: false,
+ });
+ },
+ [props.dispatch]
+ );
+ const updateAll = useMemo(
+ () => (datasourceId: string, newDatasourceState: unknown, newVisualizationState: unknown) => {
+ props.dispatch({
+ type: 'UPDATE_STATE',
+ subType: 'UPDATE_ALL_STATES',
+ updater: prevState => {
+ return {
+ ...prevState,
+ datasourceStates: {
+ ...prevState.datasourceStates,
+ [datasourceId]: {
+ state: newDatasourceState,
+ isLoading: false,
+ },
+ },
+ visualization: {
+ activeId: activeVisualization.id,
+ state: newVisualizationState,
+ },
+ stagedPreview: undefined,
+ };
+ },
+ });
+ },
+ [props.dispatch]
+ );
const layerIds = activeVisualization.getLayerIds(visualizationState);
return (
@@ -108,12 +149,13 @@ function LayerPanels(
key={layerId}
layerId={layerId}
activeVisualization={activeVisualization}
- dragDropContext={dragDropContext}
- state={setState}
- setState={setState}
+ visualizationState={visualizationState}
+ updateVisualization={setVisualizationState}
+ updateDatasource={updateDatasource}
+ updateAll={updateAll}
frame={framePublicAPI}
isOnlyLayer={layerIds.length === 1}
- onRemove={() => {
+ onRemoveLayer={() => {
dispatch({
type: 'UPDATE_STATE',
subType: 'REMOVE_OR_CLEAR_LAYER',
@@ -143,7 +185,7 @@ function LayerPanels(
className="lnsConfigPanel__addLayerBtn"
fullWidth
size="s"
- data-test-subj={`lnsXY_layer_add`}
+ data-test-subj="lnsXY_layer_add"
aria-label={i18n.translate('xpack.lens.xyChart.addLayerButton', {
defaultMessage: 'Add layer',
})}
@@ -174,85 +216,399 @@ function LayerPanels(
}
function LayerPanel(
- props: ConfigPanelWrapperProps &
- VisualizationLayerConfigProps & {
- isOnlyLayer: boolean;
- activeVisualization: Visualization;
- onRemove: () => void;
- }
+ props: Exclude & {
+ frame: FramePublicAPI;
+ layerId: string;
+ isOnlyLayer: boolean;
+ activeVisualization: Visualization;
+ visualizationState: unknown;
+ updateVisualization: StateSetter;
+ updateDatasource: (datasourceId: string, newState: unknown) => void;
+ updateAll: (
+ datasourceId: string,
+ newDatasourcestate: unknown,
+ newVisualizationState: unknown
+ ) => void;
+ onRemoveLayer: () => void;
+ }
) {
- const { framePublicAPI, layerId, activeVisualization, isOnlyLayer, onRemove } = props;
+ const dragDropContext = useContext(DragContext);
+ const { framePublicAPI, layerId, activeVisualization, isOnlyLayer, onRemoveLayer } = props;
const datasourcePublicAPI = framePublicAPI.datasourceLayers[layerId];
- const layerConfigProps = {
+ if (!datasourcePublicAPI) {
+ return null;
+ }
+ const layerVisualizationConfigProps = {
layerId,
- dragDropContext: props.dragDropContext,
+ dragDropContext,
state: props.visualizationState,
- setState: props.setState,
frame: props.framePublicAPI,
+ dateRange: props.framePublicAPI.dateRange,
};
+ const datasourceId = datasourcePublicAPI.datasourceId;
+ const layerDatasourceState = props.datasourceStates[datasourceId].state;
+ const layerDatasource = props.datasourceMap[datasourceId];
- return (
-
-
-
-
-
+ const layerDatasourceDropProps = {
+ layerId,
+ dragDropContext,
+ state: layerDatasourceState,
+ setState: (newState: unknown) => {
+ props.updateDatasource(datasourceId, newState);
+ },
+ };
- {datasourcePublicAPI && (
-
- ({
+ isOpen: false,
+ openId: null,
+ addingToGroupId: null,
+ });
+
+ const { groups } = activeVisualization.getConfiguration(layerVisualizationConfigProps);
+ const isEmptyLayer = !groups.some(d => d.accessors.length > 0);
+
+ function wrapInPopover(
+ id: string,
+ groupId: string,
+ trigger: React.ReactElement,
+ panel: React.ReactElement
+ ) {
+ const noMatch = popoverState.isOpen ? !groups.some(d => d.accessors.includes(id)) : false;
+ return (
+ {
+ setPopoverState({ isOpen: false, openId: null, addingToGroupId: null });
+ }}
+ button={trigger}
+ anchorPosition="leftUp"
+ withTitle
+ panelPaddingSize="s"
+ >
+ {panel}
+
+ );
+ }
+
+ return (
+
+
+
+
+
- )}
-
-
-
-
+ {layerDatasource && (
+
+ {
+ const newState =
+ typeof updater === 'function' ? updater(layerDatasourceState) : updater;
+ // Look for removed columns
+ const nextPublicAPI = layerDatasource.getPublicAPI({
+ state: newState,
+ layerId,
+ dateRange: props.framePublicAPI.dateRange,
+ });
+ const nextTable = new Set(
+ nextPublicAPI.getTableSpec().map(({ columnId }) => columnId)
+ );
+ const removed = datasourcePublicAPI
+ .getTableSpec()
+ .map(({ columnId }) => columnId)
+ .filter(columnId => !nextTable.has(columnId));
+ let nextVisState = props.visualizationState;
+ removed.forEach(columnId => {
+ nextVisState = activeVisualization.removeDimension({
+ layerId,
+ columnId,
+ prevState: nextVisState,
+ });
+ });
-
+ props.updateAll(datasourceId, newState, nextVisState);
+ },
+ }}
+ />
+
+ )}
+
-
-
- {
- // If we don't blur the remove / clear button, it remains focused
- // which is a strange UX in this case. e.target.blur doesn't work
- // due to who knows what, but probably event re-writing. Additionally,
- // activeElement does not have blur so, we need to do some casting + safeguards.
- const el = (document.activeElement as unknown) as { blur: () => void };
+
- if (el && el.blur) {
- el.blur();
+ {groups.map((group, index) => {
+ const newId = generateId();
+ const isMissing = !isEmptyLayer && group.required && group.accessors.length === 0;
+ return (
+
+ <>
+ {group.accessors.map(accessor => (
+ {
+ layerDatasource.onDrop({
+ ...layerDatasourceDropProps,
+ droppedItem,
+ columnId: accessor,
+ filterOperations: group.filterOperations,
+ });
+ }}
+ >
+ {wrapInPopover(
+ accessor,
+ group.groupId,
+ {
+ if (popoverState.isOpen) {
+ setPopoverState({
+ isOpen: false,
+ openId: null,
+ addingToGroupId: null,
+ });
+ } else {
+ setPopoverState({
+ isOpen: true,
+ openId: accessor,
+ addingToGroupId: null, // not set for existing dimension
+ });
+ }
+ },
+ }}
+ />,
+
+ )}
- onRemove();
- }}
- >
- {isOnlyLayer
- ? i18n.translate('xpack.lens.resetLayer', {
- defaultMessage: 'Reset layer',
- })
- : i18n.translate('xpack.lens.deleteLayer', {
- defaultMessage: 'Delete layer',
- })}
-
-
-
-
+ {
+ trackUiEvent('indexpattern_dimension_removed');
+ props.updateAll(
+ datasourceId,
+ layerDatasource.removeColumn({
+ layerId,
+ columnId: accessor,
+ prevState: layerDatasourceState,
+ }),
+ props.activeVisualization.removeDimension({
+ layerId,
+ columnId: accessor,
+ prevState: props.visualizationState,
+ })
+ );
+ }}
+ />
+
+ ))}
+ {group.supportsMoreColumns ? (
+ {
+ const dropSuccess = layerDatasource.onDrop({
+ ...layerDatasourceDropProps,
+ droppedItem,
+ columnId: newId,
+ filterOperations: group.filterOperations,
+ });
+ if (dropSuccess) {
+ props.updateVisualization(
+ activeVisualization.setDimension({
+ layerId,
+ groupId: group.groupId,
+ columnId: newId,
+ prevState: props.visualizationState,
+ })
+ );
+ }
+ }}
+ >
+ {wrapInPopover(
+ newId,
+ group.groupId,
+
+ {
+ if (popoverState.isOpen) {
+ setPopoverState({
+ isOpen: false,
+ openId: null,
+ addingToGroupId: null,
+ });
+ } else {
+ setPopoverState({
+ isOpen: true,
+ openId: newId,
+ addingToGroupId: group.groupId,
+ });
+ }
+ }}
+ size="xs"
+ >
+
+
+
,
+ {
+ props.updateAll(
+ datasourceId,
+ newState,
+ activeVisualization.setDimension({
+ layerId,
+ groupId: group.groupId,
+ columnId: newId,
+ prevState: props.visualizationState,
+ })
+ );
+ setPopoverState({
+ isOpen: true,
+ openId: newId,
+ addingToGroupId: null, // clear now that dimension exists
+ });
+ },
+ }}
+ />
+ )}
+
+ ) : null}
+ >
+
+ );
+ })}
+
+
+
+
+
+ {
+ // If we don't blur the remove / clear button, it remains focused
+ // which is a strange UX in this case. e.target.blur doesn't work
+ // due to who knows what, but probably event re-writing. Additionally,
+ // activeElement does not have blur so, we need to do some casting + safeguards.
+ const el = (document.activeElement as unknown) as { blur: () => void };
+
+ if (el?.blur) {
+ el.blur();
+ }
+
+ onRemoveLayer();
+ }}
+ >
+ {isOnlyLayer
+ ? i18n.translate('xpack.lens.resetLayer', {
+ defaultMessage: 'Reset layer',
+ })
+ : i18n.translate('xpack.lens.deleteLayer', {
+ defaultMessage: 'Delete layer',
+ })}
+
+
+
+
+
);
}
@@ -263,7 +619,7 @@ function LayerSettings({
}: {
layerId: string;
activeVisualization: Visualization;
- layerConfigProps: VisualizationLayerConfigProps;
+ layerConfigProps: VisualizationLayerWidgetProps;
}) {
const [isOpen, setIsOpen] = useState(false);
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx
index dd591b3992fe52..8d8d38944e18a3 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx
@@ -87,14 +87,15 @@ describe('editor_frame', () => {
mockVisualization.getLayerIds.mockReturnValue(['first']);
mockVisualization2.getLayerIds.mockReturnValue(['second']);
- mockDatasource = createMockDatasource();
- mockDatasource2 = createMockDatasource();
+ mockDatasource = createMockDatasource('testDatasource');
+ mockDatasource2 = createMockDatasource('testDatasource2');
expressionRendererMock = createExpressionRendererMock();
});
describe('initialization', () => {
it('should initialize initial datasource', async () => {
+ mockVisualization.getLayerIds.mockReturnValue([]);
await act(async () => {
mount(
{
});
it('should initialize all datasources with state from doc', async () => {
- const mockDatasource3 = createMockDatasource();
+ const mockDatasource3 = createMockDatasource('testDatasource3');
const datasource1State = { datasource1: '' };
const datasource2State = { datasource2: '' };
@@ -198,9 +199,9 @@ describe('editor_frame', () => {
ExpressionRenderer={expressionRendererMock}
/>
);
- expect(mockVisualization.renderLayerConfigPanel).not.toHaveBeenCalled();
expect(mockDatasource.renderDataPanel).not.toHaveBeenCalled();
});
+ expect(mockDatasource.renderDataPanel).toHaveBeenCalled();
});
it('should not initialize visualization before datasource is initialized', async () => {
@@ -289,6 +290,7 @@ describe('editor_frame', () => {
mockDatasource2.initialize.mockReturnValue(Promise.resolve(initialState));
mockDatasource2.getLayers.mockReturnValue(['abc', 'def']);
mockDatasource2.removeLayer.mockReturnValue({ removed: true });
+ mockVisualization.getLayerIds.mockReturnValue(['first', 'abc', 'def']);
await act(async () => {
mount(
{
);
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({ state: initialState })
);
});
@@ -614,15 +615,14 @@ describe('editor_frame', () => {
);
});
const updatedState = {};
- const setVisualizationState = (mockVisualization.renderLayerConfigPanel as jest.Mock).mock
- .calls[0][1].setState;
+ const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1]
+ .setState;
act(() => {
- setVisualizationState(updatedState);
+ setDatasourceState(updatedState);
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(2);
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenLastCalledWith(
- expect.any(Element),
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(2);
+ expect(mockVisualization.getConfiguration).toHaveBeenLastCalledWith(
expect.objectContaining({
state: updatedState,
})
@@ -688,8 +688,7 @@ describe('editor_frame', () => {
});
const updatedPublicAPI: DatasourcePublicAPI = {
- renderLayerPanel: jest.fn(),
- renderDimensionPanel: jest.fn(),
+ datasourceId: 'testDatasource',
getOperationForColumnId: jest.fn(),
getTableSpec: jest.fn(),
};
@@ -701,9 +700,8 @@ describe('editor_frame', () => {
setDatasourceState({});
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(2);
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenLastCalledWith(
- expect.any(Element),
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(2);
+ expect(mockVisualization.getConfiguration).toHaveBeenLastCalledWith(
expect.objectContaining({
frame: expect.objectContaining({
datasourceLayers: {
@@ -719,6 +717,7 @@ describe('editor_frame', () => {
it('should pass the datasource api for each layer to the visualization', async () => {
mockDatasource.getLayers.mockReturnValue(['first']);
mockDatasource2.getLayers.mockReturnValue(['second', 'third']);
+ mockVisualization.getLayerIds.mockReturnValue(['first', 'second', 'third']);
await act(async () => {
mount(
@@ -755,10 +754,10 @@ describe('editor_frame', () => {
);
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalled();
+ expect(mockVisualization.getConfiguration).toHaveBeenCalled();
const datasourceLayers =
- mockVisualization.renderLayerConfigPanel.mock.calls[0][1].frame.datasourceLayers;
+ mockVisualization.getConfiguration.mock.calls[0][0].frame.datasourceLayers;
expect(datasourceLayers.first).toBe(mockDatasource.publicAPIMock);
expect(datasourceLayers.second).toBe(mockDatasource2.publicAPIMock);
expect(datasourceLayers.third).toBe(mockDatasource2.publicAPIMock);
@@ -811,21 +810,18 @@ describe('editor_frame', () => {
expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith(
expect.objectContaining({
state: datasource1State,
- setState: expect.anything(),
layerId: 'first',
})
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
expect.objectContaining({
state: datasource2State,
- setState: expect.anything(),
layerId: 'second',
})
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
expect.objectContaining({
state: datasource2State,
- setState: expect.anything(),
layerId: 'third',
})
);
@@ -858,45 +854,9 @@ describe('editor_frame', () => {
expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith({
dateRange,
state: datasourceState,
- setState: expect.any(Function),
layerId: 'first',
});
});
-
- it('should re-create the public api after state has been set', async () => {
- mockDatasource.getLayers.mockReturnValue(['first']);
-
- await act(async () => {
- mount(
-
- );
- });
-
- const updatedState = {};
- const setDatasourceState = mockDatasource.getPublicAPI.mock.calls[0][0].setState;
- act(() => {
- setDatasourceState(updatedState);
- });
-
- expect(mockDatasource.getPublicAPI).toHaveBeenLastCalledWith(
- expect.objectContaining({
- state: updatedState,
- setState: expect.any(Function),
- layerId: 'first',
- })
- );
- });
});
describe('switching', () => {
@@ -1021,8 +981,7 @@ describe('editor_frame', () => {
expect(mockVisualization2.getSuggestions).toHaveBeenCalled();
expect(mockVisualization2.initialize).toHaveBeenCalledWith(expect.anything(), initialState);
- expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization2.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({ state: { initial: true } })
);
});
@@ -1039,8 +998,7 @@ describe('editor_frame', () => {
datasourceLayers: expect.objectContaining({ first: mockDatasource.publicAPIMock }),
})
);
- expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization2.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({ state: { initial: true } })
);
});
@@ -1239,9 +1197,8 @@ describe('editor_frame', () => {
.simulate('click');
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(1);
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(1);
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({
state: suggestionVisState,
})
@@ -1306,8 +1263,7 @@ describe('editor_frame', () => {
.simulate('drop');
});
- expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({
state: suggestionVisState,
})
@@ -1375,14 +1331,16 @@ describe('editor_frame', () => {
instance.update();
act(() => {
- instance.find(DragDrop).prop('onDrop')!({
+ instance
+ .find(DragDrop)
+ .filter('[data-test-subj="mockVisA"]')
+ .prop('onDrop')!({
indexPatternId: '1',
field: {},
});
});
- expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization2.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({
state: suggestionVisState,
})
@@ -1472,14 +1430,16 @@ describe('editor_frame', () => {
instance.update();
act(() => {
- instance.find(DragDrop).prop('onDrop')!({
+ instance
+ .find(DragDrop)
+ .filter('[data-test-subj="lnsWorkspace"]')
+ .prop('onDrop')!({
indexPatternId: '1',
field: {},
});
});
- expect(mockVisualization3.renderLayerConfigPanel).toHaveBeenCalledWith(
- expect.any(Element),
+ expect(mockVisualization3.getConfiguration).toHaveBeenCalledWith(
expect.objectContaining({
state: suggestionVisState,
})
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
index a456372c99c01d..082519d9a8febc 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx
@@ -21,6 +21,7 @@ import { FrameLayout } from './frame_layout';
import { SuggestionPanel } from './suggestion_panel';
import { WorkspacePanel } from './workspace_panel';
import { Document } from '../../persistence/saved_object_store';
+import { RootDragDropProvider } from '../../drag_drop';
import { getSavedObjectFormat } from './save';
import { WorkspacePanelWrapper } from './workspace_panel_wrapper';
import { generateId } from '../../id_generator';
@@ -90,21 +91,11 @@ export function EditorFrame(props: EditorFrameProps) {
const layers = datasource.getLayers(datasourceState);
layers.forEach(layer => {
- const publicAPI = props.datasourceMap[id].getPublicAPI({
+ datasourceLayers[layer] = props.datasourceMap[id].getPublicAPI({
state: datasourceState,
- setState: (newState: unknown) => {
- dispatch({
- type: 'UPDATE_DATASOURCE_STATE',
- datasourceId: id,
- updater: newState,
- clearStagedPreview: true,
- });
- },
layerId: layer,
dateRange: props.dateRange,
});
-
- datasourceLayers[layer] = publicAPI;
});
});
@@ -235,74 +226,79 @@ export function EditorFrame(props: EditorFrameProps) {
]);
return (
-
- }
- configPanel={
- allLoaded && (
-
+
- )
- }
- workspacePanel={
- allLoaded && (
-
-
+ )
+ }
+ workspacePanel={
+ allLoaded && (
+
+
+
+ )
+ }
+ suggestionsPanel={
+ allLoaded && (
+
-
- )
- }
- suggestionsPanel={
- allLoaded && (
-
- )
- }
- />
+ )
+ }
+ />
+
);
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
index a69da8b49e2330..56afe3ed69a734 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx
@@ -6,7 +6,6 @@
import React from 'react';
import { EuiPage, EuiPageSideBar, EuiPageBody } from '@elastic/eui';
-import { RootDragDropProvider } from '../../drag_drop';
export interface FrameLayoutProps {
dataPanel: React.ReactNode;
@@ -17,19 +16,17 @@ export interface FrameLayoutProps {
export function FrameLayout(props: FrameLayoutProps) {
return (
-
-
-
- {props.dataPanel}
-
- {props.workspacePanel}
- {props.suggestionsPanel}
-
-
- {props.configPanel}
-
-
-
-
+
+
+ {props.dataPanel}
+
+ {props.workspacePanel}
+ {props.suggestionsPanel}
+
+
+ {props.configPanel}
+
+
+
);
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss
index fee28c374ef7ef..6c6a63c8c7eb6d 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss
@@ -1,4 +1,5 @@
@import './chart_switch';
+@import './config_panel_wrapper';
@import './data_panel_wrapper';
@import './expression_renderer';
@import './frame_layout';
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts
index 158a6cb8c979aa..60bfbc493f61cc 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts
@@ -11,7 +11,7 @@ import { esFilters, IIndexPattern, IFieldType } from '../../../../../../../src/p
describe('save editor frame state', () => {
const mockVisualization = createMockVisualization();
mockVisualization.getPersistableState.mockImplementation(x => x);
- const mockDatasource = createMockDatasource();
+ const mockDatasource = createMockDatasource('a');
const mockIndexPattern = ({ id: 'indexpattern' } as unknown) as IIndexPattern;
const mockField = ({ name: '@timestamp' } as unknown) as IFieldType;
@@ -45,7 +45,7 @@ describe('save editor frame state', () => {
};
it('transforms from internal state to persisted doc format', async () => {
- const datasource = createMockDatasource();
+ const datasource = createMockDatasource('a');
datasource.getPersistableState.mockImplementation(state => ({
stuff: `${state}_datasource_persisted`,
}));
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts
index 487a91c22b5d53..63b8b1f0482968 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts
@@ -30,7 +30,7 @@ let datasourceStates: Record<
beforeEach(() => {
datasourceMap = {
- mock: createMockDatasource(),
+ mock: createMockDatasource('a'),
};
datasourceStates = {
@@ -147,9 +147,9 @@ describe('suggestion helpers', () => {
},
};
const multiDatasourceMap = {
- mock: createMockDatasource(),
- mock2: createMockDatasource(),
- mock3: createMockDatasource(),
+ mock: createMockDatasource('a'),
+ mock2: createMockDatasource('a'),
+ mock3: createMockDatasource('a'),
};
const droppedField = {};
getSuggestions({
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx
index 9729d6259f84ac..b146f2467c46cd 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx
@@ -39,7 +39,7 @@ describe('suggestion_panel', () => {
beforeEach(() => {
mockVisualization = createMockVisualization();
- mockDatasource = createMockDatasource();
+ mockDatasource = createMockDatasource('a');
expressionRendererMock = createExpressionRendererMock();
dispatchMock = jest.fn();
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
index 1115126792c861..93f6ea6ea67acb 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx
@@ -373,7 +373,6 @@ function getPreviewExpression(
layerId,
dateRange: frame.dateRange,
state: datasourceState,
- setState: () => {},
});
}
});
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx
index a51091d39f84c8..748e5b876da951 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx
@@ -36,7 +36,7 @@ describe('workspace_panel', () => {
mockVisualization = createMockVisualization();
mockVisualization2 = createMockVisualization();
- mockDatasource = createMockDatasource();
+ mockDatasource = createMockDatasource('a');
expressionRendererMock = createExpressionRendererMock();
});
@@ -199,7 +199,7 @@ describe('workspace_panel', () => {
});
it('should include data fetching for each layer in the expression', () => {
- const mockDatasource2 = createMockDatasource();
+ const mockDatasource2 = createMockDatasource('a');
const framePublicAPI = createMockFramePublicAPI();
framePublicAPI.datasourceLayers = {
first: mockDatasource.publicAPIMock,
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx
index e606c69c8c3867..5d2f68a5567ebd 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx
@@ -33,9 +33,24 @@ export function createMockVisualization(): jest.Mocked {
getPersistableState: jest.fn(_state => _state),
getSuggestions: jest.fn(_options => []),
initialize: jest.fn((_frame, _state?) => ({})),
- renderLayerConfigPanel: jest.fn(),
+ getConfiguration: jest.fn(props => ({
+ groups: [
+ {
+ groupId: 'a',
+ groupLabel: 'a',
+ layerId: 'layer1',
+ supportsMoreColumns: true,
+ accessors: [],
+ filterOperations: jest.fn(() => true),
+ dataTestSubj: 'mockVisA',
+ },
+ ],
+ })),
toExpression: jest.fn((_state, _frame) => null),
toPreviewExpression: jest.fn((_state, _frame) => null),
+
+ setDimension: jest.fn(),
+ removeDimension: jest.fn(),
};
}
@@ -43,12 +58,11 @@ export type DatasourceMock = jest.Mocked & {
publicAPIMock: jest.Mocked;
};
-export function createMockDatasource(): DatasourceMock {
+export function createMockDatasource(id: string): DatasourceMock {
const publicAPIMock: jest.Mocked = {
+ datasourceId: id,
getTableSpec: jest.fn(() => []),
getOperationForColumnId: jest.fn(),
- renderDimensionPanel: jest.fn(),
- renderLayerPanel: jest.fn(),
};
return {
@@ -60,12 +74,19 @@ export function createMockDatasource(): DatasourceMock {
getPublicAPI: jest.fn().mockReturnValue(publicAPIMock),
initialize: jest.fn((_state?) => Promise.resolve()),
renderDataPanel: jest.fn(),
+ renderLayerPanel: jest.fn(),
toExpression: jest.fn((_frame, _state) => null),
insertLayer: jest.fn((_state, _newLayerId) => {}),
removeLayer: jest.fn((_state, _layerId) => {}),
+ removeColumn: jest.fn(props => {}),
getLayers: jest.fn(_state => []),
getMetaData: jest.fn(_state => ({ filterableIndexPatterns: [] })),
+ renderDimensionTrigger: jest.fn(),
+ renderDimensionEditor: jest.fn(),
+ canHandleDrop: jest.fn(),
+ onDrop: jest.fn(),
+
// this is an additional property which doesn't exist on real datasources
// but can be used to validate whether specific API mock functions are called
publicAPIMock,
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx
index 6b9dc88e7ed12b..47fd810bb4c531 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx
@@ -47,7 +47,7 @@ describe('editor_frame service', () => {
pluginSetupDependencies
);
const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies);
- const instance = await publicAPI.createInstance({});
+ const instance = await publicAPI.createInstance();
instance.mount(mountpoint, {
onError: jest.fn(),
onChange: jest.fn(),
@@ -66,7 +66,7 @@ describe('editor_frame service', () => {
pluginSetupDependencies
);
const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies);
- const instance = await publicAPI.createInstance({});
+ const instance = await publicAPI.createInstance();
instance.mount(mountpoint, {
onError: jest.fn(),
onChange: jest.fn(),
diff --git a/x-pack/legacy/plugins/lens/public/index.scss b/x-pack/legacy/plugins/lens/public/index.scss
index 496573f6a1c9a4..2f91d14c397c70 100644
--- a/x-pack/legacy/plugins/lens/public/index.scss
+++ b/x-pack/legacy/plugins/lens/public/index.scss
@@ -4,8 +4,6 @@
@import './variables';
@import './mixins';
-@import './config_panel';
-
@import './app_plugin/index';
@import 'datatable_visualization/index';
@import './drag_drop/index';
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_dimension_panel.scss b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_dimension_panel.scss
deleted file mode 100644
index ddb37505f99851..00000000000000
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_dimension_panel.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.lnsIndexPatternDimensionPanel {
- @include euiFontSizeS;
- background-color: $euiColorEmptyShade;
- border-radius: $euiBorderRadius;
- display: flex;
- align-items: center;
- margin-top: $euiSizeXS;
- overflow: hidden;
-}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss
index 2ce3e11171fc9e..26f805fe735f02 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss
@@ -1,3 +1,2 @@
-@import './dimension_panel';
@import './field_select';
@import './popover';
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss
index 8f26ab91e0f167..07a72ee1f66fce 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss
@@ -1,37 +1,24 @@
-.lnsPopoverEditor {
+.lnsIndexPatternDimensionEditor {
flex-grow: 1;
line-height: 0;
overflow: hidden;
}
-.lnsPopoverEditor__anchor {
- max-width: 100%;
- display: block;
-}
-
-.lnsPopoverEditor__link {
- width: 100%;
- display: flex;
- align-items: center;
- padding: $euiSizeS;
- min-height: $euiSizeXXL;
-}
-
-.lnsPopoverEditor__left,
-.lnsPopoverEditor__right {
+.lnsIndexPatternDimensionEditor__left,
+.lnsIndexPatternDimensionEditor__right {
padding: $euiSizeS;
}
-.lnsPopoverEditor__left {
+.lnsIndexPatternDimensionEditor__left {
padding-top: 0;
background-color: $euiPageBackgroundColor;
}
-.lnsPopoverEditor__right {
+.lnsIndexPatternDimensionEditor__right {
width: $euiSize * 20;
}
-.lnsPopoverEditor__operation {
+.lnsIndexPatternDimensionEditor__operation {
@include euiFontSizeS;
color: $euiColorPrimary;
@@ -41,11 +28,11 @@
}
}
-.lnsPopoverEditor__operation--selected {
+.lnsIndexPatternDimensionEditor__operation--selected {
font-weight: bold;
color: $euiTextColor;
}
-.lnsPopoverEditor__operation--incompatible {
+.lnsIndexPatternDimensionEditor__operation--incompatible {
color: $euiColorMediumShade;
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
index 56f75ae4b17be7..41c317ccab290f 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx
@@ -7,27 +7,28 @@
import { ReactWrapper, ShallowWrapper } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
-import {
- EuiComboBox,
- EuiSideNav,
- EuiSideNavItemType,
- EuiPopover,
- EuiFieldNumber,
-} from '@elastic/eui';
+import { EuiComboBox, EuiSideNav, EuiSideNavItemType, EuiFieldNumber } from '@elastic/eui';
import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public';
import { changeColumn } from '../state_helpers';
import {
- IndexPatternDimensionPanel,
- IndexPatternDimensionPanelComponent,
- IndexPatternDimensionPanelProps,
+ IndexPatternDimensionEditorComponent,
+ IndexPatternDimensionEditorProps,
+ onDrop,
+ canHandleDrop,
} from './dimension_panel';
-import { DropHandler, DragContextState } from '../../drag_drop';
+import { DragContextState } from '../../drag_drop';
import { createMockedDragDropContext } from '../mocks';
import { mountWithIntl as mount, shallowWithIntl as shallow } from 'test_utils/enzyme_helpers';
-import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public';
+import {
+ IUiSettingsClient,
+ SavedObjectsClientContract,
+ HttpSetup,
+ CoreSetup,
+} from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { IndexPatternPrivateState } from '../types';
import { documentField } from '../document_field';
+import { OperationMetadata } from '../../types';
jest.mock('ui/new_platform');
jest.mock('../loader');
@@ -79,20 +80,12 @@ const expectedIndexPatterns = {
},
};
-describe('IndexPatternDimensionPanel', () => {
- let wrapper: ReactWrapper | ShallowWrapper;
+describe('IndexPatternDimensionEditorPanel', () => {
let state: IndexPatternPrivateState;
let setState: jest.Mock;
- let defaultProps: IndexPatternDimensionPanelProps;
+ let defaultProps: IndexPatternDimensionEditorProps;
let dragDropContext: DragContextState;
- function openPopover() {
- wrapper
- .find('[data-test-subj="indexPattern-configure-dimension"]')
- .first()
- .simulate('click');
- }
-
beforeEach(() => {
state = {
indexPatternRefs: [],
@@ -134,7 +127,6 @@ describe('IndexPatternDimensionPanel', () => {
dragDropContext = createMockedDragDropContext();
defaultProps = {
- dragDropContext,
state,
setState,
dateRange: { fromDate: 'now-1d', toDate: 'now' },
@@ -158,475 +150,582 @@ describe('IndexPatternDimensionPanel', () => {
}),
} as unknown) as DataPublicPluginStart['fieldFormats'],
} as unknown) as DataPublicPluginStart,
+ core: {} as CoreSetup,
};
jest.clearAllMocks();
});
- afterEach(() => {
- if (wrapper) {
- wrapper.unmount();
- }
- });
+ describe('Editor component', () => {
+ let wrapper: ReactWrapper | ShallowWrapper;
- it('should display a configure button if dimension has no column yet', () => {
- wrapper = mount( );
- expect(
- wrapper
- .find('[data-test-subj="indexPattern-configure-dimension"]')
- .first()
- .prop('iconType')
- ).toEqual('plusInCircleFilled');
- });
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.unmount();
+ }
+ });
- it('should call the filterOperations function', () => {
- const filterOperations = jest.fn().mockReturnValue(true);
+ it('should call the filterOperations function', () => {
+ const filterOperations = jest.fn().mockReturnValue(true);
- wrapper = shallow(
-
- );
+ wrapper = shallow(
+
+ );
- expect(filterOperations).toBeCalled();
- });
+ expect(filterOperations).toBeCalled();
+ });
- it('should show field select combo box on click', () => {
- wrapper = mount( );
+ it('should show field select combo box on click', () => {
+ wrapper = mount( );
- openPopover();
+ expect(
+ wrapper.find(EuiComboBox).filter('[data-test-subj="indexPattern-dimension-field"]')
+ ).toHaveLength(1);
+ });
- expect(
- wrapper.find(EuiComboBox).filter('[data-test-subj="indexPattern-dimension-field"]')
- ).toHaveLength(1);
- });
+ it('should not show any choices if the filter returns false', () => {
+ wrapper = mount(
+ false}
+ />
+ );
- it('should not show any choices if the filter returns false', () => {
- wrapper = mount(
- false}
- />
- );
+ expect(
+ wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')!
+ .prop('options')!
+ ).toHaveLength(0);
+ });
- openPopover();
+ it('should list all field names and document as a whole in prioritized order', () => {
+ wrapper = mount( );
- expect(
- wrapper
+ const options = wrapper
.find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')!
- .prop('options')!
- ).toHaveLength(0);
- });
-
- it('should list all field names and document as a whole in prioritized order', () => {
- wrapper = mount( );
-
- openPopover();
-
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
- expect(options).toHaveLength(2);
+ expect(options).toHaveLength(2);
- expect(options![0].label).toEqual('Records');
+ expect(options![0].label).toEqual('Records');
- expect(options![1].options!.map(({ label }) => label)).toEqual([
- 'timestamp',
- 'bytes',
- 'memory',
- 'source',
- ]);
- });
+ expect(options![1].options!.map(({ label }) => label)).toEqual([
+ 'timestamp',
+ 'bytes',
+ 'memory',
+ 'source',
+ ]);
+ });
- it('should hide fields that have no data', () => {
- const props = {
- ...defaultProps,
- state: {
- ...defaultProps.state,
- existingFields: {
- 'my-fake-index-pattern': {
- timestamp: true,
- source: true,
+ it('should hide fields that have no data', () => {
+ const props = {
+ ...defaultProps,
+ state: {
+ ...defaultProps.state,
+ existingFields: {
+ 'my-fake-index-pattern': {
+ timestamp: true,
+ source: true,
+ },
},
},
- },
- };
- wrapper = mount( );
-
- openPopover();
-
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
+ };
+ wrapper = mount( );
- expect(options![1].options!.map(({ label }) => label)).toEqual(['timestamp', 'source']);
- });
+ const options = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
- it('should indicate fields which are incompatible for the operation of the current column', () => {
- wrapper = mount(
- label)).toEqual(['timestamp', 'source']);
+ });
- // Private
- operationType: 'max',
- sourceField: 'bytes',
+ it('should indicate fields which are incompatible for the operation of the current column', () => {
+ wrapper = mount(
+
- );
-
- openPopover();
-
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
+ }}
+ />
+ );
- expect(options![0]['data-test-subj']).toEqual('lns-fieldOptionIncompatible-Records');
+ const options = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
- expect(
- options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
- ).toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'memory')[0]['data-test-subj']
- ).not.toContain('Incompatible');
- });
+ expect(options![0]['data-test-subj']).toEqual('lns-fieldOptionIncompatible-Records');
- it('should indicate operations which are incompatible for the field of the current column', () => {
- wrapper = mount(
- label === 'timestamp')[0]['data-test-subj']
+ ).toContain('Incompatible');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'memory')[0]['data-test-subj']
+ ).not.toContain('Incompatible');
+ });
- // Private
- operationType: 'max',
- sourceField: 'bytes',
+ it('should indicate operations which are incompatible for the field of the current column', () => {
+ wrapper = mount(
+
- );
-
- openPopover();
+ }}
+ />
+ );
- interface ItemType {
- name: string;
- 'data-test-subj': string;
- }
- const items: Array> = wrapper.find(EuiSideNav).prop('items');
- const options = (items[0].items as unknown) as ItemType[];
+ interface ItemType {
+ name: string;
+ 'data-test-subj': string;
+ }
+ const items: Array> = wrapper.find(EuiSideNav).prop('items');
+ const options = (items[0].items as unknown) as ItemType[];
- expect(options.find(({ name }) => name === 'Minimum')!['data-test-subj']).not.toContain(
- 'Incompatible'
- );
+ expect(options.find(({ name }) => name === 'Minimum')!['data-test-subj']).not.toContain(
+ 'Incompatible'
+ );
- expect(options.find(({ name }) => name === 'Date histogram')!['data-test-subj']).toContain(
- 'Incompatible'
- );
- });
+ expect(options.find(({ name }) => name === 'Date histogram')!['data-test-subj']).toContain(
+ 'Incompatible'
+ );
+ });
- it('should keep the operation when switching to another field compatible with this operation', () => {
- const initialState: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: {
- label: 'Max of bytes',
- dataType: 'number',
- isBucketed: false,
+ it('should keep the operation when switching to another field compatible with this operation', () => {
+ const initialState: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: {
+ label: 'Max of bytes',
+ dataType: 'number',
+ isBucketed: false,
- // Private
- operationType: 'max',
- sourceField: 'bytes',
- params: { format: { id: 'bytes' } },
+ // Private
+ operationType: 'max',
+ sourceField: 'bytes',
+ params: { format: { id: 'bytes' } },
+ },
},
},
},
- },
- };
-
- wrapper = mount( );
+ };
- openPopover();
+ wrapper = mount(
+
+ );
- const comboBox = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')!;
- const option = comboBox.prop('options')![1].options!.find(({ label }) => label === 'memory')!;
+ const comboBox = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')!;
+ const option = comboBox.prop('options')![1].options!.find(({ label }) => label === 'memory')!;
- act(() => {
- comboBox.prop('onChange')!([option]);
- });
+ act(() => {
+ comboBox.prop('onChange')!([option]);
+ });
- expect(setState).toHaveBeenCalledWith({
- ...initialState,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- operationType: 'max',
- sourceField: 'memory',
- params: { format: { id: 'bytes' } },
- // Other parts of this don't matter for this test
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...initialState,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ operationType: 'max',
+ sourceField: 'memory',
+ params: { format: { id: 'bytes' } },
+ // Other parts of this don't matter for this test
+ }),
+ },
},
},
- },
+ });
});
- });
-
- it('should switch operations when selecting a field that requires another operation', () => {
- wrapper = mount( );
- openPopover();
+ it('should switch operations when selecting a field that requires another operation', () => {
+ wrapper = mount( );
- const comboBox = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')!;
- const option = comboBox.prop('options')![1].options!.find(({ label }) => label === 'source')!;
+ const comboBox = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')!;
+ const option = comboBox.prop('options')![1].options!.find(({ label }) => label === 'source')!;
- act(() => {
- comboBox.prop('onChange')!([option]);
- });
+ act(() => {
+ comboBox.prop('onChange')!([option]);
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- operationType: 'terms',
- sourceField: 'source',
- // Other parts of this don't matter for this test
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ operationType: 'terms',
+ sourceField: 'source',
+ // Other parts of this don't matter for this test
+ }),
+ },
},
},
- },
+ });
});
- });
-
- it('should keep the field when switching to another operation compatible for this field', () => {
- wrapper = mount(
- {
+ wrapper = mount(
+
- );
-
- openPopover();
+ }}
+ />
+ );
- act(() => {
- wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click');
- });
+ act(() => {
+ wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click');
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- operationType: 'min',
- sourceField: 'bytes',
- params: { format: { id: 'bytes' } },
- // Other parts of this don't matter for this test
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ operationType: 'min',
+ sourceField: 'bytes',
+ params: { format: { id: 'bytes' } },
+ // Other parts of this don't matter for this test
+ }),
+ },
},
},
- },
+ });
});
- });
- it('should not set the state if selecting the currently active operation', () => {
- wrapper = mount( );
+ it('should not set the state if selecting the currently active operation', () => {
+ wrapper = mount( );
- openPopover();
+ act(() => {
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimension-date_histogram"]')
+ .simulate('click');
+ });
- act(() => {
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimension-date_histogram"]')
- .simulate('click');
+ expect(setState).not.toHaveBeenCalled();
});
- expect(setState).not.toHaveBeenCalled();
- });
-
- it('should update label on label input changes', () => {
- wrapper = mount( );
+ it('should update label on label input changes', () => {
+ wrapper = mount( );
- openPopover();
-
- act(() => {
- wrapper
- .find('input[data-test-subj="indexPattern-label-edit"]')
- .simulate('change', { target: { value: 'New Label' } });
- });
+ act(() => {
+ wrapper
+ .find('input[data-test-subj="indexPattern-label-edit"]')
+ .simulate('change', { target: { value: 'New Label' } });
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- label: 'New Label',
- // Other parts of this don't matter for this test
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ label: 'New Label',
+ // Other parts of this don't matter for this test
+ }),
+ },
},
},
- },
+ });
});
- });
- describe('transient invalid state', () => {
- it('should not set the state if selecting an operation incompatible with the current field', () => {
- wrapper = mount( );
+ describe('transient invalid state', () => {
+ it('should not set the state if selecting an operation incompatible with the current field', () => {
+ wrapper = mount( );
- openPopover();
+ act(() => {
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
+ .simulate('click');
+ });
+
+ expect(setState).not.toHaveBeenCalled();
+ });
+
+ it('should show error message in invalid state', () => {
+ wrapper = mount( );
- act(() => {
wrapper
.find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
.simulate('click');
+
+ expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).not.toHaveLength(
+ 0
+ );
+
+ expect(setState).not.toHaveBeenCalled();
});
- expect(setState).not.toHaveBeenCalled();
- });
+ it('should leave error state if a compatible operation is selected', () => {
+ wrapper = mount( );
- it('should show error message in invalid state', () => {
- wrapper = mount( );
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
+ .simulate('click');
- openPopover();
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimension-date_histogram"]')
+ .simulate('click');
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
+ expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).toHaveLength(0);
+ });
- expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).not.toHaveLength(0);
+ it('should indicate fields compatible with selected operation', () => {
+ wrapper = mount( );
- expect(setState).not.toHaveBeenCalled();
- });
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
+ .simulate('click');
- it('should leave error state if a compatible operation is selected', () => {
- wrapper = mount( );
+ const options = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
- openPopover();
+ expect(options![0]['data-test-subj']).toContain('Incompatible');
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
+ ).toContain('Incompatible');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'source')[0]['data-test-subj']
+ ).not.toContain('Incompatible');
+ });
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimension-date_histogram"]')
- .simulate('click');
+ it('should select compatible operation if field not compatible with selected operation', () => {
+ wrapper = mount(
+
+ );
- expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).toHaveLength(0);
- });
+ wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
- it('should leave error state if the popover gets closed', () => {
- wrapper = mount( );
+ const comboBox = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]');
+ const options = comboBox.prop('options');
- openPopover();
+ // options[1][2] is a `source` field of type `string` which doesn't support `avg` operation
+ act(() => {
+ comboBox.prop('onChange')!([options![1].options![2]]);
+ });
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col2: expect.objectContaining({
+ sourceField: 'source',
+ operationType: 'terms',
+ // Other parts of this don't matter for this test
+ }),
+ },
+ columnOrder: ['col1', 'col2'],
+ },
+ },
+ });
+ });
- act(() => {
- wrapper.find(EuiPopover).prop('closePopover')!();
+ it('should select the Records field when count is selected', () => {
+ const initialState: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col2: {
+ dataType: 'number',
+ isBucketed: false,
+ label: '',
+ operationType: 'avg',
+ sourceField: 'bytes',
+ },
+ },
+ },
+ },
+ };
+ wrapper = mount(
+
+ );
+
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-count"]')
+ .simulate('click');
+
+ const newColumnState = setState.mock.calls[0][0].layers.first.columns.col2;
+ expect(newColumnState.operationType).toEqual('count');
+ expect(newColumnState.sourceField).toEqual('Records');
});
- openPopover();
+ it('should indicate document and field compatibility with selected document operation', () => {
+ const initialState: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col2: {
+ dataType: 'number',
+ isBucketed: false,
+ label: '',
+ operationType: 'count',
+ sourceField: 'Records',
+ },
+ },
+ },
+ },
+ };
+ wrapper = mount(
+
+ );
+
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
+ .simulate('click');
- expect(wrapper.find('[data-test-subj="indexPattern-invalid-operation"]')).toHaveLength(0);
- });
+ const options = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
- it('should indicate fields compatible with selected operation', () => {
- wrapper = mount( );
+ expect(options![0]['data-test-subj']).toContain('Incompatible');
- openPopover();
+ expect(
+ options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
+ ).toContain('Incompatible');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'source')[0]['data-test-subj']
+ ).not.toContain('Incompatible');
+ });
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
+ it('should set datasource state if compatible field is selected for operation', () => {
+ wrapper = mount( );
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
+ act(() => {
+ wrapper
+ .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
+ .simulate('click');
+ });
- expect(options![0]['data-test-subj']).toContain('Incompatible');
+ const comboBox = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')!;
+ const option = comboBox
+ .prop('options')![1]
+ .options!.find(({ label }) => label === 'source')!;
- expect(
- options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
- ).toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'source')[0]['data-test-subj']
- ).not.toContain('Incompatible');
- });
+ act(() => {
+ comboBox.prop('onChange')!([option]);
+ });
- it('should select compatible operation if field not compatible with selected operation', () => {
- wrapper = mount( );
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ sourceField: 'source',
+ operationType: 'terms',
+ }),
+ },
+ },
+ },
+ });
+ });
+ });
- openPopover();
+ it('should support selecting the operation before the field', () => {
+ wrapper = mount( );
wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
@@ -635,9 +734,8 @@ describe('IndexPatternDimensionPanel', () => {
.filter('[data-test-subj="indexPattern-dimension-field"]');
const options = comboBox.prop('options');
- // options[1][2] is a `source` field of type `string` which doesn't support `avg` operation
act(() => {
- comboBox.prop('onChange')!([options![1].options![2]]);
+ comboBox.prop('onChange')!([options![1].options![0]]);
});
expect(setState).toHaveBeenCalledWith({
@@ -648,8 +746,8 @@ describe('IndexPatternDimensionPanel', () => {
columns: {
...state.layers.first.columns,
col2: expect.objectContaining({
- sourceField: 'source',
- operationType: 'terms',
+ sourceField: 'bytes',
+ operationType: 'avg',
// Other parts of this don't matter for this test
}),
},
@@ -659,41 +757,93 @@ describe('IndexPatternDimensionPanel', () => {
});
});
- it('should select the Records field when count is selected', () => {
- const initialState: IndexPatternPrivateState = {
+ it('should select operation directly if only one field is possible', () => {
+ const initialState = {
+ ...state,
+ indexPatterns: {
+ 1: {
+ ...state.indexPatterns['1'],
+ fields: state.indexPatterns['1'].fields.filter(field => field.name !== 'memory'),
+ },
+ },
+ };
+
+ wrapper = mount(
+
+ );
+
+ wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
+
+ expect(setState).toHaveBeenCalledWith({
+ ...initialState,
+ layers: {
+ first: {
+ ...initialState.layers.first,
+ columns: {
+ ...initialState.layers.first.columns,
+ col2: expect.objectContaining({
+ sourceField: 'bytes',
+ operationType: 'avg',
+ // Other parts of this don't matter for this test
+ }),
+ },
+ columnOrder: ['col1', 'col2'],
+ },
+ },
+ });
+ });
+
+ it('should select operation directly if only document is possible', () => {
+ wrapper = mount( );
+
+ wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click');
+
+ expect(setState).toHaveBeenCalledWith({
...state,
layers: {
first: {
...state.layers.first,
columns: {
...state.layers.first.columns,
- col2: {
- dataType: 'number',
- isBucketed: false,
- label: '',
- operationType: 'avg',
- sourceField: 'bytes',
- },
+ col2: expect.objectContaining({
+ operationType: 'count',
+ // Other parts of this don't matter for this test
+ }),
},
+ columnOrder: ['col1', 'col2'],
},
},
- };
- wrapper = mount(
-
- );
+ });
+ });
- openPopover();
+ it('should indicate compatible fields when selecting the operation first', () => {
+ wrapper = mount( );
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-count"]')
- .simulate('click');
+ wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
- const newColumnState = setState.mock.calls[0][0].layers.first.columns.col2;
- expect(newColumnState.operationType).toEqual('count');
- expect(newColumnState.sourceField).toEqual('Records');
+ const options = wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('options');
+
+ expect(options![0]['data-test-subj']).toContain('Incompatible');
+
+ expect(
+ options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
+ ).toContain('Incompatible');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'bytes')[0]['data-test-subj']
+ ).not.toContain('Incompatible');
+ expect(
+ options![1].options!.filter(({ label }) => label === 'memory')[0]['data-test-subj']
+ ).not.toContain('Incompatible');
});
- it('should indicate document and field compatibility with selected document operation', () => {
+ it('should indicate document compatibility when document operation is selected', () => {
const initialState: IndexPatternPrivateState = {
...state,
layers: {
@@ -713,45 +863,56 @@ describe('IndexPatternDimensionPanel', () => {
},
};
wrapper = mount(
-
+
);
- openPopover();
-
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
-
const options = wrapper
.find(EuiComboBox)
.filter('[data-test-subj="indexPattern-dimension-field"]')
.prop('options');
- expect(options![0]['data-test-subj']).toContain('Incompatible');
+ expect(options![0]['data-test-subj']).not.toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
- ).toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'source')[0]['data-test-subj']
- ).not.toContain('Incompatible');
+ options![1].options!.map(operation =>
+ expect(operation['data-test-subj']).toContain('Incompatible')
+ );
});
- it('should set datasource state if compatible field is selected for operation', () => {
- wrapper = mount( );
+ it('should show all operations that are not filtered out', () => {
+ wrapper = mount(
+ !op.isBucketed && op.dataType === 'number'}
+ />
+ );
- openPopover();
+ interface ItemType {
+ name: React.ReactNode;
+ }
+ const items: Array> = wrapper.find(EuiSideNav).prop('items');
+ const options = (items[0].items as unknown) as ItemType[];
+
+ expect(options.map(({ name }: { name: React.ReactNode }) => name)).toEqual([
+ 'Unique count',
+ 'Average',
+ 'Count',
+ 'Maximum',
+ 'Minimum',
+ 'Sum',
+ ]);
+ });
- act(() => {
- wrapper
- .find('button[data-test-subj="lns-indexPatternDimensionIncompatible-terms"]')
- .simulate('click');
- });
+ it('should add a column on selection of a field', () => {
+ wrapper = mount( );
const comboBox = wrapper
.find(EuiComboBox)
.filter('[data-test-subj="indexPattern-dimension-field"]')!;
- const option = comboBox.prop('options')![1].options!.find(({ label }) => label === 'source')!;
+ const option = comboBox.prop('options')![1].options![0];
act(() => {
comboBox.prop('onChange')!([option]);
@@ -764,479 +925,237 @@ describe('IndexPatternDimensionPanel', () => {
...state.layers.first,
columns: {
...state.layers.first.columns,
- col1: expect.objectContaining({
- sourceField: 'source',
- operationType: 'terms',
+ col2: expect.objectContaining({
+ sourceField: 'bytes',
+ // Other parts of this don't matter for this test
}),
},
+ columnOrder: ['col1', 'col2'],
},
},
});
});
- });
-
- it('should support selecting the operation before the field', () => {
- wrapper = mount( );
-
- openPopover();
-
- wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
-
- const comboBox = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]');
- const options = comboBox.prop('options');
-
- act(() => {
- comboBox.prop('onChange')!([options![1].options![0]]);
- });
-
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col2: expect.objectContaining({
- sourceField: 'bytes',
- operationType: 'avg',
- // Other parts of this don't matter for this test
- }),
- },
- columnOrder: ['col1', 'col2'],
- },
- },
- });
- });
-
- it('should select operation directly if only one field is possible', () => {
- const initialState = {
- ...state,
- indexPatterns: {
- 1: {
- ...state.indexPatterns['1'],
- fields: state.indexPatterns['1'].fields.filter(field => field.name !== 'memory'),
- },
- },
- };
-
- wrapper = mount(
-
- );
-
- openPopover();
-
- wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
-
- expect(setState).toHaveBeenCalledWith({
- ...initialState,
- layers: {
- first: {
- ...initialState.layers.first,
- columns: {
- ...initialState.layers.first.columns,
- col2: expect.objectContaining({
- sourceField: 'bytes',
- operationType: 'avg',
- // Other parts of this don't matter for this test
- }),
- },
- columnOrder: ['col1', 'col2'],
- },
- },
- });
- });
-
- it('should select operation directly if only document is possible', () => {
- wrapper = mount( );
-
- openPopover();
-
- wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click');
-
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col2: expect.objectContaining({
- operationType: 'count',
- // Other parts of this don't matter for this test
- }),
- },
- columnOrder: ['col1', 'col2'],
- },
- },
- });
- });
- it('should indicate compatible fields when selecting the operation first', () => {
- wrapper = mount( );
-
- openPopover();
-
- wrapper.find('button[data-test-subj="lns-indexPatternDimension-avg"]').simulate('click');
-
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
-
- expect(options![0]['data-test-subj']).toContain('Incompatible');
-
- expect(
- options![1].options!.filter(({ label }) => label === 'timestamp')[0]['data-test-subj']
- ).toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'bytes')[0]['data-test-subj']
- ).not.toContain('Incompatible');
- expect(
- options![1].options!.filter(({ label }) => label === 'memory')[0]['data-test-subj']
- ).not.toContain('Incompatible');
- });
-
- it('should indicate document compatibility when document operation is selected', () => {
- const initialState: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col2: {
- dataType: 'number',
- isBucketed: false,
- label: '',
- operationType: 'count',
- sourceField: 'Records',
- },
- },
- },
- },
- };
- wrapper = mount(
-
- );
-
- openPopover();
-
- const options = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('options');
-
- expect(options![0]['data-test-subj']).not.toContain('Incompatible');
-
- options![1].options!.map(operation =>
- expect(operation['data-test-subj']).toContain('Incompatible')
- );
- });
-
- it('should show all operations that are not filtered out', () => {
- wrapper = mount(
- !op.isBucketed && op.dataType === 'number'}
- />
- );
-
- openPopover();
-
- interface ItemType {
- name: React.ReactNode;
- }
- const items: Array> = wrapper.find(EuiSideNav).prop('items');
- const options = (items[0].items as unknown) as ItemType[];
-
- expect(options.map(({ name }: { name: React.ReactNode }) => name)).toEqual([
- 'Unique count',
- 'Average',
- 'Count',
- 'Maximum',
- 'Minimum',
- 'Sum',
- ]);
- });
-
- it('should add a column on selection of a field', () => {
- wrapper = mount( );
-
- openPopover();
-
- const comboBox = wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')!;
- const option = comboBox.prop('options')![1].options![0];
-
- act(() => {
- comboBox.prop('onChange')!([option]);
- });
-
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col2: expect.objectContaining({
- sourceField: 'bytes',
- // Other parts of this don't matter for this test
- }),
- },
- columnOrder: ['col1', 'col2'],
- },
- },
- });
- });
-
- it('should use helper function when changing the function', () => {
- const initialState: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: {
- label: 'Max of bytes',
- dataType: 'number',
- isBucketed: false,
+ it('should use helper function when changing the function', () => {
+ const initialState: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: {
+ label: 'Max of bytes',
+ dataType: 'number',
+ isBucketed: false,
- // Private
- operationType: 'max',
- sourceField: 'bytes',
+ // Private
+ operationType: 'max',
+ sourceField: 'bytes',
+ },
},
},
},
- },
- };
- wrapper = mount( );
-
- openPopover();
-
- act(() => {
- wrapper
- .find('[data-test-subj="lns-indexPatternDimension-min"]')
- .first()
- .prop('onClick')!({} as React.MouseEvent<{}, MouseEvent>);
- });
-
- expect(changeColumn).toHaveBeenCalledWith({
- state: initialState,
- columnId: 'col1',
- layerId: 'first',
- newColumn: expect.objectContaining({
- sourceField: 'bytes',
- operationType: 'min',
- }),
- });
- });
-
- it('should clear the dimension with the clear button', () => {
- wrapper = mount( );
-
- const clearButton = wrapper.find(
- 'EuiButtonIcon[data-test-subj="indexPattern-dimensionPopover-remove"]'
- );
+ };
+ wrapper = mount(
+
+ );
- act(() => {
- clearButton.simulate('click');
- });
+ act(() => {
+ wrapper
+ .find('[data-test-subj="lns-indexPatternDimension-min"]')
+ .first()
+ .prop('onClick')!({} as React.MouseEvent<{}, MouseEvent>);
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- indexPatternId: '1',
- columns: {},
- columnOrder: [],
- },
- },
+ expect(changeColumn).toHaveBeenCalledWith({
+ state: initialState,
+ columnId: 'col1',
+ layerId: 'first',
+ newColumn: expect.objectContaining({
+ sourceField: 'bytes',
+ operationType: 'min',
+ }),
+ });
});
- });
-
- it('should clear the dimension when removing the selection in field combobox', () => {
- wrapper = mount( );
- openPopover();
+ it('should clear the dimension when removing the selection in field combobox', () => {
+ wrapper = mount( );
- act(() => {
- wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-field"]')
- .prop('onChange')!([]);
- });
+ act(() => {
+ wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-field"]')
+ .prop('onChange')!([]);
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- indexPatternId: '1',
- columns: {},
- columnOrder: [],
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ indexPatternId: '1',
+ columns: {},
+ columnOrder: [],
+ },
},
- },
+ });
});
- });
- it('allows custom format', () => {
- const stateWithNumberCol: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- indexPatternId: '1',
- columnOrder: ['col1'],
- columns: {
- col1: {
- label: 'Average of bar',
- dataType: 'number',
- isBucketed: false,
- // Private
- operationType: 'avg',
- sourceField: 'bar',
+ it('allows custom format', () => {
+ const stateWithNumberCol: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ indexPatternId: '1',
+ columnOrder: ['col1'],
+ columns: {
+ col1: {
+ label: 'Average of bar',
+ dataType: 'number',
+ isBucketed: false,
+ // Private
+ operationType: 'avg',
+ sourceField: 'bar',
+ },
},
},
},
- },
- };
-
- wrapper = mount( );
+ };
- openPopover();
+ wrapper = mount(
+
+ );
- act(() => {
- wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-format"]')
- .prop('onChange')!([{ value: 'bytes', label: 'Bytes' }]);
- });
+ act(() => {
+ wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-format"]')
+ .prop('onChange')!([{ value: 'bytes', label: 'Bytes' }]);
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- params: {
- format: { id: 'bytes', params: { decimals: 2 } },
- },
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ params: {
+ format: { id: 'bytes', params: { decimals: 2 } },
+ },
+ }),
+ },
},
},
- },
+ });
});
- });
- it('keeps decimal places while switching', () => {
- const stateWithNumberCol: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- indexPatternId: '1',
- columnOrder: ['col1'],
- columns: {
- col1: {
- label: 'Average of bar',
- dataType: 'number',
- isBucketed: false,
- // Private
- operationType: 'avg',
- sourceField: 'bar',
- params: {
- format: { id: 'bytes', params: { decimals: 0 } },
+ it('keeps decimal places while switching', () => {
+ const stateWithNumberCol: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ indexPatternId: '1',
+ columnOrder: ['col1'],
+ columns: {
+ col1: {
+ label: 'Average of bar',
+ dataType: 'number',
+ isBucketed: false,
+ // Private
+ operationType: 'avg',
+ sourceField: 'bar',
+ params: {
+ format: { id: 'bytes', params: { decimals: 0 } },
+ },
},
},
},
},
- },
- };
+ };
- wrapper = mount( );
+ wrapper = mount(
+
+ );
- openPopover();
+ act(() => {
+ wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-format"]')
+ .prop('onChange')!([{ value: '', label: 'Default' }]);
+ });
- act(() => {
- wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-format"]')
- .prop('onChange')!([{ value: '', label: 'Default' }]);
- });
+ act(() => {
+ wrapper
+ .find(EuiComboBox)
+ .filter('[data-test-subj="indexPattern-dimension-format"]')
+ .prop('onChange')!([{ value: 'number', label: 'Number' }]);
+ });
- act(() => {
- wrapper
- .find(EuiComboBox)
- .filter('[data-test-subj="indexPattern-dimension-format"]')
- .prop('onChange')!([{ value: 'number', label: 'Number' }]);
+ expect(
+ wrapper
+ .find(EuiFieldNumber)
+ .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]')
+ .prop('value')
+ ).toEqual(0);
});
- expect(
- wrapper
- .find(EuiFieldNumber)
- .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]')
- .prop('value')
- ).toEqual(0);
- });
-
- it('allows custom format with number of decimal places', () => {
- const stateWithNumberCol: IndexPatternPrivateState = {
- ...state,
- layers: {
- first: {
- indexPatternId: '1',
- columnOrder: ['col1'],
- columns: {
- col1: {
- label: 'Average of bar',
- dataType: 'number',
- isBucketed: false,
- // Private
- operationType: 'avg',
- sourceField: 'bar',
- params: {
- format: { id: 'bytes', params: { decimals: 2 } },
+ it('allows custom format with number of decimal places', () => {
+ const stateWithNumberCol: IndexPatternPrivateState = {
+ ...state,
+ layers: {
+ first: {
+ indexPatternId: '1',
+ columnOrder: ['col1'],
+ columns: {
+ col1: {
+ label: 'Average of bar',
+ dataType: 'number',
+ isBucketed: false,
+ // Private
+ operationType: 'avg',
+ sourceField: 'bar',
+ params: {
+ format: { id: 'bytes', params: { decimals: 2 } },
+ },
},
},
},
},
- },
- };
-
- wrapper = mount( );
+ };
- openPopover();
+ wrapper = mount(
+
+ );
- act(() => {
- wrapper
- .find(EuiFieldNumber)
- .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]')
- .prop('onChange')!({ target: { value: '0' } });
- });
+ act(() => {
+ wrapper
+ .find(EuiFieldNumber)
+ .filter('[data-test-subj="indexPattern-dimension-formatDecimals"]')
+ .prop('onChange')!({ target: { value: '0' } });
+ });
- expect(setState).toHaveBeenCalledWith({
- ...state,
- layers: {
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: expect.objectContaining({
- params: {
- format: { id: 'bytes', params: { decimals: 0 } },
- },
- }),
+ expect(setState).toHaveBeenCalledWith({
+ ...state,
+ layers: {
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: expect.objectContaining({
+ params: {
+ format: { id: 'bytes', params: { decimals: 0 } },
+ },
+ }),
+ },
},
},
- },
+ });
});
});
- describe('drag and drop', () => {
+ describe('Drag and drop', () => {
function dragDropState(): IndexPatternPrivateState {
return {
indexPatternRefs: [],
@@ -1287,112 +1206,80 @@ describe('IndexPatternDimensionPanel', () => {
}
it('is not droppable if no drag is happening', () => {
- wrapper = mount(
-
- );
-
expect(
- wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('droppable')
- ).toBeFalsy();
+ canHandleDrop({
+ ...defaultProps,
+ dragDropContext,
+ state: dragDropState(),
+ layerId: 'myLayer',
+ })
+ ).toBe(false);
});
it('is not droppable if the dragged item has no field', () => {
- wrapper = shallow(
-
- );
-
- expect(
- wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('droppable')
- ).toBeFalsy();
+ },
+ })
+ ).toBe(false);
});
it('is not droppable if field is not supported by filterOperations', () => {
- wrapper = shallow(
- false}
- layerId="myLayer"
- />
- );
-
- expect(
- wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('droppable')
- ).toBeFalsy();
+ },
+ state: dragDropState(),
+ filterOperations: () => false,
+ layerId: 'myLayer',
+ })
+ ).toBe(false);
});
it('is droppable if the field is supported by filterOperations', () => {
- wrapper = shallow(
- op.dataType === 'number'}
- layerId="myLayer"
- />
- );
-
- expect(
- wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('droppable')
- ).toBeTruthy();
+ },
+ state: dragDropState(),
+ filterOperations: (op: OperationMetadata) => op.dataType === 'number',
+ layerId: 'myLayer',
+ })
+ ).toBe(true);
});
- it('is notdroppable if the field belongs to another index pattern', () => {
- wrapper = shallow(
- {
+ expect(
+ canHandleDrop({
+ ...defaultProps,
+ dragDropContext: {
...dragDropContext,
dragging: {
field: { type: 'number', name: 'bar', aggregatable: true },
indexPatternId: 'foo2',
},
- }}
- state={dragDropState()}
- filterOperations={op => op.dataType === 'number'}
- layerId="myLayer"
- />
- );
-
- expect(
- wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('droppable')
- ).toBeFalsy();
+ },
+ state: dragDropState(),
+ filterOperations: (op: OperationMetadata) => op.dataType === 'number',
+ layerId: 'myLayer',
+ })
+ ).toBe(false);
});
it('appends the dropped column when a field is dropped', () => {
@@ -1401,27 +1288,18 @@ describe('IndexPatternDimensionPanel', () => {
indexPatternId: 'foo',
};
const testState = dragDropState();
- wrapper = shallow(
- op.dataType === 'number'}
- layerId="myLayer"
- />
- );
-
- act(() => {
- const onDrop = wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('onDrop') as DropHandler;
- onDrop(dragging);
+ onDrop({
+ ...defaultProps,
+ dragDropContext: {
+ ...dragDropContext,
+ dragging,
+ },
+ droppedItem: dragging,
+ state: testState,
+ columnId: 'col2',
+ filterOperations: (op: OperationMetadata) => op.dataType === 'number',
+ layerId: 'myLayer',
});
expect(setState).toBeCalledTimes(1);
@@ -1449,27 +1327,17 @@ describe('IndexPatternDimensionPanel', () => {
indexPatternId: 'foo',
};
const testState = dragDropState();
- wrapper = shallow(
- op.isBucketed}
- layerId="myLayer"
- />
- );
-
- act(() => {
- const onDrop = wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('onDrop') as DropHandler;
-
- onDrop(dragging);
+ onDrop({
+ ...defaultProps,
+ dragDropContext: {
+ ...dragDropContext,
+ dragging,
+ },
+ droppedItem: dragging,
+ state: testState,
+ columnId: 'col2',
+ filterOperations: (op: OperationMetadata) => op.isBucketed,
+ layerId: 'myLayer',
});
expect(setState).toBeCalledTimes(1);
@@ -1497,26 +1365,16 @@ describe('IndexPatternDimensionPanel', () => {
indexPatternId: 'foo',
};
const testState = dragDropState();
- wrapper = shallow(
- op.dataType === 'number'}
- layerId="myLayer"
- />
- );
-
- act(() => {
- const onDrop = wrapper
- .find('[data-test-subj="indexPattern-dropTarget"]')
- .first()
- .prop('onDrop') as DropHandler;
-
- onDrop(dragging);
+ onDrop({
+ ...defaultProps,
+ dragDropContext: {
+ ...dragDropContext,
+ dragging,
+ },
+ droppedItem: dragging,
+ state: testState,
+ filterOperations: (op: OperationMetadata) => op.dataType === 'number',
+ layerId: 'myLayer',
});
expect(setState).toBeCalledTimes(1);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx
index 59350ff215c27c..5d87137db3d39e 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx
@@ -5,27 +5,36 @@
*/
import _ from 'lodash';
-import React, { memo, useMemo } from 'react';
-import { EuiButtonIcon } from '@elastic/eui';
+import React, { memo } from 'react';
import { i18n } from '@kbn/i18n';
+import { EuiLink } from '@elastic/eui';
import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
+import {
+ DatasourceDimensionTriggerProps,
+ DatasourceDimensionEditorProps,
+ DatasourceDimensionDropProps,
+ DatasourceDimensionDropHandlerProps,
+} from '../../types';
import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public';
-import { DatasourceDimensionPanelProps, StateSetter } from '../../types';
import { IndexPatternColumn, OperationType } from '../indexpattern';
import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations';
import { PopoverEditor } from './popover_editor';
-import { DragContextState, ChildDragDropProvider, DragDrop } from '../../drag_drop';
-import { changeColumn, deleteColumn } from '../state_helpers';
+import { changeColumn } from '../state_helpers';
import { isDraggedField, hasField } from '../utils';
import { IndexPatternPrivateState, IndexPatternField } from '../types';
import { trackUiEvent } from '../../lens_ui_telemetry';
import { DateRange } from '../../../../../../plugins/lens/common';
-export type IndexPatternDimensionPanelProps = DatasourceDimensionPanelProps & {
- state: IndexPatternPrivateState;
- setState: StateSetter;
- dragDropContext: DragContextState;
+export type IndexPatternDimensionTriggerProps = DatasourceDimensionTriggerProps<
+ IndexPatternPrivateState
+> & {
+ uniqueLabel: string;
+};
+
+export type IndexPatternDimensionEditorProps = DatasourceDimensionEditorProps<
+ IndexPatternPrivateState
+> & {
uiSettings: IUiSettingsClient;
storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
@@ -41,152 +50,181 @@ export interface OperationFieldSupportMatrix {
fieldByOperation: Partial>;
}
-export const IndexPatternDimensionPanelComponent = function IndexPatternDimensionPanel(
- props: IndexPatternDimensionPanelProps
-) {
+type Props = Pick<
+ DatasourceDimensionDropProps,
+ 'layerId' | 'columnId' | 'state' | 'filterOperations'
+>;
+
+// TODO: This code has historically been memoized, as a potentially performance
+// sensitive task. If we can add memoization without breaking the behavior, we should.
+const getOperationFieldSupportMatrix = (props: Props): OperationFieldSupportMatrix => {
const layerId = props.layerId;
const currentIndexPattern = props.state.indexPatterns[props.state.layers[layerId].indexPatternId];
- const operationFieldSupportMatrix = useMemo(() => {
- const filteredOperationsByMetadata = getAvailableOperationsByMetadata(
- currentIndexPattern
- ).filter(operation => props.filterOperations(operation.operationMetaData));
-
- const supportedOperationsByField: Partial> = {};
- const supportedFieldsByOperation: Partial> = {};
-
- filteredOperationsByMetadata.forEach(({ operations }) => {
- operations.forEach(operation => {
- if (supportedOperationsByField[operation.field]) {
- supportedOperationsByField[operation.field]!.push(operation.operationType);
- } else {
- supportedOperationsByField[operation.field] = [operation.operationType];
- }
-
- if (supportedFieldsByOperation[operation.operationType]) {
- supportedFieldsByOperation[operation.operationType]!.push(operation.field);
- } else {
- supportedFieldsByOperation[operation.operationType] = [operation.field];
- }
- });
+ const filteredOperationsByMetadata = getAvailableOperationsByMetadata(
+ currentIndexPattern
+ ).filter(operation => props.filterOperations(operation.operationMetaData));
+
+ const supportedOperationsByField: Partial> = {};
+ const supportedFieldsByOperation: Partial> = {};
+
+ filteredOperationsByMetadata.forEach(({ operations }) => {
+ operations.forEach(operation => {
+ if (supportedOperationsByField[operation.field]) {
+ supportedOperationsByField[operation.field]!.push(operation.operationType);
+ } else {
+ supportedOperationsByField[operation.field] = [operation.operationType];
+ }
+
+ if (supportedFieldsByOperation[operation.operationType]) {
+ supportedFieldsByOperation[operation.operationType]!.push(operation.field);
+ } else {
+ supportedFieldsByOperation[operation.operationType] = [operation.field];
+ }
});
- return {
- operationByField: _.mapValues(supportedOperationsByField, _.uniq),
- fieldByOperation: _.mapValues(supportedFieldsByOperation, _.uniq),
- };
- }, [currentIndexPattern, props.filterOperations]);
+ });
+ return {
+ operationByField: _.mapValues(supportedOperationsByField, _.uniq),
+ fieldByOperation: _.mapValues(supportedFieldsByOperation, _.uniq),
+ };
+};
- const selectedColumn: IndexPatternColumn | null =
- props.state.layers[layerId].columns[props.columnId] || null;
+export function canHandleDrop(props: DatasourceDimensionDropProps) {
+ const operationFieldSupportMatrix = getOperationFieldSupportMatrix(props);
+
+ const { dragging } = props.dragDropContext;
+ const layerIndexPatternId = props.state.layers[props.layerId].indexPatternId;
function hasOperationForField(field: IndexPatternField) {
return Boolean(operationFieldSupportMatrix.operationByField[field.name]);
}
- function canHandleDrop() {
- const { dragging } = props.dragDropContext;
- const layerIndexPatternId = props.state.layers[props.layerId].indexPatternId;
+ return (
+ isDraggedField(dragging) &&
+ layerIndexPatternId === dragging.indexPatternId &&
+ Boolean(hasOperationForField(dragging.field))
+ );
+}
+
+export function onDrop(
+ props: DatasourceDimensionDropHandlerProps
+): boolean {
+ const operationFieldSupportMatrix = getOperationFieldSupportMatrix(props);
+ const droppedItem = props.droppedItem;
+
+ function hasOperationForField(field: IndexPatternField) {
+ return Boolean(operationFieldSupportMatrix.operationByField[field.name]);
+ }
- return (
- isDraggedField(dragging) &&
- layerIndexPatternId === dragging.indexPatternId &&
- Boolean(hasOperationForField(dragging.field))
- );
+ if (!isDraggedField(droppedItem) || !hasOperationForField(droppedItem.field)) {
+ // TODO: What do we do if we couldn't find a column?
+ return false;
}
+ const operationsForNewField =
+ operationFieldSupportMatrix.operationByField[droppedItem.field.name];
+
+ const layerId = props.layerId;
+ const selectedColumn: IndexPatternColumn | null =
+ props.state.layers[layerId].columns[props.columnId] || null;
+ const currentIndexPattern =
+ props.state.indexPatterns[props.state.layers[layerId]?.indexPatternId];
+
+ // We need to check if dragging in a new field, was just a field change on the same
+ // index pattern and on the same operations (therefore checking if the new field supports
+ // our previous operation)
+ const hasFieldChanged =
+ selectedColumn &&
+ hasField(selectedColumn) &&
+ selectedColumn.sourceField !== droppedItem.field.name &&
+ operationsForNewField &&
+ operationsForNewField.includes(selectedColumn.operationType);
+
+ // If only the field has changed use the onFieldChange method on the operation to get the
+ // new column, otherwise use the regular buildColumn to get a new column.
+ const newColumn = hasFieldChanged
+ ? changeField(selectedColumn, currentIndexPattern, droppedItem.field)
+ : buildColumn({
+ op: operationsForNewField ? operationsForNewField[0] : undefined,
+ columns: props.state.layers[props.layerId].columns,
+ indexPattern: currentIndexPattern,
+ layerId,
+ suggestedPriority: props.suggestedPriority,
+ field: droppedItem.field,
+ previousColumn: selectedColumn,
+ });
+
+ trackUiEvent('drop_onto_dimension');
+ const hasData = Object.values(props.state.layers).some(({ columns }) => columns.length);
+ trackUiEvent(hasData ? 'drop_non_empty' : 'drop_empty');
+
+ props.setState(
+ changeColumn({
+ state: props.state,
+ layerId,
+ columnId: props.columnId,
+ newColumn,
+ // If the field has changed, the onFieldChange method needs to take care of everything including moving
+ // over params. If we create a new column above we want changeColumn to move over params.
+ keepParams: !hasFieldChanged,
+ })
+ );
+
+ return true;
+}
+
+export const IndexPatternDimensionTriggerComponent = function IndexPatternDimensionTrigger(
+ props: IndexPatternDimensionTriggerProps
+) {
+ const layerId = props.layerId;
+
+ const selectedColumn: IndexPatternColumn | null =
+ props.state.layers[layerId].columns[props.columnId] || null;
+
+ const { columnId, uniqueLabel } = props;
+ if (!selectedColumn) {
+ return null;
+ }
+ return (
+ {
+ props.togglePopover();
+ }}
+ data-test-subj="lns-dimensionTrigger"
+ aria-label={i18n.translate('xpack.lens.configure.editConfig', {
+ defaultMessage: 'Edit configuration',
+ })}
+ title={i18n.translate('xpack.lens.configure.editConfig', {
+ defaultMessage: 'Edit configuration',
+ })}
+ >
+ {uniqueLabel}
+
+ );
+};
+
+export const IndexPatternDimensionEditorComponent = function IndexPatternDimensionPanel(
+ props: IndexPatternDimensionEditorProps
+) {
+ const layerId = props.layerId;
+ const currentIndexPattern =
+ props.state.indexPatterns[props.state.layers[layerId]?.indexPatternId];
+ const operationFieldSupportMatrix = getOperationFieldSupportMatrix(props);
+
+ const selectedColumn: IndexPatternColumn | null =
+ props.state.layers[layerId].columns[props.columnId] || null;
+
return (
-
- {
- if (!isDraggedField(droppedItem) || !hasOperationForField(droppedItem.field)) {
- // TODO: What do we do if we couldn't find a column?
- return;
- }
-
- const operationsForNewField =
- operationFieldSupportMatrix.operationByField[droppedItem.field.name];
-
- // We need to check if dragging in a new field, was just a field change on the same
- // index pattern and on the same operations (therefore checking if the new field supports
- // our previous operation)
- const hasFieldChanged =
- selectedColumn &&
- hasField(selectedColumn) &&
- selectedColumn.sourceField !== droppedItem.field.name &&
- operationsForNewField &&
- operationsForNewField.includes(selectedColumn.operationType);
-
- // If only the field has changed use the onFieldChange method on the operation to get the
- // new column, otherwise use the regular buildColumn to get a new column.
- const newColumn = hasFieldChanged
- ? changeField(selectedColumn, currentIndexPattern, droppedItem.field)
- : buildColumn({
- op: operationsForNewField ? operationsForNewField[0] : undefined,
- columns: props.state.layers[props.layerId].columns,
- indexPattern: currentIndexPattern,
- layerId,
- suggestedPriority: props.suggestedPriority,
- field: droppedItem.field,
- previousColumn: selectedColumn,
- });
-
- trackUiEvent('drop_onto_dimension');
- const hasData = Object.values(props.state.layers).some(({ columns }) => columns.length);
- trackUiEvent(hasData ? 'drop_non_empty' : 'drop_empty');
-
- props.setState(
- changeColumn({
- state: props.state,
- layerId,
- columnId: props.columnId,
- newColumn,
- // If the field has changed, the onFieldChange method needs to take care of everything including moving
- // over params. If we create a new column above we want changeColumn to move over params.
- keepParams: !hasFieldChanged,
- })
- );
- }}
- >
-
- {selectedColumn && (
- {
- trackUiEvent('indexpattern_dimension_removed');
- props.setState(
- deleteColumn({
- state: props.state,
- layerId,
- columnId: props.columnId,
- })
- );
- if (props.onRemove) {
- props.onRemove(props.columnId);
- }
- }}
- />
- )}
-
-
+
);
};
-export const IndexPatternDimensionPanel = memo(IndexPatternDimensionPanelComponent);
+export const IndexPatternDimensionTrigger = memo(IndexPatternDimensionTriggerComponent);
+export const IndexPatternDimensionEditor = memo(IndexPatternDimensionEditorComponent);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx
index 056a8d177dfe81..e26c338b6e2404 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx
@@ -7,22 +7,18 @@
import _ from 'lodash';
import React, { useState, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
import {
- EuiPopover,
EuiFlexItem,
EuiFlexGroup,
EuiSideNav,
EuiCallOut,
EuiFormRow,
EuiFieldText,
- EuiLink,
- EuiButtonEmpty,
EuiSpacer,
} from '@elastic/eui';
import classNames from 'classnames';
import { IndexPatternColumn, OperationType } from '../indexpattern';
-import { IndexPatternDimensionPanelProps, OperationFieldSupportMatrix } from './dimension_panel';
+import { IndexPatternDimensionEditorProps, OperationFieldSupportMatrix } from './dimension_panel';
import {
operationDefinitionMap,
getOperationDisplay,
@@ -39,7 +35,7 @@ import { FormatSelector } from './format_selector';
const operationPanels = getOperationDisplay();
-export interface PopoverEditorProps extends IndexPatternDimensionPanelProps {
+export interface PopoverEditorProps extends IndexPatternDimensionEditorProps {
selectedColumn?: IndexPatternColumn;
operationFieldSupportMatrix: OperationFieldSupportMatrix;
currentIndexPattern: IndexPattern;
@@ -67,11 +63,9 @@ export function PopoverEditor(props: PopoverEditorProps) {
setState,
layerId,
currentIndexPattern,
- uniqueLabel,
hideGrouping,
} = props;
const { operationByField, fieldByOperation } = operationFieldSupportMatrix;
- const [isPopoverOpen, setPopoverOpen] = useState(false);
const [
incompatibleSelectedOperationType,
setInvalidOperationType,
@@ -115,14 +109,14 @@ export function PopoverEditor(props: PopoverEditorProps) {
items: getOperationTypes().map(({ operationType, compatibleWithCurrentField }) => ({
name: operationPanels[operationType].displayName,
id: operationType as string,
- className: classNames('lnsPopoverEditor__operation', {
- 'lnsPopoverEditor__operation--selected': Boolean(
+ className: classNames('lnsIndexPatternDimensionEditor__operation', {
+ 'lnsIndexPatternDimensionEditor__operation--selected': Boolean(
incompatibleSelectedOperationType === operationType ||
(!incompatibleSelectedOperationType &&
selectedColumn &&
selectedColumn.operationType === operationType)
),
- 'lnsPopoverEditor__operation--incompatible': !compatibleWithCurrentField,
+ 'lnsIndexPatternDimensionEditor__operation--incompatible': !compatibleWithCurrentField,
}),
'data-test-subj': `lns-indexPatternDimension${
compatibleWithCurrentField ? '' : 'Incompatible'
@@ -188,246 +182,193 @@ export function PopoverEditor(props: PopoverEditorProps) {
}
return (
- {
- setPopoverOpen(!isPopoverOpen);
+
+
+
+ {
+ setState(
+ deleteColumn({
+ state,
+ layerId,
+ columnId,
+ })
+ );
}}
- data-test-subj="indexPattern-configure-dimension"
- aria-label={i18n.translate('xpack.lens.configure.editConfig', {
- defaultMessage: 'Edit configuration',
- })}
- title={i18n.translate('xpack.lens.configure.editConfig', {
- defaultMessage: 'Edit configuration',
- })}
- >
- {uniqueLabel}
-
- ) : (
- <>
- setPopoverOpen(!isPopoverOpen)}
- size="xs"
- >
-
-
- >
- )
- }
- isOpen={isPopoverOpen}
- closePopover={() => {
- setPopoverOpen(false);
- setInvalidOperationType(null);
- }}
- anchorPosition="leftUp"
- withTitle
- panelPaddingSize="s"
- >
- {isPopoverOpen && (
-
-
- {
- setState(
- deleteColumn({
- state,
- layerId,
- columnId,
- })
- );
- }}
- onChoose={choice => {
- let column: IndexPatternColumn;
- if (
- !incompatibleSelectedOperationType &&
- selectedColumn &&
- 'field' in choice &&
- choice.operationType === selectedColumn.operationType
- ) {
- // If we just changed the field are not in an error state and the operation didn't change,
- // we use the operations onFieldChange method to calculate the new column.
- column = changeField(selectedColumn, currentIndexPattern, fieldMap[choice.field]);
- } else {
- // Otherwise we'll use the buildColumn method to calculate a new column
- const compatibleOperations =
- ('field' in choice &&
- operationFieldSupportMatrix.operationByField[choice.field]) ||
- [];
- let operation;
- if (compatibleOperations.length > 0) {
- operation =
- incompatibleSelectedOperationType &&
- compatibleOperations.includes(incompatibleSelectedOperationType)
- ? incompatibleSelectedOperationType
- : compatibleOperations[0];
- } else if ('field' in choice) {
- operation = choice.operationType;
- }
- column = buildColumn({
- columns: props.state.layers[props.layerId].columns,
- field: fieldMap[choice.field],
- indexPattern: currentIndexPattern,
- layerId: props.layerId,
- suggestedPriority: props.suggestedPriority,
- op: operation as OperationType,
- previousColumn: selectedColumn,
- });
+ onChoose={choice => {
+ let column: IndexPatternColumn;
+ if (
+ !incompatibleSelectedOperationType &&
+ selectedColumn &&
+ 'field' in choice &&
+ choice.operationType === selectedColumn.operationType
+ ) {
+ // If we just changed the field are not in an error state and the operation didn't change,
+ // we use the operations onFieldChange method to calculate the new column.
+ column = changeField(selectedColumn, currentIndexPattern, fieldMap[choice.field]);
+ } else {
+ // Otherwise we'll use the buildColumn method to calculate a new column
+ const compatibleOperations =
+ ('field' in choice &&
+ operationFieldSupportMatrix.operationByField[choice.field]) ||
+ [];
+ let operation;
+ if (compatibleOperations.length > 0) {
+ operation =
+ incompatibleSelectedOperationType &&
+ compatibleOperations.includes(incompatibleSelectedOperationType)
+ ? incompatibleSelectedOperationType
+ : compatibleOperations[0];
+ } else if ('field' in choice) {
+ operation = choice.operationType;
}
+ column = buildColumn({
+ columns: props.state.layers[props.layerId].columns,
+ field: fieldMap[choice.field],
+ indexPattern: currentIndexPattern,
+ layerId: props.layerId,
+ suggestedPriority: props.suggestedPriority,
+ op: operation as OperationType,
+ previousColumn: selectedColumn,
+ });
+ }
- setState(
- changeColumn({
- state,
- layerId,
- columnId,
- newColumn: column,
- keepParams: false,
- })
- );
- setInvalidOperationType(null);
- }}
- />
-
-
-
-
-
-
-
- {incompatibleSelectedOperationType && selectedColumn && (
-
- )}
- {incompatibleSelectedOperationType && !selectedColumn && (
-
- )}
- {!incompatibleSelectedOperationType && ParamEditor && (
- <>
-
-
- >
- )}
- {!incompatibleSelectedOperationType && selectedColumn && (
-
- {
- setState(
- changeColumn({
- state,
- layerId,
- columnId,
- newColumn: {
- ...selectedColumn,
- label: e.target.value,
- },
- })
- );
- }}
- />
-
- )}
-
- {!hideGrouping && (
- {
- setState({
- ...state,
- layers: {
- ...state.layers,
- [props.layerId]: {
- ...state.layers[props.layerId],
- columnOrder,
- },
- },
- });
- }}
+ setState(
+ changeColumn({
+ state,
+ layerId,
+ columnId,
+ newColumn: column,
+ keepParams: false,
+ })
+ );
+ setInvalidOperationType(null);
+ }}
+ />
+
+
+
+
+
+
+
+ {incompatibleSelectedOperationType && selectedColumn && (
+
+ )}
+ {incompatibleSelectedOperationType && !selectedColumn && (
+
+ )}
+ {!incompatibleSelectedOperationType && ParamEditor && (
+ <>
+
- )}
-
- {selectedColumn && selectedColumn.dataType === 'number' ? (
- {
+
+ >
+ )}
+ {!incompatibleSelectedOperationType && selectedColumn && (
+
+ {
setState(
- updateColumnParam({
+ changeColumn({
state,
layerId,
- currentColumn: selectedColumn,
- paramName: 'format',
- value: newFormat,
+ columnId,
+ newColumn: {
+ ...selectedColumn,
+ label: e.target.value,
+ },
})
);
}}
/>
- ) : null}
-
-
-
-
- )}
-
+
+ )}
+
+ {!hideGrouping && (
+ {
+ setState({
+ ...state,
+ layers: {
+ ...state.layers,
+ [props.layerId]: {
+ ...state.layers[props.layerId],
+ columnOrder,
+ },
+ },
+ });
+ }}
+ />
+ )}
+
+ {selectedColumn && selectedColumn.dataType === 'number' ? (
+ {
+ setState(
+ updateColumnParam({
+ state,
+ layerId,
+ currentColumn: selectedColumn,
+ paramName: 'format',
+ value: newFormat,
+ })
+ );
+ }}
+ />
+ ) : null}
+
+
+
+
+
);
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts
index 25121eec30f2a9..76e59a170a9e93 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts
@@ -408,7 +408,6 @@ describe('IndexPattern Data Source', () => {
const initialState = stateFromPersistedState(persistedState);
publicAPI = indexPatternDatasource.getPublicAPI({
state: initialState,
- setState: () => {},
layerId: 'first',
dateRange: {
fromDate: 'now-30d',
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
index 00f52d6a1747f7..9c2a9c9bf4a091 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx
@@ -12,7 +12,8 @@ import { CoreStart } from 'src/core/public';
import { i18n } from '@kbn/i18n';
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import {
- DatasourceDimensionPanelProps,
+ DatasourceDimensionEditorProps,
+ DatasourceDimensionTriggerProps,
DatasourceDataPanelProps,
Operation,
DatasourceLayerPanelProps,
@@ -20,7 +21,12 @@ import {
} from '../types';
import { loadInitialState, changeIndexPattern, changeLayerIndexPattern } from './loader';
import { toExpression } from './to_expression';
-import { IndexPatternDimensionPanel } from './dimension_panel';
+import {
+ IndexPatternDimensionTrigger,
+ IndexPatternDimensionEditor,
+ canHandleDrop,
+ onDrop,
+} from './dimension_panel';
import { IndexPatternDataPanel } from './datapanel';
import {
getDatasourceSuggestionsForField,
@@ -38,6 +44,7 @@ import {
} from './types';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { Plugin as DataPlugin } from '../../../../../../src/plugins/data/public';
+import { deleteColumn } from './state_helpers';
import { Datasource, StateSetter } from '..';
export { OperationType, IndexPatternColumn } from './operations';
@@ -80,6 +87,9 @@ export function uniqueLabels(layers: Record) {
};
Object.values(layers).forEach(layer => {
+ if (!layer.columns) {
+ return;
+ }
Object.entries(layer.columns).forEach(([columnId, column]) => {
columnLabelMap[columnId] = makeUnique(column.label);
});
@@ -156,6 +166,14 @@ export function getIndexPatternDatasource({
return Object.keys(state.layers);
},
+ removeColumn({ prevState, layerId, columnId }) {
+ return deleteColumn({
+ state: prevState,
+ layerId,
+ columnId,
+ });
+ },
+
toExpression,
getMetaData(state: IndexPatternPrivateState) {
@@ -198,15 +216,97 @@ export function getIndexPatternDatasource({
);
},
- getPublicAPI({
- state,
- setState,
- layerId,
- dateRange,
- }: PublicAPIProps) {
+ renderDimensionTrigger: (
+ domElement: Element,
+ props: DatasourceDimensionTriggerProps
+ ) => {
+ const columnLabelMap = uniqueLabels(props.state.layers);
+
+ render(
+
+
+
+
+ ,
+ domElement
+ );
+ },
+
+ renderDimensionEditor: (
+ domElement: Element,
+ props: DatasourceDimensionEditorProps
+ ) => {
+ const columnLabelMap = uniqueLabels(props.state.layers);
+
+ render(
+
+
+
+
+ ,
+ domElement
+ );
+ },
+
+ renderLayerPanel: (
+ domElement: Element,
+ props: DatasourceLayerPanelProps
+ ) => {
+ render(
+ {
+ changeLayerIndexPattern({
+ savedObjectsClient,
+ indexPatternId,
+ setState: props.setState,
+ state: props.state,
+ layerId: props.layerId,
+ onError: onIndexPatternLoadError,
+ replaceIfPossible: true,
+ });
+ }}
+ {...props}
+ />,
+ domElement
+ );
+ },
+
+ canHandleDrop,
+ onDrop,
+
+ getPublicAPI({ state, layerId }: PublicAPIProps) {
const columnLabelMap = uniqueLabels(state.layers);
return {
+ datasourceId: 'indexpattern',
+
getTableSpec: () => {
return state.layers[layerId].columnOrder.map(colId => ({ columnId: colId }));
},
@@ -218,58 +318,6 @@ export function getIndexPatternDatasource({
}
return null;
},
- renderDimensionPanel: (domElement: Element, props: DatasourceDimensionPanelProps) => {
- render(
-
-
-
-
- ,
- domElement
- );
- },
-
- renderLayerPanel: (domElement: Element, props: DatasourceLayerPanelProps) => {
- render(
- {
- changeLayerIndexPattern({
- savedObjectsClient,
- indexPatternId,
- setState,
- state,
- layerId: props.layerId,
- onError: onIndexPatternLoadError,
- replaceIfPossible: true,
- });
- }}
- {...props}
- />,
- domElement
- );
- },
};
},
getDatasourceSuggestionsForField(state, draggedField) {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx
index af7afb9cf9342a..219a6d935e436d 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx
@@ -178,6 +178,7 @@ describe('Layer Data Panel', () => {
defaultProps = {
layerId: 'first',
state: initialState,
+ setState: jest.fn(),
onChangeIndexPattern: jest.fn(async () => {}),
};
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx
index ae346ecc72cbce..eea00d52a77f95 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx
@@ -11,7 +11,8 @@ import { DatasourceLayerPanelProps } from '../types';
import { IndexPatternPrivateState } from './types';
import { ChangeIndexPattern } from './change_indexpattern';
-export interface IndexPatternLayerPanelProps extends DatasourceLayerPanelProps {
+export interface IndexPatternLayerPanelProps
+ extends DatasourceLayerPanelProps {
state: IndexPatternPrivateState;
onChangeIndexPattern: (newId: string) => void;
}
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.test.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.test.tsx
deleted file mode 100644
index eac35f82a50fa0..00000000000000
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.test.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import { ReactWrapper } from 'enzyme';
-import { mountWithIntl as mount } from 'test_utils/enzyme_helpers';
-import { MetricConfigPanel } from './metric_config_panel';
-import { DatasourceDimensionPanelProps, Operation, DatasourcePublicAPI } from '../types';
-import { State } from './types';
-import { NativeRendererProps } from '../native_renderer';
-import { createMockFramePublicAPI, createMockDatasource } from '../editor_frame_service/mocks';
-
-describe('MetricConfigPanel', () => {
- const dragDropContext = { dragging: undefined, setDragging: jest.fn() };
-
- function mockDatasource(): DatasourcePublicAPI {
- return createMockDatasource().publicAPIMock;
- }
-
- function testState(): State {
- return {
- accessor: 'foo',
- layerId: 'bar',
- };
- }
-
- function testSubj(component: ReactWrapper, subj: string) {
- return component
- .find(`[data-test-subj="${subj}"]`)
- .first()
- .props();
- }
-
- test('the value dimension panel only accepts singular numeric operations', () => {
- const state = testState();
- const component = mount(
-
- );
-
- const panel = testSubj(component, 'lns_metric_valueDimensionPanel');
- const nativeProps = (panel as NativeRendererProps).nativeProps;
- const { columnId, filterOperations } = nativeProps;
- const exampleOperation: Operation = {
- dataType: 'number',
- isBucketed: false,
- label: 'bar',
- };
- const ops: Operation[] = [
- { ...exampleOperation, dataType: 'number' },
- { ...exampleOperation, dataType: 'string' },
- { ...exampleOperation, dataType: 'boolean' },
- { ...exampleOperation, dataType: 'date' },
- ];
- expect(columnId).toEqual('shazm');
- expect(ops.filter(filterOperations)).toEqual([{ ...exampleOperation, dataType: 'number' }]);
- });
-});
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.tsx
deleted file mode 100644
index 16e24f247fb684..00000000000000
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_config_panel.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import { i18n } from '@kbn/i18n';
-import { EuiFormRow } from '@elastic/eui';
-import { State } from './types';
-import { VisualizationLayerConfigProps, OperationMetadata } from '../types';
-import { NativeRenderer } from '../native_renderer';
-
-const isMetric = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number';
-
-export function MetricConfigPanel(props: VisualizationLayerConfigProps) {
- const { state, frame, layerId } = props;
- const datasource = frame.datasourceLayers[layerId];
-
- return (
-
-
-
- );
-}
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx
index 66ed963002f590..4d979a766cd2b9 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx
@@ -91,6 +91,11 @@ export function MetricChart({
const { title, accessor, mode } = args;
let value = '-';
const firstTable = Object.values(data.tables)[0];
+ if (!accessor) {
+ return (
+
+ );
+ }
if (firstTable) {
const column = firstTable.columns[0];
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts
index 88964b95c2ac7e..276f24433c6708 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts
@@ -24,8 +24,8 @@ function mockFrame(): FramePublicAPI {
...createMockFramePublicAPI(),
addNewLayer: () => 'l42',
datasourceLayers: {
- l1: createMockDatasource().publicAPIMock,
- l42: createMockDatasource().publicAPIMock,
+ l1: createMockDatasource('l1').publicAPIMock,
+ l42: createMockDatasource('l42').publicAPIMock,
},
};
}
@@ -36,10 +36,10 @@ describe('metric_visualization', () => {
(generateId as jest.Mock).mockReturnValueOnce('test-id1');
const initialState = metricVisualization.initialize(mockFrame());
- expect(initialState.accessor).toBeDefined();
+ expect(initialState.accessor).not.toBeDefined();
expect(initialState).toMatchInlineSnapshot(`
Object {
- "accessor": "test-id1",
+ "accessor": undefined,
"layerId": "l42",
}
`);
@@ -60,7 +60,7 @@ describe('metric_visualization', () => {
it('returns a clean layer', () => {
(generateId as jest.Mock).mockReturnValueOnce('test-id1');
expect(metricVisualization.clearLayer(exampleState(), 'l1')).toEqual({
- accessor: 'test-id1',
+ accessor: undefined,
layerId: 'l1',
});
});
@@ -72,10 +72,47 @@ describe('metric_visualization', () => {
});
});
+ describe('#setDimension', () => {
+ it('sets the accessor', () => {
+ expect(
+ metricVisualization.setDimension({
+ prevState: {
+ accessor: undefined,
+ layerId: 'l1',
+ },
+ layerId: 'l1',
+ groupId: '',
+ columnId: 'newDimension',
+ })
+ ).toEqual({
+ accessor: 'newDimension',
+ layerId: 'l1',
+ });
+ });
+ });
+
+ describe('#removeDimension', () => {
+ it('removes the accessor', () => {
+ expect(
+ metricVisualization.removeDimension({
+ prevState: {
+ accessor: 'a',
+ layerId: 'l1',
+ },
+ layerId: 'l1',
+ columnId: 'a',
+ })
+ ).toEqual({
+ accessor: undefined,
+ layerId: 'l1',
+ });
+ });
+ });
+
describe('#toExpression', () => {
it('should map to a valid AST', () => {
const datasource: DatasourcePublicAPI = {
- ...createMockDatasource().publicAPIMock,
+ ...createMockDatasource('l1').publicAPIMock,
getOperationForColumnId(_: string) {
return {
id: 'a',
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx
index 6714c057878373..44256df5aed6d4 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx
@@ -4,23 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
-import { render } from 'react-dom';
-import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { Ast } from '@kbn/interpreter/target/common';
import { getSuggestions } from './metric_suggestions';
-import { MetricConfigPanel } from './metric_config_panel';
-import { Visualization, FramePublicAPI } from '../types';
+import { Visualization, FramePublicAPI, OperationMetadata } from '../types';
import { State, PersistableState } from './types';
-import { generateId } from '../id_generator';
import chartMetricSVG from '../assets/chart_metric.svg';
const toExpression = (
state: State,
frame: FramePublicAPI,
mode: 'reduced' | 'full' = 'full'
-): Ast => {
+): Ast | null => {
+ if (!state.accessor) {
+ return null;
+ }
+
const [datasource] = Object.values(frame.datasourceLayers);
const operation = datasource && datasource.getOperationForColumnId(state.accessor);
@@ -57,7 +56,7 @@ export const metricVisualization: Visualization = {
clearLayer(state) {
return {
...state,
- accessor: generateId(),
+ accessor: undefined,
};
},
@@ -80,22 +79,37 @@ export const metricVisualization: Visualization = {
return (
state || {
layerId: frame.addNewLayer(),
- accessor: generateId(),
+ accessor: undefined,
}
);
},
getPersistableState: state => state,
- renderLayerConfigPanel: (domElement, props) =>
- render(
-
-
- ,
- domElement
- ),
+ getConfiguration(props) {
+ return {
+ groups: [
+ {
+ groupId: 'metric',
+ groupLabel: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric' }),
+ layerId: props.state.layerId,
+ accessors: props.state.accessor ? [props.state.accessor] : [],
+ supportsMoreColumns: false,
+ filterOperations: (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number',
+ },
+ ],
+ };
+ },
toExpression,
toPreviewExpression: (state: State, frame: FramePublicAPI) =>
toExpression(state, frame, 'reduced'),
+
+ setDimension({ prevState, columnId }) {
+ return { ...prevState, accessor: columnId };
+ },
+
+ removeDimension({ prevState }) {
+ return { ...prevState, accessor: undefined };
+ },
};
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/types.ts b/x-pack/legacy/plugins/lens/public/metric_visualization/types.ts
index 6348d80b15e2f3..53fc1039342558 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization/types.ts
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization/types.ts
@@ -6,7 +6,7 @@
export interface State {
layerId: string;
- accessor: string;
+ accessor?: string;
}
export interface MetricConfig extends State {
diff --git a/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.test.tsx b/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.test.tsx
deleted file mode 100644
index 38f48c9cdaf727..00000000000000
--- a/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.test.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import { createMockDatasource } from '../editor_frame_service/mocks';
-import { MultiColumnEditor } from './multi_column_editor';
-import { mount } from 'enzyme';
-
-jest.useFakeTimers();
-
-describe('MultiColumnEditor', () => {
- it('should add a trailing accessor if the accessor list is empty', () => {
- const onAdd = jest.fn();
- mount(
- true}
- layerId="foo"
- onAdd={onAdd}
- onRemove={jest.fn()}
- testSubj="bar"
- />
- );
-
- expect(onAdd).toHaveBeenCalledTimes(0);
-
- jest.runAllTimers();
-
- expect(onAdd).toHaveBeenCalledTimes(1);
- });
-
- it('should add a trailing accessor if the last accessor is configured', () => {
- const onAdd = jest.fn();
- mount(
- true}
- layerId="foo"
- onAdd={onAdd}
- onRemove={jest.fn()}
- testSubj="bar"
- />
- );
-
- expect(onAdd).toHaveBeenCalledTimes(0);
-
- jest.runAllTimers();
-
- expect(onAdd).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.tsx b/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.tsx
deleted file mode 100644
index 422f1dcf60f3c4..00000000000000
--- a/x-pack/legacy/plugins/lens/public/multi_column_editor/multi_column_editor.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React, { useEffect } from 'react';
-import { NativeRenderer } from '../native_renderer';
-import { DatasourcePublicAPI, OperationMetadata } from '../types';
-import { DragContextState } from '../drag_drop';
-
-interface Props {
- accessors: string[];
- datasource: DatasourcePublicAPI;
- dragDropContext: DragContextState;
- onRemove: (accessor: string) => void;
- onAdd: () => void;
- filterOperations: (op: OperationMetadata) => boolean;
- suggestedPriority?: 0 | 1 | 2 | undefined;
- testSubj: string;
- layerId: string;
-}
-
-export function MultiColumnEditor({
- accessors,
- datasource,
- dragDropContext,
- onRemove,
- onAdd,
- filterOperations,
- suggestedPriority,
- testSubj,
- layerId,
-}: Props) {
- const lastOperation = datasource.getOperationForColumnId(accessors[accessors.length - 1]);
-
- useEffect(() => {
- if (accessors.length === 0 || lastOperation !== null) {
- setTimeout(onAdd);
- }
- }, [lastOperation]);
-
- return (
- <>
- {accessors.map(accessor => (
-
-
-
- ))}
- >
- );
-}
diff --git a/x-pack/legacy/plugins/lens/public/plugin.tsx b/x-pack/legacy/plugins/lens/public/plugin.tsx
index cc029fee49d1d8..c74653c70703c0 100644
--- a/x-pack/legacy/plugins/lens/public/plugin.tsx
+++ b/x-pack/legacy/plugins/lens/public/plugin.tsx
@@ -114,7 +114,7 @@ export class LensPlugin {
const savedObjectsClient = coreStart.savedObjects.client;
addHelpMenuToAppChrome(coreStart.chrome);
- const instance = await this.createEditorFrame!({});
+ const instance = await this.createEditorFrame!();
setReportManager(
new LensReportManager({
diff --git a/x-pack/legacy/plugins/lens/public/types.ts b/x-pack/legacy/plugins/lens/public/types.ts
index b7983eeb8dbb8b..c897979b06cfb6 100644
--- a/x-pack/legacy/plugins/lens/public/types.ts
+++ b/x-pack/legacy/plugins/lens/public/types.ts
@@ -13,14 +13,10 @@ import { Document } from './persistence';
import { DateRange } from '../../../../plugins/lens/common';
import { Query, Filter, SavedQuery } from '../../../../../src/plugins/data/public';
-// eslint-disable-next-line
-export interface EditorFrameOptions {}
-
export type ErrorCallback = (e: { message: string }) => void;
export interface PublicAPIProps {
state: T;
- setState: StateSetter;
layerId: string;
dateRange: DateRange;
}
@@ -34,6 +30,7 @@ export interface EditorFrameProps {
savedQuery?: SavedQuery;
// Frame loader (app or embeddable) is expected to call this when it loads and updates
+ // This should be replaced with a top-down state
onChange: (newState: {
filterableIndexPatterns: DatasourceMetaData['filterableIndexPatterns'];
doc: Document;
@@ -53,7 +50,7 @@ export interface EditorFrameSetup {
}
export interface EditorFrameStart {
- createInstance: (options: EditorFrameOptions) => Promise;
+ createInstance: () => Promise;
}
// Hints the default nesting to the data source. 0 is the highest priority
@@ -138,8 +135,14 @@ export interface Datasource {
removeLayer: (state: T, layerId: string) => T;
clearLayer: (state: T, layerId: string) => T;
getLayers: (state: T) => string[];
+ removeColumn: (props: { prevState: T; layerId: string; columnId: string }) => T;
renderDataPanel: (domElement: Element, props: DatasourceDataPanelProps) => void;
+ renderDimensionTrigger: (domElement: Element, props: DatasourceDimensionTriggerProps) => void;
+ renderDimensionEditor: (domElement: Element, props: DatasourceDimensionEditorProps) => void;
+ renderLayerPanel: (domElement: Element, props: DatasourceLayerPanelProps) => void;
+ canHandleDrop: (props: DatasourceDimensionDropProps) => boolean;
+ onDrop: (props: DatasourceDimensionDropHandlerProps) => boolean;
toExpression: (state: T, layerId: string) => Ast | string | null;
@@ -155,22 +158,11 @@ export interface Datasource {
* This is an API provided to visualizations by the frame, which calls the publicAPI on the datasource
*/
export interface DatasourcePublicAPI {
- getTableSpec: () => TableSpec;
+ datasourceId: string;
+ getTableSpec: () => Array<{ columnId: string }>;
getOperationForColumnId: (columnId: string) => Operation | null;
-
- // Render can be called many times
- renderDimensionPanel: (domElement: Element, props: DatasourceDimensionPanelProps) => void;
- renderLayerPanel: (domElement: Element, props: DatasourceLayerPanelProps) => void;
}
-export interface TableSpecColumn {
- // Column IDs are the keys for internal state in data sources and visualizations
- columnId: string;
-}
-
-// TableSpec is managed by visualizations
-export type TableSpec = TableSpecColumn[];
-
export interface DatasourceDataPanelProps {
state: T;
dragDropContext: DragContextState;
@@ -181,31 +173,61 @@ export interface DatasourceDataPanelProps {
filters: Filter[];
}
-// The only way a visualization has to restrict the query building
-export interface DatasourceDimensionPanelProps {
- layerId: string;
- columnId: string;
-
- dragDropContext: DragContextState;
-
- // Visualizations can restrict operations based on their own rules
+interface SharedDimensionProps {
+ /** Visualizations can restrict operations based on their own rules.
+ * For example, limiting to only bucketed or only numeric operations.
+ */
filterOperations: (operation: OperationMetadata) => boolean;
- // Visualizations can hint at the role this dimension would play, which
- // affects the default ordering of the query
+ /** Visualizations can hint at the role this dimension would play, which
+ * affects the default ordering of the query
+ */
suggestedPriority?: DimensionPriority;
- onRemove?: (accessor: string) => void;
- // Some dimension editors will allow users to change the operation grouping
- // from the panel, and this lets the visualization hint that it doesn't want
- // users to have that level of control
+ /** Some dimension editors will allow users to change the operation grouping
+ * from the panel, and this lets the visualization hint that it doesn't want
+ * users to have that level of control
+ */
hideGrouping?: boolean;
}
-export interface DatasourceLayerPanelProps {
+export type DatasourceDimensionProps = SharedDimensionProps & {
layerId: string;
+ columnId: string;
+ onRemove?: (accessor: string) => void;
+ state: T;
+};
+
+// The only way a visualization has to restrict the query building
+export type DatasourceDimensionEditorProps = DatasourceDimensionProps & {
+ setState: StateSetter;
+ core: Pick;
+ dateRange: DateRange;
+};
+
+export type DatasourceDimensionTriggerProps = DatasourceDimensionProps & {
+ dragDropContext: DragContextState;
+ togglePopover: () => void;
+};
+
+export interface DatasourceLayerPanelProps {
+ layerId: string;
+ state: T;
+ setState: StateSetter;
}
+export type DatasourceDimensionDropProps = SharedDimensionProps & {
+ layerId: string;
+ columnId: string;
+ state: T;
+ setState: StateSetter;
+ dragDropContext: DragContextState;
+};
+
+export type DatasourceDimensionDropHandlerProps = DatasourceDimensionDropProps & {
+ droppedItem: unknown;
+};
+
export type DataType = 'document' | 'string' | 'number' | 'date' | 'boolean' | 'ip';
// An operation represents a column in a table, not any information
@@ -239,12 +261,32 @@ export interface LensMultiTable {
};
}
-export interface VisualizationLayerConfigProps {
+export interface VisualizationConfigProps {
layerId: string;
- dragDropContext: DragContextState;
frame: FramePublicAPI;
state: T;
+}
+
+export type VisualizationLayerWidgetProps = VisualizationConfigProps & {
setState: (newState: T) => void;
+};
+
+type VisualizationDimensionGroupConfig = SharedDimensionProps & {
+ groupLabel: string;
+
+ /** ID is passed back to visualization. For example, `x` */
+ groupId: string;
+ accessors: string[];
+ supportsMoreColumns: boolean;
+ /** If required, a warning will appear if accessors are empty */
+ required?: boolean;
+ dataTestSubj?: string;
+};
+
+interface VisualizationDimensionChangeProps {
+ layerId: string;
+ columnId: string;
+ prevState: T;
}
/**
@@ -329,16 +371,18 @@ export interface Visualization {
visualizationTypes: VisualizationType[];
getLayerIds: (state: T) => string[];
-
clearLayer: (state: T, layerId: string) => T;
-
removeLayer?: (state: T, layerId: string) => T;
-
appendLayer?: (state: T, layerId: string) => T;
+ // Layer context menu is used by visualizations for styling the entire layer
+ // For example, the XY visualization uses this to have multiple chart types
getLayerContextMenuIcon?: (opts: { state: T; layerId: string }) => IconType | undefined;
+ renderLayerContextMenu?: (domElement: Element, props: VisualizationLayerWidgetProps) => void;
- renderLayerContextMenu?: (domElement: Element, props: VisualizationLayerConfigProps) => void;
+ getConfiguration: (
+ props: VisualizationConfigProps
+ ) => { groups: VisualizationDimensionGroupConfig[] };
getDescription: (
state: T
@@ -354,7 +398,13 @@ export interface Visualization {
getPersistableState: (state: T) => P;
- renderLayerConfigPanel: (domElement: Element, props: VisualizationLayerConfigProps) => void;
+ // Actions triggered by the frame which tell the datasource that a dimension is being changed
+ setDimension: (
+ props: VisualizationDimensionChangeProps & {
+ groupId: string;
+ }
+ ) => T;
+ removeDimension: (props: VisualizationDimensionChangeProps) => T;
toExpression: (state: T, frame: FramePublicAPI) => Ast | string | null;
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_visualization.test.ts.snap b/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
similarity index 96%
rename from x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_visualization.test.ts.snap
rename to x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
index 76af8328673add..6b68679bfd4ec0 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_visualization.test.ts.snap
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`xy_visualization #toExpression should map to a valid AST 1`] = `
+exports[`#toExpression should map to a valid AST 1`] = `
Object {
"chain": Array [
Object {
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.test.ts
new file mode 100644
index 00000000000000..6bc379ea33bca1
--- /dev/null
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.test.ts
@@ -0,0 +1,133 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 { Ast } from '@kbn/interpreter/target/common';
+import { Position } from '@elastic/charts';
+import { xyVisualization } from './xy_visualization';
+import { Operation } from '../types';
+import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks';
+
+describe('#toExpression', () => {
+ let mockDatasource: ReturnType