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 (
+
+
+
+
+ {label}
+
+
+ );
+ }
+
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/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"
}
}
}