diff --git a/x-pack/plugins/maps/public/components/geometry_filter_form.js b/x-pack/plugins/maps/public/components/geometry_filter_form.js
index d5cdda3c1c324..fde07e8c16bc5 100644
--- a/x-pack/plugins/maps/public/components/geometry_filter_form.js
+++ b/x-pack/plugins/maps/public/components/geometry_filter_form.js
@@ -20,11 +20,15 @@ import { i18n } from '@kbn/i18n';
import { ES_GEO_FIELD_TYPE, ES_SPATIAL_RELATIONS } from '../../common/constants';
import { getEsSpatialRelationLabel } from '../../common/i18n_getters';
import { MultiIndexGeoFieldSelect } from './multi_index_geo_field_select';
+import { ActionSelect } from './action_select';
+import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../src/plugins/data/public';
export class GeometryFilterForm extends Component {
static propTypes = {
buttonLabel: PropTypes.string.isRequired,
geoFields: PropTypes.array.isRequired,
+ getFilterActions: PropTypes.func,
+ getActionContext: PropTypes.func,
intitialGeometryLabel: PropTypes.string.isRequired,
onSubmit: PropTypes.func.isRequired,
isFilterGeometryClosed: PropTypes.bool,
@@ -36,6 +40,7 @@ export class GeometryFilterForm extends Component {
};
state = {
+ actionId: ACTION_GLOBAL_APPLY_FILTER,
selectedField: this.props.geoFields.length ? this.props.geoFields[0] : undefined,
geometryLabel: this.props.intitialGeometryLabel,
relation: ES_SPATIAL_RELATIONS.INTERSECTS,
@@ -57,8 +62,13 @@ export class GeometryFilterForm extends Component {
});
};
+ _onActionIdChange = (value) => {
+ this.setState({ actionId: value });
+ };
+
_onSubmit = () => {
this.props.onSubmit({
+ actionId: this.state.actionId,
geometryLabel: this.state.geometryLabel,
indexPatternId: this.state.selectedField.indexPatternId,
geoFieldName: this.state.selectedField.geoFieldName,
@@ -134,6 +144,13 @@ export class GeometryFilterForm extends Component {
{this._renderRelationInput()}
+
+
{error}
diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap
index 3b3d82c92fbb7..29df06a64a3f2 100644
--- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap
+++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/__snapshots__/feature_properties.test.js.snap
@@ -1,11 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`FeatureProperties should not show filter button 1`] = `
+exports[`FeatureProperties should render 1`] = `
@@ -56,12 +60,13 @@ exports[`FeatureProperties should show error message if unable to load tooltip c
`;
-exports[`FeatureProperties should show only filter button for filterable properties 1`] = `
+exports[`FeatureProperties should show filter button for filterable properties 1`] = `
+`;
+
+exports[`FeatureProperties should show view actions button when there are available actions 1`] = `
+
+
+
+
+ prop1
+ |
+ |
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ prop2
+ |
+ |
+ |
diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/_index.scss b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/_index.scss
index fb75cc1e2db69..abd747c8fa47a 100644
--- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/_index.scss
+++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/_index.scss
@@ -1,6 +1,5 @@
.mapFeatureTooltip_table {
width: 100%;
- display: block;
max-height: calc(49vh - #{$euiSizeXL * 2});
td {
@@ -8,6 +7,10 @@
}
}
+.mapFeatureTooltip_row {
+ border-bottom: 1px solid $euiColorLightestShade;
+}
+
.mapFeatureTooltip_actionLinks {
padding: $euiSizeXS;
}
@@ -20,3 +23,10 @@
max-width: $euiSizeXL * 4;
font-weight: $euiFontWeightSemiBold;
}
+
+.mapFeatureTooltip_actionsRow {
+ > span {
+ display: flex;
+ justify-content: flex-end;
+ }
+}
diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js
index b0ce52b4db7ab..98267965fd30f 100644
--- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js
+++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js
@@ -4,9 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
-import { EuiIcon } from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
+import React, { Component } from 'react';
import { i18n } from '@kbn/i18n';
import { URL_MAX_LENGTH } from '../../../../../../../src/core/public';
@@ -95,28 +93,7 @@ export class FeatureGeometryFilterForm extends Component {
this.props.onClose();
};
- _renderHeader() {
- return (
-
- );
- }
-
- _renderForm() {
+ render() {
return (
);
}
-
- render() {
- return (
-
- {this._renderHeader()}
- {this._renderForm()}
-
- );
- }
}
diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_properties.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_properties.js
index 5e2a153b2ccbf..edd501f266690 100644
--- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_properties.js
+++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_properties.js
@@ -5,12 +5,21 @@
*/
import React from 'react';
-import { EuiCallOut, EuiLoadingSpinner, EuiTextAlign, EuiButtonIcon } from '@elastic/eui';
+import {
+ EuiCallOut,
+ EuiLoadingSpinner,
+ EuiTextAlign,
+ EuiButtonEmpty,
+ EuiIcon,
+ EuiContextMenu,
+} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
+import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../src/plugins/data/public';
export class FeatureProperties extends React.Component {
state = {
properties: null,
+ actions: [],
loadPropertiesErrorMsg: null,
prevWidth: null,
prevHeight: null,
@@ -21,6 +30,7 @@ export class FeatureProperties extends React.Component {
this.prevLayerId = undefined;
this.prevFeatureId = undefined;
this._loadProperties();
+ this._loadActions();
}
componentDidUpdate() {
@@ -31,6 +41,16 @@ export class FeatureProperties extends React.Component {
this._isMounted = false;
}
+ async _loadActions() {
+ if (!this.props.getFilterActions) {
+ return;
+ }
+ const actions = await this.props.getFilterActions();
+ if (this._isMounted) {
+ this.setState({ actions });
+ }
+ }
+
_loadProperties = async () => {
this._fetchProperties({
nextFeatureId: this.props.featureId,
@@ -39,6 +59,10 @@ export class FeatureProperties extends React.Component {
});
};
+ _showFilterActions = (tooltipProperty) => {
+ this.props.showFilterActions(this._renderFilterActions(tooltipProperty));
+ };
+
_fetchProperties = async ({ nextLayerId, nextFeatureId, mbProperties }) => {
if (this.prevLayerId === nextLayerId && this.prevFeatureId === nextFeatureId) {
// do not reload same feature properties
@@ -83,35 +107,108 @@ export class FeatureProperties extends React.Component {
}
if (this._isMounted) {
- this.setState({
- properties,
- });
+ this.setState({ properties });
}
};
+ _renderFilterActions(tooltipProperty) {
+ const panel = {
+ id: 0,
+ items: this.state.actions.map((action) => {
+ const actionContext = this.props.getActionContext();
+ const iconType = action.getIconType(actionContext);
+ const name = action.getDisplayName(actionContext);
+ return {
+ name,
+ icon: iconType ? : null,
+ onClick: async () => {
+ this.props.onCloseTooltip();
+ const filters = await tooltipProperty.getESFilters();
+ this.props.addFilters(filters, action.id);
+ },
+ ['data-test-subj']: `mapFilterActionButton__${name}`,
+ };
+ }),
+ };
+
+ return (
+
+
(this._node = node)}
+ >
+
+
+
+ {tooltipProperty.getPropertyName()}
+ |
+ |
+
+
+
+
+
+ );
+ }
+
_renderFilterCell(tooltipProperty) {
if (!this.props.showFilterButtons || !tooltipProperty.isFilterable()) {
- return null;
+ return | ;
}
- return (
-
- {
- this.props.onCloseTooltip();
- const filters = await tooltipProperty.getESFilters();
- this.props.addFilters(filters);
- }}
- aria-label={i18n.translate('xpack.maps.tooltip.filterOnPropertyAriaLabel', {
- defaultMessage: 'Filter on property',
- })}
- data-test-subj="mapTooltipCreateFilterButton"
- />
+ const applyFilterButton = (
+ {
+ this.props.onCloseTooltip();
+ const filters = await tooltipProperty.getESFilters();
+ this.props.addFilters(filters);
+ }}
+ aria-label={i18n.translate('xpack.maps.tooltip.filterOnPropertyAriaLabel', {
+ defaultMessage: 'Filter on property',
+ })}
+ data-test-subj="mapTooltipCreateFilterButton"
+ >
+
+
+ );
+
+ return this.state.actions.length === 0 ||
+ (this.state.actions.length === 1 &&
+ this.state.actions[0].id === ACTION_GLOBAL_APPLY_FILTER) ? (
+ {applyFilterButton} |
+ ) : (
+
+
+ {applyFilterButton}
+ {
+ this._showFilterActions(tooltipProperty);
+ }}
+ aria-label={i18n.translate('xpack.maps.tooltip.viewActionsTitle', {
+ defaultMessage: 'View filter actions',
+ })}
+ data-test-subj="mapTooltipMoreActionsButton"
+ >
+
+
+
|
);
}
@@ -154,7 +251,7 @@ export class FeatureProperties extends React.Component {
const rows = this.state.properties.map((tooltipProperty) => {
const label = tooltipProperty.getPropertyName();
return (
-
+
{label} |
{},
showFilterButtons: false,
+ getFilterActions: () => {
+ return [{ id: ACTION_GLOBAL_APPLY_FILTER }];
+ },
};
const mockTooltipProperties = [
@@ -44,10 +48,29 @@ const mockTooltipProperties = [
];
describe('FeatureProperties', () => {
- test('should not show filter button', async () => {
+ test('should render', async () => {
+ const component = shallow(
+ {
+ return mockTooltipProperties;
+ }}
+ />
+ );
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('should show filter button for filterable properties', async () => {
const component = shallow(
{
return mockTooltipProperties;
}}
@@ -62,7 +85,7 @@ describe('FeatureProperties', () => {
expect(component).toMatchSnapshot();
});
- test('should show only filter button for filterable properties', async () => {
+ test('should show view actions button when there are available actions', async () => {
const component = shallow(
{
loadFeatureProperties={() => {
return mockTooltipProperties;
}}
+ getFilterActions={() => {
+ return [{ id: 'drilldown1' }];
+ }}
/>
);
diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/features_tooltip.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/features_tooltip.js
index d91bc8e803ab9..8547219b42e30 100644
--- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/features_tooltip.js
+++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/features_tooltip.js
@@ -4,20 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Fragment } from 'react';
-import { EuiLink } from '@elastic/eui';
+import React, { Component, Fragment } from 'react';
+import { EuiIcon, EuiLink } from '@elastic/eui';
import { FeatureProperties } from './feature_properties';
-import { FormattedMessage } from '@kbn/i18n/react';
import { GEO_JSON_TYPE, ES_GEO_FIELD_TYPE } from '../../../../common/constants';
import { FeatureGeometryFilterForm } from './feature_geometry_filter_form';
import { TooltipHeader } from './tooltip_header';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
const VIEWS = {
PROPERTIES_VIEW: 'PROPERTIES_VIEW',
GEOMETRY_FILTER_VIEW: 'GEOMETRY_FILTER_VIEW',
+ FILTER_ACTIONS_VIEW: 'FILTER_ACTIONS_VIEW',
};
-export class FeaturesTooltip extends React.Component {
+export class FeaturesTooltip extends Component {
state = {};
static getDerivedStateFromProps(nextProps, prevState) {
@@ -41,7 +43,11 @@ export class FeaturesTooltip extends React.Component {
};
_showPropertiesView = () => {
- this.setState({ view: VIEWS.PROPERTIES_VIEW });
+ this.setState({ view: VIEWS.PROPERTIES_VIEW, filterView: null });
+ };
+
+ _showFilterActionsView = (filterView) => {
+ this.setState({ view: VIEWS.FILTER_ACTIONS_VIEW, filterView });
};
_renderActions(geoFields) {
@@ -96,6 +102,22 @@ export class FeaturesTooltip extends React.Component {
});
};
+ _renderBackButton(label) {
+ return (
+
+ );
+ }
+
render() {
if (!this.state.currentFeature) {
return null;
@@ -109,14 +131,36 @@ export class FeaturesTooltip extends React.Component {
if (this.state.view === VIEWS.GEOMETRY_FILTER_VIEW && currentFeatureGeometry) {
return (
-
+
+ {this._renderBackButton(
+ i18n.translate('xpack.maps.tooltip.showGeometryFilterViewLinkLabel', {
+ defaultMessage: 'Filter by geometry',
+ })
+ )}
+
+
+ );
+ }
+
+ if (this.state.view === VIEWS.FILTER_ACTIONS_VIEW) {
+ return (
+
+ {this._renderBackButton(
+ i18n.translate('xpack.maps.tooltip.showAddFilterActionsViewLabel', {
+ defaultMessage: 'Filter actions',
+ })
+ )}
+ {this.state.filterView}
+
);
}
@@ -137,6 +181,9 @@ export class FeaturesTooltip extends React.Component {
showFilterButtons={!!this.props.addFilters && this.props.isLocked}
onCloseTooltip={this.props.closeTooltip}
addFilters={this.props.addFilters}
+ getFilterActions={this.props.getFilterActions}
+ getActionContext={this.props.getActionContext}
+ showFilterActions={this._showFilterActionsView}
/>
{this._renderActions(geoFields)}
diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js
index 6de936fa4a8f1..49675ac6a3924 100644
--- a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js
+++ b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js
@@ -62,11 +62,12 @@ export class DrawControl extends React.Component {
}
}, 0);
- _onDraw = (e) => {
+ _onDraw = async (e) => {
if (!e.features.length) {
return;
}
+ let filter;
if (this.props.drawState.drawType === DRAW_TYPE.DISTANCE) {
const circle = e.features[0];
const distanceKm = _.round(
@@ -82,7 +83,7 @@ export class DrawControl extends React.Component {
} else if (distanceKm <= 100) {
precision = 3;
}
- const filter = createDistanceFilterWithMeta({
+ filter = createDistanceFilterWithMeta({
alias: this.props.drawState.filterLabel,
distanceKm,
geoFieldName: this.props.drawState.geoFieldName,
@@ -92,17 +93,12 @@ export class DrawControl extends React.Component {
_.round(circle.properties.center[1], precision),
],
});
- this.props.addFilters([filter]);
- this.props.disableDrawState();
- return;
- }
-
- const geometry = e.features[0].geometry;
- // MapboxDraw returns coordinates with 12 decimals. Round to a more reasonable number
- roundCoordinates(geometry.coordinates);
+ } else {
+ const geometry = e.features[0].geometry;
+ // MapboxDraw returns coordinates with 12 decimals. Round to a more reasonable number
+ roundCoordinates(geometry.coordinates);
- try {
- const filter = createSpatialFilterWithGeometry({
+ filter = createSpatialFilterWithGeometry({
geometry:
this.props.drawState.drawType === DRAW_TYPE.BOUNDS
? getBoundingBoxGeometry(geometry)
@@ -113,7 +109,10 @@ export class DrawControl extends React.Component {
geometryLabel: this.props.drawState.geometryLabel,
relation: this.props.drawState.relation,
});
- this.props.addFilters([filter]);
+ }
+
+ try {
+ await this.props.addFilters([filter], this.props.drawState.actionId);
} catch (error) {
// TODO notify user why filter was not created
console.error(error);
diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_control.js b/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_control.js
index 84a29db852539..87d6f8e1d8e71 100644
--- a/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_control.js
+++ b/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_control.js
@@ -195,6 +195,8 @@ export class TooltipControl extends React.Component {
mbMap={this.props.mbMap}
layerList={this.props.layerList}
addFilters={this.props.addFilters}
+ getFilterActions={this.props.getFilterActions}
+ getActionContext={this.props.getActionContext}
renderTooltipContent={this.props.renderTooltipContent}
geoFields={this.props.geoFields}
features={features}
diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_popover.js b/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_popover.js
index 6c42057680408..4cfddf0034039 100644
--- a/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_popover.js
+++ b/x-pack/plugins/maps/public/connected_components/map/mb/tooltip_control/tooltip_popover.js
@@ -117,6 +117,8 @@ export class TooltipPopover extends Component {
_renderTooltipContent = () => {
const publicProps = {
addFilters: this.props.addFilters,
+ getFilterActions: this.props.getFilterActions,
+ getActionContext: this.props.getActionContext,
closeTooltip: this.props.closeTooltip,
features: this.props.features,
isLocked: this.props.isLocked,
diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js
index 5a38f6039ae4b..22c374aceedd5 100644
--- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js
+++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js
@@ -309,6 +309,8 @@ export class MBMap extends React.Component {
diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
index beb1eb0947c50..bf75c86ac249d 100644
--- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
+++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
@@ -11,6 +11,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import uuid from 'uuid/v4';
import { Filter } from 'src/plugins/data/public';
+import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public';
// @ts-expect-error
import { MBMap } from '../map/mb';
// @ts-expect-error
@@ -35,7 +36,9 @@ import 'mapbox-gl/dist/mapbox-gl.css';
const RENDER_COMPLETE_EVENT = 'renderComplete';
interface Props {
- addFilters: ((filters: Filter[]) => void) | null;
+ addFilters: ((filters: Filter[]) => Promise) | null;
+ getFilterActions?: () => Promise;
+ getActionContext?: () => ActionExecutionContext;
areLayersLoaded: boolean;
cancelAllInFlightRequests: () => void;
exitFullScreen: () => void;
@@ -183,6 +186,8 @@ export class MapContainer extends Component {
render() {
const {
addFilters,
+ getFilterActions,
+ getActionContext,
flyoutDisplay,
isFullScreen,
exitFullScreen,
@@ -230,11 +235,18 @@ export class MapContainer extends Component {
{!this.props.hideToolbarOverlay && (
-
+
)}
diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.js b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.js
index a4f85163512f7..a9dc3f822060c 100644
--- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.js
+++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/toolbar_overlay.js
@@ -12,14 +12,18 @@ import { FitToData } from './fit_to_data';
export class ToolbarOverlay extends React.Component {
_renderToolsControl() {
- const { addFilters, geoFields } = this.props;
+ const { addFilters, geoFields, getFilterActions, getActionContext } = this.props;
if (!addFilters || !geoFields.length) {
return null;
}
return (
-
+
);
}
diff --git a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.js b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.js
index a06def086b861..017f0369e0b73 100644
--- a/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.js
+++ b/x-pack/plugins/maps/public/connected_components/toolbar_overlay/tools_control/tools_control.js
@@ -123,6 +123,8 @@ export class ToolsControl extends Component {
className="mapDrawControl__geometryFilterForm"
buttonLabel={DRAW_SHAPE_LABEL_SHORT}
geoFields={this.props.geoFields}
+ getFilterActions={this.props.getFilterActions}
+ getActionContext={this.props.getActionContext}
intitialGeometryLabel={i18n.translate(
'xpack.maps.toolbarOverlay.drawShape.initialGeometryLabel',
{
@@ -141,6 +143,8 @@ export class ToolsControl extends Component {
className="mapDrawControl__geometryFilterForm"
buttonLabel={DRAW_BOUNDS_LABEL_SHORT}
geoFields={this.props.geoFields}
+ getFilterActions={this.props.getFilterActions}
+ getActionContext={this.props.getActionContext}
intitialGeometryLabel={i18n.translate(
'xpack.maps.toolbarOverlay.drawBounds.initialGeometryLabel',
{
@@ -161,6 +165,8 @@ export class ToolsControl extends Component {
geoFields={this.props.geoFields.filter(({ geoFieldType }) => {
return geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT;
})}
+ getFilterActions={this.props.getFilterActions}
+ getActionContext={this.props.getActionContext}
onSubmit={this._initiateDistanceDraw}
/>
),
diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
index 43ff274b1353f..1cb393bede956 100644
--- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
+++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx
@@ -11,7 +11,12 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { Subscription } from 'rxjs';
import { Unsubscribe } from 'redux';
import { Embeddable, IContainer } from '../../../../../src/plugins/embeddable/public';
-import { APPLY_FILTER_TRIGGER } from '../../../../../src/plugins/ui_actions/public';
+import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../src/plugins/data/public';
+import {
+ APPLY_FILTER_TRIGGER,
+ ActionExecutionContext,
+ TriggerContextMapping,
+} from '../../../../../src/plugins/ui_actions/public';
import {
esFilters,
TimeRange,
@@ -99,6 +104,10 @@ export class MapEmbeddable extends Embeddable this.onContainerStateChanged(input));
}
+ supportedTriggers(): Array {
+ return [APPLY_FILTER_TRIGGER];
+ }
+
setRenderTooltipContent = (renderTooltipContent: RenderToolTipContent) => {
this._renderTooltipContent = renderTooltipContent;
};
@@ -226,6 +235,8 @@ export class MapEmbeddable extends Embeddable
@@ -243,13 +254,36 @@ export class MapEmbeddable extends Embeddable(replaceLayerList(this._layerList));
}
- addFilters = (filters: Filter[]) => {
- getUiActions().executeTriggerActions(APPLY_FILTER_TRIGGER, {
- embeddable: this,
+ addFilters = async (filters: Filter[], actionId: string = ACTION_GLOBAL_APPLY_FILTER) => {
+ const executeContext = {
+ ...this.getActionContext(),
filters,
+ };
+ const action = getUiActions().getAction(actionId);
+ if (!action) {
+ throw new Error('Unable to apply filter, could not locate action');
+ }
+ action.execute(executeContext);
+ };
+
+ getFilterActions = async () => {
+ return await getUiActions().getTriggerCompatibleActions(APPLY_FILTER_TRIGGER, {
+ embeddable: this,
+ filters: [],
});
};
+ getActionContext = () => {
+ const trigger = getUiActions().getTrigger(APPLY_FILTER_TRIGGER);
+ if (!trigger) {
+ throw new Error('Unable to get context, could not locate trigger');
+ }
+ return {
+ embeddable: this,
+ trigger,
+ } as ActionExecutionContext;
+ };
+
destroy() {
super.destroy();
if (this._unsubscribeFromStore) {
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js
index b23b4fc888120..5d8af8d71b7fc 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/bulk_uploader.js
@@ -5,7 +5,7 @@
*/
import { defaultsDeep, uniq, compact } from 'lodash';
-
+import { ServiceStatusLevels } from '../../../../../src/core/server';
import {
TELEMETRY_COLLECTION_INTERVAL,
KIBANA_STATS_TYPE_MONITORING,
@@ -30,7 +30,7 @@ import { sendBulkPayload, monitoringBulk } from './lib';
* @param {Object} xpackInfo server.plugins.xpack_main.info object
*/
export class BulkUploader {
- constructor({ log, interval, elasticsearch, kibanaStats }) {
+ constructor({ log, interval, elasticsearch, statusGetter$, kibanaStats }) {
if (typeof interval !== 'number') {
throw new Error('interval number of milliseconds is required');
}
@@ -52,11 +52,11 @@ export class BulkUploader {
});
this.kibanaStats = kibanaStats;
- this.kibanaStatusGetter = null;
- }
- setKibanaStatusGetter(getter) {
- this.kibanaStatusGetter = getter;
+ this.kibanaStatus = null;
+ this.kibanaStatusGetter$ = statusGetter$.subscribe((nextStatus) => {
+ this.kibanaStatus = nextStatus.level;
+ });
}
filterCollectorSet(usageCollection) {
@@ -128,7 +128,7 @@ export class BulkUploader {
async _fetchAndUpload(usageCollection) {
const collectorsReady = await usageCollection.areAllCollectorsReady();
const hasUsageCollectors = usageCollection.some(usageCollection.isUsageCollector);
- if (!collectorsReady || typeof this.kibanaStatusGetter !== 'function') {
+ if (!collectorsReady) {
this._log.debug('Skipping bulk uploading because not all collectors are ready');
if (hasUsageCollectors) {
this._lastFetchUsageTime = null;
@@ -172,10 +172,23 @@ export class BulkUploader {
return await sendBulkPayload(this._cluster, this._interval, payload, this._log);
}
+ getConvertedKibanaStatuss() {
+ if (this.kibanaStatus === ServiceStatusLevels.available) {
+ return 'green';
+ }
+ if (this.kibanaStatus === ServiceStatusLevels.critical) {
+ return 'red';
+ }
+ if (this.kibanaStatus === ServiceStatusLevels.degraded) {
+ return 'yellow';
+ }
+ return 'unknown';
+ }
+
getKibanaStats(type) {
const stats = {
...this.kibanaStats,
- status: this.kibanaStatusGetter(),
+ status: this.getConvertedKibanaStatuss(),
};
if (type === KIBANA_STATS_TYPE_MONITORING) {
diff --git a/x-pack/plugins/monitoring/server/plugin.test.ts b/x-pack/plugins/monitoring/server/plugin.test.ts
index 8bd43b6be0a8d..a2520593c436d 100644
--- a/x-pack/plugins/monitoring/server/plugin.test.ts
+++ b/x-pack/plugins/monitoring/server/plugin.test.ts
@@ -5,8 +5,6 @@
*/
import { Plugin } from './plugin';
import { combineLatest } from 'rxjs';
-// @ts-ignore
-import { initBulkUploader } from './kibana_monitoring';
import { AlertsFactory } from './alerts';
jest.mock('rxjs', () => ({
@@ -27,10 +25,6 @@ jest.mock('./license_service', () => ({
})),
}));
-jest.mock('./kibana_monitoring', () => ({
- initBulkUploader: jest.fn(),
-}));
-
describe('Monitoring plugin', () => {
const initializerContext = {
logger: {
@@ -71,6 +65,11 @@ describe('Monitoring plugin', () => {
createClient: jest.fn(),
},
},
+ status: {
+ overall$: {
+ subscribe: jest.fn(),
+ },
+ },
};
const setupPlugins = {
@@ -113,19 +112,13 @@ describe('Monitoring plugin', () => {
afterEach(() => {
(setupPlugins.alerts.registerType as jest.Mock).mockReset();
+ (coreSetup.status.overall$.subscribe as jest.Mock).mockReset();
});
it('always create the bulk uploader', async () => {
- const setKibanaStatusGetter = jest.fn();
- (initBulkUploader as jest.Mock).mockImplementation(() => {
- return {
- setKibanaStatusGetter,
- };
- });
const plugin = new Plugin(initializerContext as any);
- const contract = await plugin.setup(coreSetup as any, setupPlugins as any);
- contract.registerLegacyAPI(null as any);
- expect(setKibanaStatusGetter).toHaveBeenCalled();
+ await plugin.setup(coreSetup as any, setupPlugins as any);
+ expect(coreSetup.status.overall$.subscribe).toHaveBeenCalled();
});
it('should register all alerts', async () => {
diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts
index 501c96b12fde8..f5cbadb523a81 100644
--- a/x-pack/plugins/monitoring/server/plugin.ts
+++ b/x-pack/plugins/monitoring/server/plugin.ts
@@ -46,7 +46,6 @@ import {
IBulkUploader,
PluginsSetup,
PluginsStart,
- LegacyAPI,
LegacyRequest,
} from './types';
@@ -158,6 +157,7 @@ export class Plugin {
elasticsearch: core.elasticsearch,
config,
log: kibanaMonitoringLog,
+ statusGetter$: core.status.overall$,
kibanaStats: {
uuid: this.initializerContext.env.instanceUuid,
name: serverInfo.name,
@@ -221,11 +221,6 @@ export class Plugin {
}
return {
- // The legacy plugin calls this to register certain legacy dependencies
- // that are necessary for the plugin to properly run
- registerLegacyAPI: (legacyAPI: LegacyAPI) => {
- this.setupLegacy(legacyAPI);
- },
// OSS stats api needs to call this in order to centralize how
// we fetch kibana specific stats
getKibanaStats: () => this.bulkUploader.getKibanaStats(),
@@ -280,11 +275,6 @@ export class Plugin {
});
}
- async setupLegacy(legacyAPI: LegacyAPI) {
- // Set the stats getter
- this.bulkUploader.setKibanaStatusGetter(() => legacyAPI.getServerStatus());
- }
-
getLegacyShim(
config: MonitoringConfig,
legacyConfig: any,
diff --git a/x-pack/plugins/monitoring/server/types.ts b/x-pack/plugins/monitoring/server/types.ts
index a0ef6d3e2d984..e6a4b174df55d 100644
--- a/x-pack/plugins/monitoring/server/types.ts
+++ b/x-pack/plugins/monitoring/server/types.ts
@@ -33,10 +33,6 @@ export interface MonitoringElasticsearchConfig {
hosts: string[];
}
-export interface LegacyAPI {
- getServerStatus: () => string;
-}
-
export interface PluginsSetup {
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
telemetryCollectionManager?: TelemetryCollectionManagerPluginSetup;
@@ -77,7 +73,6 @@ export interface LegacyShimDependencies {
}
export interface IBulkUploader {
- setKibanaStatusGetter: (getter: () => string | undefined) => void;
getKibanaStats: () => any;
}
diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx
index db7fca140be89..19995ed233e8d 100644
--- a/x-pack/plugins/observability/public/application/application.test.tsx
+++ b/x-pack/plugins/observability/public/application/application.test.tsx
@@ -4,10 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { createMemoryHistory } from 'history';
import React from 'react';
-import { renderApp } from './';
import { Observable } from 'rxjs';
-import { CoreStart, AppMountParameters } from 'src/core/public';
+import { AppMountParameters, CoreStart } from 'src/core/public';
+import { renderApp } from './';
describe('renderApp', () => {
it('renders', () => {
@@ -19,6 +20,7 @@ describe('renderApp', () => {
} as unknown) as CoreStart;
const params = ({
element: window.document.createElement('div'),
+ history: createMemoryHistory(),
} as unknown) as AppMountParameters;
expect(() => {
diff --git a/x-pack/plugins/observability/public/application/index.tsx b/x-pack/plugins/observability/public/application/index.tsx
index 4c0147dc3cd51..fa691a7f41ddb 100644
--- a/x-pack/plugins/observability/public/application/index.tsx
+++ b/x-pack/plugins/observability/public/application/index.tsx
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
-import { createHashHistory } from 'history';
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import { Route, Router, Switch } from 'react-router-dom';
@@ -52,10 +51,10 @@ function App() {
);
}
-export const renderApp = (core: CoreStart, { element }: AppMountParameters) => {
+export const renderApp = (core: CoreStart, { element, history }: AppMountParameters) => {
const i18nCore = core.i18n;
const isDarkMode = core.uiSettings.get('theme:darkMode');
- const history = createHashHistory();
+
ReactDOM.render(
diff --git a/x-pack/plugins/security_solution/public/common/components/news_feed/no_news/index.tsx b/x-pack/plugins/security_solution/public/common/components/news_feed/no_news/index.tsx
index d626433de1b63..c2ef6b9b192c7 100644
--- a/x-pack/plugins/security_solution/public/common/components/news_feed/no_news/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/news_feed/no_news/index.tsx
@@ -4,24 +4,37 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiLink, EuiText } from '@elastic/eui';
-import React from 'react';
+import { EuiText } from '@elastic/eui';
+import React, { useCallback } from 'react';
import * as i18n from '../translations';
-import { useBasePath } from '../../../lib/kibana';
+import { useKibana } from '../../../lib/kibana';
+import { LinkAnchor } from '../../links';
export const NoNews = React.memo(() => {
- const basePath = useBasePath();
+ const { getUrlForApp, navigateToApp, capabilities } = useKibana().services.application;
+ const canSeeAdvancedSettings = capabilities.management.kibana.settings ?? false;
+ const goToKibanaSettings = useCallback(
+ () => navigateToApp('management', { path: '/kibana/settings' }),
+ [navigateToApp]
+ );
+
return (
- <>
-
- {i18n.NO_NEWS_MESSAGE}{' '}
-
- {i18n.ADVANCED_SETTINGS_LINK_TITLE}
-
- {'.'}
-
- >
+
+ {canSeeAdvancedSettings ? i18n.NO_NEWS_MESSAGE_ADMIN : i18n.NO_NEWS_MESSAGE}
+ {canSeeAdvancedSettings && (
+ <>
+ {' '}
+
+ {i18n.ADVANCED_SETTINGS_LINK_TITLE}
+
+ {'.'}
+ >
+ )}
+
);
});
diff --git a/x-pack/plugins/security_solution/public/common/components/news_feed/translations.ts b/x-pack/plugins/security_solution/public/common/components/news_feed/translations.ts
index b0f9507266e52..dabaa38178884 100644
--- a/x-pack/plugins/security_solution/public/common/components/news_feed/translations.ts
+++ b/x-pack/plugins/security_solution/public/common/components/news_feed/translations.ts
@@ -7,10 +7,17 @@
import { i18n } from '@kbn/i18n';
export const NO_NEWS_MESSAGE = i18n.translate('xpack.securitySolution.newsFeed.noNewsMessage', {
- defaultMessage:
- 'Your current news feed URL returned no recent news. You may update the URL or disable security news via',
+ defaultMessage: 'Your current news feed URL returned no recent news.',
});
+export const NO_NEWS_MESSAGE_ADMIN = i18n.translate(
+ 'xpack.securitySolution.newsFeed.noNewsMessageForAdmin',
+ {
+ defaultMessage:
+ 'Your current news feed URL returned no recent news. You may update the URL or disable security news via',
+ }
+);
+
export const ADVANCED_SETTINGS_LINK_TITLE = i18n.translate(
'xpack.securitySolution.newsFeed.advancedSettingsLinkTitle',
{
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx
index 86334308558b8..8f18a173f3bed 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx
@@ -272,9 +272,6 @@ export interface NewTimelineProps {
export const NewTimeline = React.memo(
({ closeGearMenu, outline = false, timelineId, title = i18n.NEW_TIMELINE }) => {
- const uiCapabilities = useKibana().services.application.capabilities;
- const capabilitiesCanUserCRUD: boolean = !!uiCapabilities.siem.crud;
-
const { getButton } = useCreateTimelineButton({
timelineId,
timelineType: TimelineType.default,
@@ -282,7 +279,7 @@ export const NewTimeline = React.memo(
});
const button = getButton({ outline, title });
- return capabilitiesCanUserCRUD ? button : null;
+ return button;
}
);
NewTimeline.displayName = 'NewTimeline';
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx
index 70257c97a6887..12eab4942128f 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx
@@ -22,7 +22,6 @@ import {
TimelineType,
} from '../../../../../common/types/timeline';
import { InspectButton, InspectButtonContainer } from '../../../../common/components/inspect';
-import { useKibana } from '../../../../common/lib/kibana';
import { Note } from '../../../../common/lib/note';
import { AssociateNote } from '../../notes/helpers';
@@ -121,8 +120,6 @@ const PropertiesRightComponent: React.FC = ({
updateNote,
usersViewing,
}) => {
- const uiCapabilities = useKibana().services.application.capabilities;
- const capabilitiesCanUserCRUD: boolean = !!uiCapabilities.siem.crud;
return (
@@ -143,15 +140,13 @@ const PropertiesRightComponent: React.FC = ({
repositionOnScroll
>
- {capabilitiesCanUserCRUD && (
-
-
-
- )}
+
+
+
{
});
});
+ describe('create draft timeline in read-only permission', () => {
+ const timelineId = null;
+ const initialDraftTimeline = {
+ columns: [
+ {
+ columnHeaderType: 'not-filtered',
+ id: '@timestamp',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'message',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'event.category',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'event.action',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'host.name',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'source.ip',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'destination.ip',
+ },
+ {
+ columnHeaderType: 'not-filtered',
+ id: 'user.name',
+ },
+ ],
+ dataProviders: [],
+ description: 'x',
+ eventType: 'all',
+ filters: [],
+ kqlMode: 'filter',
+ kqlQuery: {
+ filterQuery: null,
+ },
+ title: '',
+ timelineType: TimelineType.default,
+ templateTimelineVersion: null,
+ templateTimelineId: null,
+ dateRange: {
+ start: 1590998565409,
+ end: 1591084965409,
+ },
+ savedQueryId: null,
+ sort: {
+ columnId: '@timestamp',
+ sortDirection: 'desc',
+ },
+ status: TimelineStatus.draft,
+ };
+
+ const version = null;
+ const fetchMock = jest.fn();
+ const postMock = jest.fn();
+ const patchMock = jest.fn();
+
+ beforeAll(() => {
+ jest.resetAllMocks();
+ jest.resetModules();
+
+ (KibanaServices.get as jest.Mock).mockReturnValue({
+ http: {
+ fetch: fetchMock.mockRejectedValue({
+ body: { status_code: 403, message: 'you do not have the permission' },
+ }),
+ post: postMock.mockRejectedValue({
+ body: { status_code: 403, message: 'you do not have the permission' },
+ }),
+ patch: patchMock.mockRejectedValue({
+ body: { status_code: 403, message: 'you do not have the permission' },
+ }),
+ },
+ });
+ });
+
+ test('it should return your request timeline with code and message', async () => {
+ const persist = await api.persistTimeline({
+ timelineId,
+ timeline: initialDraftTimeline,
+ version,
+ });
+ expect(persist).toEqual({
+ data: {
+ persistTimeline: {
+ code: 403,
+ message: 'you do not have the permission',
+ timeline: { ...initialDraftTimeline, savedObjectId: '', version: '' },
+ },
+ },
+ });
+ });
+ });
+
describe('create active timeline (import)', () => {
const timelineId = null;
const importTimeline = {
diff --git a/x-pack/plugins/security_solution/public/timelines/containers/api.ts b/x-pack/plugins/security_solution/public/timelines/containers/api.ts
index e08d52066ebdc..c6794d125368e 100644
--- a/x-pack/plugins/security_solution/public/timelines/containers/api.ts
+++ b/x-pack/plugins/security_solution/public/timelines/containers/api.ts
@@ -6,6 +6,7 @@
import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
+import isEmpty from 'lodash/isEmpty';
import { throwErrors } from '../../../../case/common/api';
import {
@@ -99,44 +100,63 @@ export const persistTimeline = async ({
timeline,
version,
}: RequestPersistTimeline): Promise => {
- if (timelineId == null && timeline.status === TimelineStatus.draft && timeline) {
- const draftTimeline = await cleanDraftTimeline({
- timelineType: timeline.timelineType!,
- templateTimelineId: timeline.templateTimelineId ?? undefined,
- templateTimelineVersion: timeline.templateTimelineVersion ?? undefined,
- });
-
- const templateTimelineInfo =
- timeline.timelineType! === TimelineType.template
- ? {
- templateTimelineId:
- draftTimeline.data.persistTimeline.timeline.templateTimelineId ??
- timeline.templateTimelineId,
- templateTimelineVersion:
- draftTimeline.data.persistTimeline.timeline.templateTimelineVersion ??
- timeline.templateTimelineVersion,
- }
- : {};
+ try {
+ if (isEmpty(timelineId) && timeline.status === TimelineStatus.draft && timeline) {
+ const draftTimeline = await cleanDraftTimeline({
+ timelineType: timeline.timelineType!,
+ templateTimelineId: timeline.templateTimelineId ?? undefined,
+ templateTimelineVersion: timeline.templateTimelineVersion ?? undefined,
+ });
+
+ const templateTimelineInfo =
+ timeline.timelineType! === TimelineType.template
+ ? {
+ templateTimelineId:
+ draftTimeline.data.persistTimeline.timeline.templateTimelineId ??
+ timeline.templateTimelineId,
+ templateTimelineVersion:
+ draftTimeline.data.persistTimeline.timeline.templateTimelineVersion ??
+ timeline.templateTimelineVersion,
+ }
+ : {};
+
+ return patchTimeline({
+ timelineId: draftTimeline.data.persistTimeline.timeline.savedObjectId,
+ timeline: {
+ ...timeline,
+ ...templateTimelineInfo,
+ },
+ version: draftTimeline.data.persistTimeline.timeline.version ?? '',
+ });
+ }
+
+ if (isEmpty(timelineId)) {
+ return postTimeline({ timeline });
+ }
return patchTimeline({
- timelineId: draftTimeline.data.persistTimeline.timeline.savedObjectId,
- timeline: {
- ...timeline,
- ...templateTimelineInfo,
- },
- version: draftTimeline.data.persistTimeline.timeline.version ?? '',
+ timelineId: timelineId ?? '-1',
+ timeline,
+ version: version ?? '',
});
+ } catch (err) {
+ if (err.status_code === 403 || err.body.status_code === 403) {
+ return Promise.resolve({
+ data: {
+ persistTimeline: {
+ code: 403,
+ message: err.message || err.body.message,
+ timeline: {
+ ...timeline,
+ savedObjectId: '',
+ version: '',
+ },
+ },
+ },
+ });
+ }
+ return Promise.resolve(err);
}
-
- if (timelineId == null) {
- return postTimeline({ timeline });
- }
-
- return patchTimeline({
- timelineId,
- timeline,
- version: version ?? '',
- });
};
export const importTimelines = async ({
diff --git a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx
index c22acf6ba7cc1..1d2e16b3fe5b8 100644
--- a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.tsx
@@ -64,13 +64,11 @@ export const TimelinesPageComponent: React.FC = () => {
{tabName === TimelineType.default ? (
- {capabilitiesCanUserCRUD && (
-
- )}
+
) : (
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index dc07044ce8ed7..07b646df74b9f 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -1115,7 +1115,6 @@
"data.search.aggs.metrics.count.customLabel.help": "このアグリゲーションのカスタムラベルを表します",
"data.search.aggs.metrics.count.enabled.help": "このアグリゲーションが有効かどうかを指定します",
"data.search.aggs.metrics.count.id.help": "このアグリゲーションのID",
- "data.search.aggs.metrics.count.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON",
"data.search.aggs.metrics.count.schema.help": "このアグリゲーションで使用するスキーマ",
"data.search.aggs.metrics.countLabel": "カウント",
"data.search.aggs.metrics.countTitle": "カウント",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 144bc1cac1852..ffd7d0cfb0f87 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -1116,7 +1116,6 @@
"data.search.aggs.metrics.count.customLabel.help": "表示此聚合的定制标签",
"data.search.aggs.metrics.count.enabled.help": "指定是否启用此聚合",
"data.search.aggs.metrics.count.id.help": "此聚合的 ID",
- "data.search.aggs.metrics.count.json.help": "聚合发送至 Elasticsearch 时要包括的高级 json",
"data.search.aggs.metrics.count.schema.help": "要用于此聚合的方案",
"data.search.aggs.metrics.countLabel": "计数",
"data.search.aggs.metrics.countTitle": "计数",
diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts
index f0222de02697d..015d9a4925f3e 100644
--- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_availability.test.ts
@@ -203,28 +203,32 @@ describe('monitor availability', () => {
},
},
},
- ],
- "minimum_should_match": 1,
- "should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
- "match_phrase": Object {
- "monitor.id": "apm-dev",
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.id": "apm-dev",
+ },
+ },
+ ],
},
},
- ],
- },
- },
- Object {
- "bool": Object {
- "minimum_should_match": 1,
- "should": Array [
Object {
- "match_phrase": Object {
- "monitor.id": "auto-http-0X8D6082B94BBE3B8A",
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.id": "auto-http-0X8D6082B94BBE3B8A",
+ },
+ },
+ ],
},
},
],
@@ -797,6 +801,133 @@ describe('monitor availability', () => {
]
`);
});
+
+ it('does not overwrite filters', async () => {
+ const [callES, esMock] = setupMockEsCompositeQuery<
+ AvailabilityKey,
+ GetMonitorAvailabilityResult,
+ AvailabilityDoc
+ >(
+ [
+ {
+ bucketCriteria: [],
+ },
+ ],
+ genBucketItem
+ );
+ await getMonitorAvailability({
+ callES,
+ dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS,
+ range: 3,
+ rangeUnit: 's',
+ threshold: '99',
+ filters: JSON.stringify({ bool: { filter: [{ term: { 'monitor.id': 'foo' } }] } }),
+ });
+ const [, params] = esMock.callAsCurrentUser.mock.calls[0];
+ expect(params).toMatchInlineSnapshot(`
+ Object {
+ "body": Object {
+ "aggs": Object {
+ "monitors": Object {
+ "aggs": Object {
+ "down_sum": Object {
+ "sum": Object {
+ "field": "summary.down",
+ "missing": 0,
+ },
+ },
+ "fields": Object {
+ "top_hits": Object {
+ "size": 1,
+ "sort": Array [
+ Object {
+ "@timestamp": Object {
+ "order": "desc",
+ },
+ },
+ ],
+ },
+ },
+ "filtered": Object {
+ "bucket_selector": Object {
+ "buckets_path": Object {
+ "threshold": "ratio.value",
+ },
+ "script": "params.threshold < 0.99",
+ },
+ },
+ "ratio": Object {
+ "bucket_script": Object {
+ "buckets_path": Object {
+ "downTotal": "down_sum",
+ "upTotal": "up_sum",
+ },
+ "script": "
+ if (params.upTotal + params.downTotal > 0) {
+ return params.upTotal / (params.upTotal + params.downTotal);
+ } return null;",
+ },
+ },
+ "up_sum": Object {
+ "sum": Object {
+ "field": "summary.up",
+ "missing": 0,
+ },
+ },
+ },
+ "composite": Object {
+ "size": 2000,
+ "sources": Array [
+ Object {
+ "monitorId": Object {
+ "terms": Object {
+ "field": "monitor.id",
+ },
+ },
+ },
+ Object {
+ "location": Object {
+ "terms": Object {
+ "field": "observer.geo.name",
+ "missing_bucket": true,
+ },
+ },
+ },
+ ],
+ },
+ },
+ },
+ "query": Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "range": Object {
+ "@timestamp": Object {
+ "gte": "now-3s",
+ "lte": "now",
+ },
+ },
+ },
+ Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "term": Object {
+ "monitor.id": "foo",
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ "size": 0,
+ },
+ "index": "heartbeat-8*",
+ }
+ `);
+ });
});
describe('formatBuckets', () => {
diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts
index 7dba71a8126e2..e61d736e37106 100644
--- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts
@@ -148,28 +148,32 @@ describe('getMonitorStatus', () => {
},
},
},
- ],
- "minimum_should_match": 1,
- "should": Array [
Object {
"bool": Object {
"minimum_should_match": 1,
"should": Array [
Object {
- "match_phrase": Object {
- "monitor.id": "apm-dev",
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.id": "apm-dev",
+ },
+ },
+ ],
},
},
- ],
- },
- },
- Object {
- "bool": Object {
- "minimum_should_match": 1,
- "should": Array [
Object {
- "match_phrase": Object {
- "monitor.id": "auto-http-0X8D6082B94BBE3B8A",
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.id": "auto-http-0X8D6082B94BBE3B8A",
+ },
+ },
+ ],
},
},
],
@@ -286,6 +290,296 @@ describe('getMonitorStatus', () => {
`);
});
+ it('properly assigns filters for complex kuery filters', async () => {
+ const [callES, esMock] = setupMockEsCompositeQuery(
+ [{ bucketCriteria: [] }],
+ genBucketItem
+ );
+ const clientParameters = {
+ timerange: {
+ from: 'now-15m',
+ to: 'now',
+ },
+ numTimes: 5,
+ locations: [],
+ filters: {
+ bool: {
+ filter: [
+ {
+ bool: {
+ should: [
+ {
+ match_phrase: {
+ tags: 'org:google',
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ {
+ bool: {
+ should: [
+ {
+ bool: {
+ should: [
+ {
+ match_phrase: {
+ 'monitor.type': 'http',
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ {
+ bool: {
+ should: [
+ {
+ match_phrase: {
+ 'monitor.type': 'tcp',
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ ],
+ },
+ },
+ };
+ await getMonitorStatus({
+ callES,
+ dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS,
+ ...clientParameters,
+ });
+ expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1);
+ const [, params] = esMock.callAsCurrentUser.mock.calls[0];
+ expect(params).toMatchInlineSnapshot(`
+ Object {
+ "body": Object {
+ "aggs": Object {
+ "monitors": Object {
+ "aggs": Object {
+ "fields": Object {
+ "top_hits": Object {
+ "size": 1,
+ },
+ },
+ },
+ "composite": Object {
+ "size": 2000,
+ "sources": Array [
+ Object {
+ "monitorId": Object {
+ "terms": Object {
+ "field": "monitor.id",
+ },
+ },
+ },
+ Object {
+ "status": Object {
+ "terms": Object {
+ "field": "monitor.status",
+ },
+ },
+ },
+ Object {
+ "location": Object {
+ "terms": Object {
+ "field": "observer.geo.name",
+ "missing_bucket": true,
+ },
+ },
+ },
+ ],
+ },
+ },
+ },
+ "query": Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "term": Object {
+ "monitor.status": "down",
+ },
+ },
+ Object {
+ "range": Object {
+ "@timestamp": Object {
+ "gte": "now-15m",
+ "lte": "now",
+ },
+ },
+ },
+ Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "tags": "org:google",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.type": "http",
+ },
+ },
+ ],
+ },
+ },
+ Object {
+ "bool": Object {
+ "minimum_should_match": 1,
+ "should": Array [
+ Object {
+ "match_phrase": Object {
+ "monitor.type": "tcp",
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ "size": 0,
+ },
+ "index": "heartbeat-8*",
+ }
+ `);
+ });
+
+ it('properly assigns filters for complex kuery filters object', async () => {
+ const [callES, esMock] = setupMockEsCompositeQuery(
+ [{ bucketCriteria: [] }],
+ genBucketItem
+ );
+ const clientParameters = {
+ timerange: {
+ from: 'now-15m',
+ to: 'now',
+ },
+ numTimes: 5,
+ locations: [],
+ filters: {
+ bool: {
+ filter: {
+ exists: {
+ field: 'monitor.status',
+ },
+ },
+ },
+ },
+ };
+ await getMonitorStatus({
+ callES,
+ dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS,
+ ...clientParameters,
+ });
+ expect(esMock.callAsCurrentUser).toHaveBeenCalledTimes(1);
+ const [, params] = esMock.callAsCurrentUser.mock.calls[0];
+ expect(params).toMatchInlineSnapshot(`
+ Object {
+ "body": Object {
+ "aggs": Object {
+ "monitors": Object {
+ "aggs": Object {
+ "fields": Object {
+ "top_hits": Object {
+ "size": 1,
+ },
+ },
+ },
+ "composite": Object {
+ "size": 2000,
+ "sources": Array [
+ Object {
+ "monitorId": Object {
+ "terms": Object {
+ "field": "monitor.id",
+ },
+ },
+ },
+ Object {
+ "status": Object {
+ "terms": Object {
+ "field": "monitor.status",
+ },
+ },
+ },
+ Object {
+ "location": Object {
+ "terms": Object {
+ "field": "observer.geo.name",
+ "missing_bucket": true,
+ },
+ },
+ },
+ ],
+ },
+ },
+ },
+ "query": Object {
+ "bool": Object {
+ "filter": Array [
+ Object {
+ "term": Object {
+ "monitor.status": "down",
+ },
+ },
+ Object {
+ "range": Object {
+ "@timestamp": Object {
+ "gte": "now-15m",
+ "lte": "now",
+ },
+ },
+ },
+ Object {
+ "bool": Object {
+ "filter": Object {
+ "exists": Object {
+ "field": "monitor.status",
+ },
+ },
+ },
+ },
+ ],
+ },
+ },
+ "size": 0,
+ },
+ "index": "heartbeat-8*",
+ }
+ `);
+ });
+
it('fetches single page of results', async () => {
const [callES, esMock] = setupMockEsCompositeQuery(
[
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts
index 0801fc5769363..f78048100b998 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts
@@ -47,6 +47,11 @@ export const getMonitorAvailability: UMElasticsearchQueryFn<
const gte = `now-${range}${rangeUnit}`;
+ let parsedFilters: any;
+ if (filters) {
+ parsedFilters = JSON.parse(filters);
+ }
+
do {
const esParams: any = {
index: dynamicSettings.heartbeatIndices,
@@ -62,6 +67,8 @@ export const getMonitorAvailability: UMElasticsearchQueryFn<
},
},
},
+ // append user filters, if defined
+ ...(parsedFilters?.bool ? [parsedFilters] : []),
],
},
},
@@ -139,11 +146,6 @@ export const getMonitorAvailability: UMElasticsearchQueryFn<
},
};
- if (filters) {
- const parsedFilter = JSON.parse(filters);
- esParams.body.query.bool = { ...esParams.body.query.bool, ...parsedFilter.bool };
- }
-
if (afterKey) {
esParams.body.aggs.monitors.composite.after = afterKey;
}
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
index beed8e8335314..caf505610e991 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
@@ -71,6 +71,8 @@ export const getMonitorStatus: UMElasticsearchQueryFn<
},
},
},
+ // append user filters, if defined
+ ...(filters?.bool ? [filters] : []),
],
},
},
@@ -116,10 +118,6 @@ export const getMonitorStatus: UMElasticsearchQueryFn<
},
};
- if (filters?.bool) {
- esParams.body.query.bool = Object.assign({}, esParams.body.query.bool, filters.bool);
- }
-
/**
* Perform a logical `and` against the selected location filters.
*/
diff --git a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js
index a996910d4787a..10754d20118e9 100644
--- a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js
+++ b/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js
@@ -13,31 +13,62 @@ export default function ({ getPageObjects, getService }) {
const filterBar = getService('filterBar');
describe('tooltip filter actions', () => {
- before(async () => {
+ async function loadDashboardAndOpenTooltip() {
await kibanaServer.uiSettings.replace({
defaultIndex: 'c698b940-e149-11e8-a35a-370a8516603a',
});
await PageObjects.common.navigateToApp('dashboard');
+ await PageObjects.dashboard.preserveCrossAppState();
await PageObjects.dashboard.loadSavedDashboard('dash for tooltip filter action test');
await PageObjects.maps.lockTooltipAtPosition(200, -200);
- });
+ }
+
+ describe('apply filter to current view', () => {
+ before(async () => {
+ await loadDashboardAndOpenTooltip();
+ });
+
+ it('should display create filter button when tooltip is locked', async () => {
+ const exists = await testSubjects.exists('mapTooltipCreateFilterButton');
+ expect(exists).to.be(true);
+ });
+
+ it('should create filters when create filter button is clicked', async () => {
+ await testSubjects.click('mapTooltipCreateFilterButton');
+ await testSubjects.click('applyFiltersPopoverButton');
+
+ // TODO: Fix me #64861
+ // const hasSourceFilter = await filterBar.hasFilter('name', 'charlie');
+ // expect(hasSourceFilter).to.be(true);
- it('should display create filter button when tooltip is locked', async () => {
- const exists = await testSubjects.exists('mapTooltipCreateFilterButton');
- expect(exists).to.be(true);
+ const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
+ expect(hasJoinFilter).to.be(true);
+ });
});
- it('should create filters when create filter button is clicked', async () => {
- await testSubjects.click('mapTooltipCreateFilterButton');
- await testSubjects.click('applyFiltersPopoverButton');
+ describe('panel actions', () => {
+ before(async () => {
+ await loadDashboardAndOpenTooltip();
+ });
+
+ it('should display more actions button when tooltip is locked', async () => {
+ const exists = await testSubjects.exists('mapTooltipMoreActionsButton');
+ expect(exists).to.be(true);
+ });
+
+ it('should trigger drilldown action when clicked', async () => {
+ await testSubjects.click('mapTooltipMoreActionsButton');
+ await testSubjects.click('mapFilterActionButton__drilldown1');
- // TODO: Fix me #64861
- // const hasSourceFilter = await filterBar.hasFilter('name', 'charlie');
- // expect(hasSourceFilter).to.be(true);
+ // Assert on new dashboard with filter from action
+ await PageObjects.dashboard.waitForRenderComplete();
+ const panelCount = await PageObjects.dashboard.getPanelCount();
+ expect(panelCount).to.equal(2);
- const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
- expect(hasJoinFilter).to.be(true);
+ const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
+ expect(hasJoinFilter).to.be(true);
+ });
});
});
}
diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json
index 198174bccb286..0f1fd3c09d706 100644
--- a/x-pack/test/functional/es_archives/maps/kibana/data.json
+++ b/x-pack/test/functional/es_archives/maps/kibana/data.json
@@ -1048,7 +1048,7 @@
"title" : "dash for tooltip filter action test",
"hits" : 0,
"description" : "Zoomed in so entire screen is covered by filter so click to open tooltip can not miss.",
- "panelsJSON" : "[{\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":26,\"i\":\"1\"},\"version\":\"8.0.0\",\"panelIndex\":\"1\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":-1.31919,\"lon\":59.53306,\"zoom\":9.67},\"isLayerTOCOpen\":false,\"openTOCDetails\":[\"n1t6f\"]},\"panelRefName\":\"panel_0\"}]",
+ "panelsJSON" : "[{\"version\":\"8.0.0\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":26,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":-1.31919,\"lon\":59.53306,\"zoom\":9.67},\"isLayerTOCOpen\":false,\"openTOCDetails\":[\"n1t6f\"],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"669a3521-1215-4228-9ced-77e2edf5ad17\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"drilldown1\",\"config\":{\"dashboardId\":\"19906970-2e40-11e9-85cb-6965aae20f13\",\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_0\"}]",
"optionsJSON" : "{\"useMargins\":true,\"hidePanelTitles\":false}",
"version" : 1,
"timeRestore" : true,
@@ -1071,9 +1071,9 @@
}
],
"migrationVersion" : {
- "dashboard" : "7.0.0"
+ "dashboard" : "7.3.0"
},
- "updated_at" : "2019-06-14T14:09:25.039Z"
+ "updated_at" : "2020-08-26T14:32:27.854Z"
}
}
}
diff --git a/x-pack/test/licensing_plugin/public/feature_usage.ts b/x-pack/test/licensing_plugin/public/feature_usage.ts
new file mode 100644
index 0000000000000..15d302d71bfab
--- /dev/null
+++ b/x-pack/test/licensing_plugin/public/feature_usage.ts
@@ -0,0 +1,82 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import expect from '@kbn/expect';
+import { FtrProviderContext } from '../services';
+import {
+ LicensingPluginSetup,
+ LicensingPluginStart,
+ LicenseType,
+} from '../../../plugins/licensing/public';
+import '../../../../test/plugin_functional/plugins/core_provider_plugin/types';
+
+interface FeatureUsage {
+ last_used?: number;
+ license_level: LicenseType;
+ name: string;
+}
+
+// eslint-disable-next-line import/no-default-export
+export default function (ftrContext: FtrProviderContext) {
+ const { getService, getPageObjects } = ftrContext;
+ const supertest = getService('supertest');
+ const browser = getService('browser');
+ const PageObjects = getPageObjects(['common', 'security']);
+
+ const registerFeature = async (featureName: string, licenseType: LicenseType) => {
+ await browser.executeAsync(
+ async (feature, type, cb) => {
+ const { setup } = window._coreProvider;
+ const licensing: LicensingPluginSetup = setup.plugins.licensing;
+ await licensing.featureUsage.register(feature, type);
+ cb();
+ },
+ featureName,
+ licenseType
+ );
+ };
+
+ const notifyFeatureUsage = async (featureName: string, lastUsed: number) => {
+ await browser.executeAsync(
+ async (feature, time, cb) => {
+ const { start } = window._coreProvider;
+ const licensing: LicensingPluginStart = start.plugins.licensing;
+ await licensing.featureUsage.notifyUsage(feature, time);
+ cb();
+ },
+ featureName,
+ lastUsed
+ );
+ };
+
+ describe('feature_usage API', () => {
+ before(async () => {
+ await PageObjects.security.login();
+ });
+
+ it('allows to register features to the server', async () => {
+ await registerFeature('test-client-A', 'gold');
+ await registerFeature('test-client-B', 'enterprise');
+
+ const response = await supertest.get('/api/licensing/feature_usage').expect(200);
+ const features = response.body.features.map(({ name }: FeatureUsage) => name);
+
+ expect(features).to.contain('test-client-A');
+ expect(features).to.contain('test-client-B');
+ });
+
+ it('allows to notify feature usage', async () => {
+ const now = new Date();
+
+ await notifyFeatureUsage('test-client-A', now.getTime());
+
+ const response = await supertest.get('/api/licensing/feature_usage').expect(200);
+ const features = response.body.features as FeatureUsage[];
+
+ expect(features.find((f) => f.name === 'test-client-A')?.last_used).to.be(now.toISOString());
+ expect(features.find((f) => f.name === 'test-client-B')?.last_used).to.be(null);
+ });
+ });
+}
diff --git a/x-pack/test/licensing_plugin/public/index.ts b/x-pack/test/licensing_plugin/public/index.ts
index 86a3c21cfdb39..268a74c56bd72 100644
--- a/x-pack/test/licensing_plugin/public/index.ts
+++ b/x-pack/test/licensing_plugin/public/index.ts
@@ -10,6 +10,7 @@ import { FtrProviderContext } from '../services';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Licensing plugin public client', function () {
this.tags('ciGroup2');
+ loadTestFile(require.resolve('./feature_usage'));
// MUST BE LAST! CHANGES LICENSE TYPE!
loadTestFile(require.resolve('./updates'));
});
diff --git a/yarn.lock b/yarn.lock
index 496331aba0485..0d8ae918f27dc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3643,13 +3643,6 @@
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.43.tgz#e9b4992817e0b6c5efaa7d6e5bb2cee4d73eab58"
integrity sha512-t9ZmXOcpVxywRw86YtIC54g7M9puRh8hFedRvVfHKf5YyOP6pSxA0TvpXpfseXSCInoW4P7bggTrSDiUOs4g5w==
-"@types/decompress@^4.2.3":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/@types/decompress/-/decompress-4.2.3.tgz#98eed48af80001038aa05690b2094915f296fe65"
- integrity sha512-W24e3Ycz1UZPgr1ZEDHlK4XnvOr+CpJH3qNsFeqXwwlW/9END9gxn3oJSsp7gYdiQxrXUHwUUd3xuzVz37MrZQ==
- dependencies:
- "@types/node" "*"
-
"@types/dedent@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@types/dedent/-/dedent-0.7.0.tgz#155f339ca404e6dd90b9ce46a3f78fd69ca9b050"
@@ -3716,6 +3709,11 @@
resolved "https://registry.yarnpkg.com/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5"
integrity sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==
+"@types/extract-zip@^1.6.2":
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/@types/extract-zip/-/extract-zip-1.6.2.tgz#5c7eb441c41136167a42b88b64051e6260c29e86"
+ integrity sha1-XH60QcQRNhZ6QriLZAUeYmDCnoY=
+
"@types/fancy-log@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.1.tgz#dd94fbc8c2e2ab8ab402ca8d04bb8c34965f0696"
@@ -7343,19 +7341,14 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
-bl@^1.0.0:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
- integrity sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=
- dependencies:
- readable-stream "^2.0.5"
-
-bl@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
- integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
+bl@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489"
+ integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==
dependencies:
- readable-stream "^3.0.1"
+ buffer "^5.5.0"
+ inherits "^2.0.4"
+ readable-stream "^3.4.0"
block-stream@*:
version "0.0.9"
@@ -7717,19 +7710,6 @@ btoa-lite@^1.0.0:
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc=
-buffer-alloc-unsafe@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
- integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-
-buffer-alloc@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
- integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
- dependencies:
- buffer-alloc-unsafe "^1.1.0"
- buffer-fill "^1.0.0"
-
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@@ -7750,11 +7730,6 @@ buffer-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe"
integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74=
-buffer-fill@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
- integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
-
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -7787,7 +7762,7 @@ buffer@^5.1.0, buffer@^5.2.0:
base64-js "^1.0.2"
ieee754 "^1.1.4"
-buffer@^5.2.1:
+buffer@^5.5.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786"
integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==
@@ -8450,7 +8425,7 @@ chokidar@^3.2.2, chokidar@^3.4.0:
optionalDependencies:
fsevents "~2.1.2"
-chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
+chownr@^1.1.1, chownr@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
@@ -10334,59 +10309,6 @@ decompress-response@^5.0.0:
dependencies:
mimic-response "^2.0.0"
-decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
- integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
- dependencies:
- file-type "^5.2.0"
- is-stream "^1.1.0"
- tar-stream "^1.5.2"
-
-decompress-tarbz2@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
- integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
- dependencies:
- decompress-tar "^4.1.0"
- file-type "^6.1.0"
- is-stream "^1.1.0"
- seek-bzip "^1.0.5"
- unbzip2-stream "^1.0.9"
-
-decompress-targz@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
- integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
- dependencies:
- decompress-tar "^4.1.1"
- file-type "^5.2.0"
- is-stream "^1.1.0"
-
-decompress-unzip@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
- integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
- dependencies:
- file-type "^3.8.0"
- get-stream "^2.2.0"
- pify "^2.3.0"
- yauzl "^2.4.2"
-
-decompress@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118"
- integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==
- dependencies:
- decompress-tar "^4.0.0"
- decompress-tarbz2 "^4.0.0"
- decompress-targz "^4.0.0"
- decompress-unzip "^4.0.1"
- graceful-fs "^4.1.10"
- make-dir "^1.0.0"
- pify "^2.3.0"
- strip-dirs "^2.0.0"
-
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@@ -12698,6 +12620,17 @@ extract-zip@^2.0.0:
optionalDependencies:
"@types/yauzl" "^2.9.1"
+extract-zip@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+ integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+ dependencies:
+ debug "^4.1.1"
+ get-stream "^5.1.0"
+ yauzl "^2.10.0"
+ optionalDependencies:
+ "@types/yauzl" "^2.9.1"
+
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -12958,21 +12891,6 @@ file-type@^10.9.0:
resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.9.0.tgz#f6c12c7cb9e6b8aeefd6917555fd4f9eadf31891"
integrity sha512-9C5qtGR/fNibHC5gzuMmmgnjH3QDDLKMa8lYe9CiZVmAnI4aUaoMh40QyUPzzs0RYo837SOBKh7TYwle4G8E4w==
-file-type@^3.8.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
- integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
-
-file-type@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
- integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
-
-file-type@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
- integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
-
file-type@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18"
@@ -13778,14 +13696,6 @@ get-stream@3.0.0, get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
-get-stream@^2.2.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
- integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
- dependencies:
- object-assign "^4.0.1"
- pinkie-promise "^2.0.0"
-
get-stream@^4.0.0, get-stream@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
@@ -14394,7 +14304,7 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
-graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4:
+graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
@@ -16483,11 +16393,6 @@ is-native@^1.0.1:
is-nil "^1.0.0"
to-source-code "^1.0.0"
-is-natural-number@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
- integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
-
is-negated-glob@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2"
@@ -18099,10 +18004,10 @@ kdbush@^3.0.0:
resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0"
integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
-kea@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/kea/-/kea-2.1.1.tgz#6e3c65c4873b67d270a2ec7bf73b0d178937234c"
- integrity sha512-W9o4lHLOcEDIu3ASHPrWJJJzL1bMkGyxaHn9kuaDgI96ztBShVrf52R0QPGlQ2k9ca3XnkB/dnVHio1UB8kGWA==
+kea@2.2.0-rc.4:
+ version "2.2.0-rc.4"
+ resolved "https://registry.yarnpkg.com/kea/-/kea-2.2.0-rc.4.tgz#cc0376950530a6751f73387c4b25a39efa1faa77"
+ integrity sha512-pYuwaCiJkBvHZShi8kqhk8dC4DjeELdK51Lw7Pn0tNdJgZJDF6COhsUiF/yrh9d7woNYDxKfuxH+QWZFfo8PkA==
kew@~0.1.7:
version "0.1.7"
@@ -19900,6 +19805,11 @@ mixin-object@^2.0.1:
for-in "^0.1.3"
is-extendable "^0.1.1"
+mkdirp-classic@^0.5.2:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
+ integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
+
mkdirp@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
@@ -22823,14 +22733,6 @@ puid@1.0.7:
resolved "https://registry.yarnpkg.com/puid/-/puid-1.0.7.tgz#fa638a737d7b20419059d93965aed36ca20e1c84"
integrity sha1-+mOKc317IEGQWdk5Za7TbKIOHIQ=
-pump@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
- integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
pump@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
@@ -24064,7 +23966,7 @@ read-pkg@^5.2.0:
parse-json "^5.0.0"
type-fest "^0.6.0"
-"readable-stream@1 || 2", readable-stream@^2.3.0, readable-stream@^2.3.7, readable-stream@~2.3.3:
+"readable-stream@1 || 2", readable-stream@^2.3.7, readable-stream@~2.3.3:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -24087,7 +23989,7 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0":
isarray "0.0.1"
string_decoder "~0.10.x"
-"readable-stream@2 || 3", readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
+"readable-stream@2 || 3", readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
@@ -25446,13 +25348,6 @@ seedrandom@^3.0.5:
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
-seek-bzip@^1.0.5:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4"
- integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==
- dependencies:
- commander "^2.8.1"
-
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -26824,13 +26719,6 @@ strip-bom@^4.0.0:
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
-strip-dirs@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
- integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
- dependencies:
- is-natural-number "^4.0.1"
-
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -27286,45 +27174,22 @@ tape@^5.0.1:
string.prototype.trim "^1.2.1"
through "^2.3.8"
-tar-fs@^1.16.3:
- version "1.16.3"
- resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509"
- integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==
- dependencies:
- chownr "^1.0.1"
- mkdirp "^0.5.1"
- pump "^1.0.0"
- tar-stream "^1.1.2"
-
-tar-stream@^1.1.2:
- version "1.5.5"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55"
- integrity sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==
- dependencies:
- bl "^1.0.0"
- end-of-stream "^1.0.0"
- readable-stream "^2.0.0"
- xtend "^4.0.0"
-
-tar-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
- integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
+tar-fs@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5"
+ integrity sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==
dependencies:
- bl "^1.0.0"
- buffer-alloc "^1.2.0"
- end-of-stream "^1.0.0"
- fs-constants "^1.0.0"
- readable-stream "^2.3.0"
- to-buffer "^1.1.1"
- xtend "^4.0.0"
+ chownr "^1.1.1"
+ mkdirp-classic "^0.5.2"
+ pump "^3.0.0"
+ tar-stream "^2.0.0"
-tar-stream@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
- integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
+tar-stream@^2.0.0, tar-stream@^2.1.0:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41"
+ integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA==
dependencies:
- bl "^3.0.0"
+ bl "^4.0.1"
end-of-stream "^1.4.1"
fs-constants "^1.0.0"
inherits "^2.0.3"
@@ -27748,11 +27613,6 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
-to-buffer@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
- integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
-
to-camel-case@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46"
@@ -28301,14 +28161,6 @@ uid-safe@2.1.5:
dependencies:
random-bytes "~1.0.0"
-unbzip2-stream@^1.0.9:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
- integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==
- dependencies:
- buffer "^5.2.1"
- through "^2.3.8"
-
unc-path-regex@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
@@ -30598,7 +30450,7 @@ yargs@~3.10.0:
decamelize "^1.0.0"
window-size "0.1.0"
-yauzl@2.10.0, yauzl@^2.10.0, yauzl@^2.4.2:
+yauzl@2.10.0, yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
| |