[Maps] allow feature editing for document layers with "applyGlobalTime", "applyGlobalQuery", and joins (#124803)

* #124061 - feature editing updated logic for documents layer

* 124061 - updates for disabling joins

* 124061 - refactoring; Excluding filtering from when enabling editing mode

* 124061 - fixes for failed tests

* 124061 - fixed test for JoinEditor

* 124061 - global time checkbox message fix

* 124071 - updated snapshot for JoinEditor

* 124061 - excluded applyGlobalQuery/applyGlobalTime from es_source in case of editing layer active

* 124061 - refactoring

* 124061 - fix for test

* 124061 - refactoring; Added message for disabled filter

* 124061 - replacing variables

* 124061 - fixed test; refactoring

* 124061 - refactoring; fixed tests

* 124061 - refactoring; fixed tests

* 124061 - refactoring; removed reuse isFeatureEditorOpenForLayer

* 124061 - fixed tests

* 124061 - removed isFeatureEditorOpenForLayer property

* 124061 - buildVectorRequestMeta updates

* 124061 - fixes for CI checks

* 124061 - refactoring

* 124061 - fixed test

* 124061 - refactoring; fixed conflict

* 124061 - syncDataLLayer called inside updateEditLayer

* 124061 - reverting changes for Join editor

* 124061 - removing unused isFeatureEditorOpenForLayer

* 124061 - updating snap

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Max Kovalev 2022-04-29 18:27:07 +03:00 committed by GitHub
parent ab795cca6b
commit a2acfe5117
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 130 additions and 57 deletions

View file

@ -96,12 +96,6 @@ To open an existing index for drawing:
. Click *Add layer*.
. Set *Scaling* to *Limit results to 10,000*.
. In **Filtering**:
** Clear the *Apply global search to layer data* checkbox.
** If your data view contains a default time field, clear the *Apply global time to layer data* checkbox.
. Click *Save & close*.
. In the legend, click the layer name and select *Edit features*.

View file

@ -41,6 +41,7 @@ export type VectorSourceRequestMeta = DataFilters & {
sourceQuery?: Query;
sourceMeta: object | null;
isForceRefresh: boolean;
isFeatureEditorOpenForLayer: boolean;
};
export type VectorJoinSourceRequestMeta = Omit<VectorSourceRequestMeta, 'geogridPrecision'>;

View file

@ -24,6 +24,7 @@ import {
getDataRequestDescriptor,
getLayerById,
getLayerList,
getEditState,
} from '../selectors/map_selectors';
import {
cancelRequest,
@ -67,6 +68,7 @@ export type DataRequestContext = {
dataFilters: DataFilters;
forceRefreshDueToDrawing: boolean; // Boolean signaling data request triggered by a user updating layer features via drawing tools. When true, layer will re-load regardless of "source.applyForceRefresh" flag.
isForceRefresh: boolean; // Boolean signaling data request triggered by auto-refresh timer or user clicking refresh button. When true, layer will re-load only when "source.applyForceRefresh" flag is set to true.
isFeatureEditorOpenForLayer: boolean; // Boolean signaling that feature editor menu is open for a layer. When true, layer will ignore all global and layer filtering so drawn features are displayed and not filtered out.
};
export function clearDataRequests(layer: ILayer) {
@ -145,6 +147,7 @@ function getDataRequestContext(
dispatch(registerCancelCallback(requestToken, callback)),
forceRefreshDueToDrawing,
isForceRefresh,
isFeatureEditorOpenForLayer: getEditState(getState())?.layerId === layerId,
};
}

View file

@ -58,6 +58,7 @@ import {
autoFitToBounds,
syncDataForAllLayers,
syncDataForLayerDueToDrawing,
syncDataForLayerId,
} from './data_request_actions';
import { addLayer, addLayerWithoutDataSync } from './layer_actions';
import { MapSettings } from '../reducers/map';
@ -394,7 +395,7 @@ export function setEditLayerToSelectedLayer() {
}
export function updateEditLayer(layerId: string | null) {
return (dispatch: Dispatch) => {
return (dispatch: ThunkDispatch<MapStoreState, void, AnyAction>) => {
if (layerId !== null) {
dispatch({ type: SET_OPEN_TOOLTIPS, openTooltips: [] });
}
@ -406,6 +407,7 @@ export function updateEditLayer(layerId: string | null) {
type: UPDATE_EDIT_STATE,
editState: layerId ? { layerId } : undefined,
});
dispatch(syncDataForLayerId(layerId, false));
};
}

View file

@ -20,6 +20,7 @@ export class MockSyncContext implements DataRequestContext {
updateSourceData: (newData: unknown) => void;
forceRefreshDueToDrawing: boolean;
isForceRefresh: boolean;
isFeatureEditorOpenForLayer: boolean;
constructor({ dataFilters }: { dataFilters: Partial<DataFilters> }) {
const mapFilters: DataFilters = {
@ -44,5 +45,6 @@ export class MockSyncContext implements DataRequestContext {
this.updateSourceData = sinon.spy();
this.forceRefreshDueToDrawing = false;
this.isForceRefresh = false;
this.isFeatureEditorOpenForLayer = false;
}
}

View file

@ -16,7 +16,8 @@ export function buildVectorRequestMeta(
fieldNames: string[],
dataFilters: DataFilters,
sourceQuery: Query | null | undefined,
isForceRefresh: boolean
isForceRefresh: boolean,
isFeatureEditorOpenForLayer: boolean
): VectorSourceRequestMeta {
return {
...dataFilters,
@ -28,5 +29,6 @@ export function buildVectorRequestMeta(
sourceMeta: source.getSyncMeta(),
applyForceRefresh: source.isESSource() ? source.getApplyForceRefresh() : false,
isForceRefresh,
isFeatureEditorOpenForLayer,
};
}

View file

@ -89,7 +89,8 @@ export class HeatmapLayer extends AbstractLayer {
this.getSource().getFieldNames(),
syncContext.dataFilters,
this.getQuery(),
syncContext.isForceRefresh
syncContext.isForceRefresh,
syncContext.isFeatureEditorOpenForLayer
),
source: this.getSource() as IMvtVectorSource,
syncContext,

View file

@ -298,7 +298,8 @@ export class BlendedVectorLayer extends GeoJsonVectorLayer implements IVectorLay
syncContext.isForceRefresh,
syncContext.dataFilters,
this.getSource(),
this.getCurrentStyle()
this.getCurrentStyle(),
syncContext.isFeatureEditorOpenForLayer
);
const source = this.getSource();

View file

@ -22,7 +22,13 @@ export async function syncBoundsData({
source: IVectorSource;
sourceQuery: Query | null;
}): Promise<MapExtent | null> {
const { startLoading, stopLoading, registerCancelCallback, dataFilters } = syncContext;
const {
startLoading,
stopLoading,
registerCancelCallback,
dataFilters,
isFeatureEditorOpenForLayer,
} = syncContext;
const requestToken = Symbol(`${SOURCE_BOUNDS_DATA_REQUEST_ID}-${layerId}`);
@ -37,6 +43,7 @@ export async function syncBoundsData({
joinKeyFilter: dataFilters.joinKeyFilter,
applyGlobalQuery: source.getApplyGlobalQuery(),
applyGlobalTime: source.getApplyGlobalTime(),
isFeatureEditorOpenForLayer,
};
let bounds = null;

View file

@ -237,7 +237,8 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer {
syncContext.isForceRefresh,
syncContext.dataFilters,
source,
style
style,
syncContext.isFeatureEditorOpenForLayer
),
syncContext,
source,

View file

@ -59,6 +59,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
},
source: mockSource,
syncContext,
@ -90,6 +91,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({
@ -131,6 +133,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({
@ -169,6 +172,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({
@ -215,6 +219,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({
@ -253,6 +258,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({
@ -291,6 +297,7 @@ describe('syncMvtSourceData', () => {
fieldNames: [],
sourceMeta: {},
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
await syncMvtSourceData({

View file

@ -232,7 +232,8 @@ export class MvtVectorLayer extends AbstractVectorLayer {
syncContext.isForceRefresh,
syncContext.dataFilters,
this.getSource(),
this.getCurrentStyle()
this.getCurrentStyle(),
syncContext.isFeatureEditorOpenForLayer
),
source: this.getSource() as IMvtVectorSource,
syncContext,

View file

@ -366,7 +366,8 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
isForceRefresh: boolean,
dataFilters: DataFilters,
source: IVectorSource,
style: IVectorStyle
style: IVectorStyle,
isFeatureEditorOpenForLayer: boolean
): Promise<VectorSourceRequestMeta> {
const fieldNames = [
...source.getFieldNames(),
@ -378,7 +379,14 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
if (timesliceMaskFieldName) {
fieldNames.push(timesliceMaskFieldName);
}
return buildVectorRequestMeta(source, fieldNames, dataFilters, this.getQuery(), isForceRefresh);
return buildVectorRequestMeta(
source,
fieldNames,
dataFilters,
this.getQuery(),
isForceRefresh,
isFeatureEditorOpenForLayer
);
}
async _syncSourceStyleMeta(
@ -542,6 +550,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
registerCancelCallback,
dataFilters,
isForceRefresh,
isFeatureEditorOpenForLayer,
}: { join: InnerJoin } & DataRequestContext): Promise<JoinState> {
const joinSource = join.getRightJoinSource();
const sourceDataId = join.getSourceDataRequestId();
@ -552,7 +561,8 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
joinSource.getFieldNames(),
dataFilters,
joinSource.getWhereQuery(),
isForceRefresh
isForceRefresh,
isFeatureEditorOpenForLayer
) as VectorJoinSourceRequestMeta;
const prevDataRequest = this.getDataRequest(sourceDataId);

View file

@ -178,6 +178,7 @@ describe('ESGeoGridSource', () => {
sourceMeta: null,
zoom: 0,
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
describe('getGeoJsonWithMeta', () => {

View file

@ -106,6 +106,7 @@ describe('ESSearchSource', () => {
applyGlobalTime: true,
applyForceRefresh: true,
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
};
it('Should only include required props', async () => {

View file

@ -230,7 +230,17 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
allFilters.push(extentFilter);
}
if (searchFilters.applyGlobalTime && (await this.isTimeAware())) {
let isFeatureEditorOpenForLayer = false;
if ('isFeatureEditorOpenForLayer' in searchFilters) {
isFeatureEditorOpenForLayer = searchFilters.isFeatureEditorOpenForLayer;
}
if (
searchFilters.applyGlobalTime &&
(await this.isTimeAware()) &&
!isFeatureEditorOpenForLayer
) {
const timeRange = searchFilters.timeslice
? {
from: new Date(searchFilters.timeslice.from).toISOString(),
@ -250,11 +260,11 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
searchSource.setField('index', indexPattern);
searchSource.setField('size', limit);
searchSource.setField('filter', allFilters);
if (searchFilters.applyGlobalQuery) {
if (searchFilters.applyGlobalQuery && !isFeatureEditorOpenForLayer) {
searchSource.setField('query', searchFilters.query);
}
if (searchFilters.sourceQuery) {
if (searchFilters.sourceQuery && !isFeatureEditorOpenForLayer) {
const layerSearchSource = searchService.searchSource.createEmpty();
layerSearchSource.setField('index', indexPattern);

View file

@ -42,6 +42,7 @@ export interface BoundsRequestMeta {
sourceQuery?: Query;
timeFilters: TimeRange;
timeslice?: Timeslice;
isFeatureEditorOpenForLayer: boolean;
joinKeyFilter?: Filter;
}

View file

@ -86,6 +86,10 @@ export async function canSkipSourceUpdate({
return false;
}
if (prevMeta.isFeatureEditorOpenForLayer !== nextRequestMeta.isFeatureEditorOpenForLayer) {
return false;
}
let updateDueToApplyGlobalTime = false;
let updateDueToTime = false;
let updateDueToTimeslice = false;

View file

@ -13,27 +13,37 @@ interface Props {
applyGlobalQuery: boolean;
label: string;
setApplyGlobalQuery: (applyGlobalQuery: boolean) => void;
isFeatureEditorOpenForLayer?: boolean;
}
export function GlobalFilterCheckbox({ applyGlobalQuery, label, setApplyGlobalQuery }: Props) {
export function GlobalFilterCheckbox({
applyGlobalQuery,
label,
setApplyGlobalQuery,
isFeatureEditorOpenForLayer,
}: Props) {
const onApplyGlobalQueryChange = (event: EuiSwitchEvent) => {
setApplyGlobalQuery(event.target.checked);
};
const tooltipMessage = isFeatureEditorOpenForLayer
? i18n.translate('xpack.maps.filterEditor.isGlobalSearchNotApplied', {
defaultMessage: 'Global search is not applied to the layer while editing features',
})
: i18n.translate('xpack.maps.filterEditor.applyGlobalFilterHelp', {
defaultMessage: 'When enabled, results narrowed by global search',
});
return (
<EuiFormRow display="columnCompressedSwitch">
<EuiToolTip
position="top"
content={i18n.translate('xpack.maps.filterEditor.applyGlobalFilterHelp', {
defaultMessage: 'When enabled, results narrowed by global search',
})}
>
<EuiToolTip position="top" content={tooltipMessage}>
<EuiSwitch
label={label}
checked={applyGlobalQuery}
checked={isFeatureEditorOpenForLayer ? false : applyGlobalQuery}
onChange={onApplyGlobalQueryChange}
data-test-subj="mapLayerPanelApplyGlobalQueryCheckbox"
compressed
disabled={isFeatureEditorOpenForLayer}
/>
</EuiToolTip>
</EuiFormRow>

View file

@ -12,27 +12,37 @@ interface Props {
applyGlobalTime: boolean;
label: string;
setApplyGlobalTime: (applyGlobalTime: boolean) => void;
isFeatureEditorOpenForLayer?: boolean;
}
export function GlobalTimeCheckbox({ applyGlobalTime, label, setApplyGlobalTime }: Props) {
export function GlobalTimeCheckbox({
applyGlobalTime,
label,
setApplyGlobalTime,
isFeatureEditorOpenForLayer,
}: Props) {
const onApplyGlobalTimeChange = (event: EuiSwitchEvent) => {
setApplyGlobalTime(event.target.checked);
};
const tooltipMessage = isFeatureEditorOpenForLayer
? i18n.translate('xpack.maps.filterEditor.isGlobalTimeNotApplied', {
defaultMessage: 'Global time is not applied to the layer while editing features',
})
: i18n.translate('xpack.maps.filterEditor.applyGlobalTimeHelp', {
defaultMessage: 'When enabled, results narrowed by global time',
});
return (
<EuiFormRow display="columnCompressedSwitch">
<EuiToolTip
position="top"
content={i18n.translate('xpack.maps.filterEditor.applyGlobalTimeHelp', {
defaultMessage: 'When enabled, results narrowed by global time',
})}
>
<EuiToolTip position="top" content={tooltipMessage}>
<EuiSwitch
label={label}
checked={applyGlobalTime}
checked={isFeatureEditorOpenForLayer ? false : applyGlobalTime}
onChange={onApplyGlobalTimeChange}
data-test-subj="mapLayerPanelApplyGlobalTimeCheckbox"
compressed
disabled={isFeatureEditorOpenForLayer}
/>
</EuiToolTip>
</EuiFormRow>

View file

@ -35,6 +35,7 @@ export interface Props {
layer: ILayer;
setLayerQuery: (id: string, query: Query) => void;
updateSourceProp: (layerId: string, propName: string, value: unknown) => void;
isFeatureEditorOpenForLayer: boolean;
}
interface State {
@ -157,6 +158,15 @@ export class FilterEditor extends Component<Props, State> {
}
_renderQuery() {
if (this.props.isFeatureEditorOpenForLayer) {
return (
<FormattedMessage
id="xpack.maps.layerPanel.filterEditor.isLayerFilterNotApplied"
defaultMessage="Layer filter is not applied while editing features"
/>
);
}
const query = this.props.layer.getQuery();
if (!query || !query.query) {
return (
@ -199,6 +209,7 @@ export class FilterEditor extends Component<Props, State> {
onClick={this._toggle}
data-test-subj="mapLayerPanelOpenFilterEditorButton"
iconType={openButtonIcon}
disabled={this.props.isFeatureEditorOpenForLayer}
>
{openButtonLabel}
</EuiButtonEmpty>
@ -213,6 +224,7 @@ export class FilterEditor extends Component<Props, State> {
})}
applyGlobalTime={this.props.layer.getSource().getApplyGlobalTime()}
setApplyGlobalTime={this._onApplyGlobalTimeChange}
isFeatureEditorOpenForLayer={this.props.isFeatureEditorOpenForLayer}
/>
) : null;
@ -244,6 +256,7 @@ export class FilterEditor extends Component<Props, State> {
})}
applyGlobalQuery={this.props.layer.getSource().getApplyGlobalQuery()}
setApplyGlobalQuery={this._onApplyGlobalQueryChange}
isFeatureEditorOpenForLayer={this.props.isFeatureEditorOpenForLayer}
/>
{globalTimeCheckbox}

View file

@ -10,13 +10,15 @@ import { ThunkDispatch } from 'redux-thunk';
import { connect } from 'react-redux';
import type { Query } from '@kbn/data-plugin/public';
import { FilterEditor } from './filter_editor';
import { getSelectedLayer } from '../../../selectors/map_selectors';
import { getEditState, getSelectedLayer } from '../../../selectors/map_selectors';
import { setLayerQuery, updateSourceProp } from '../../../actions';
import { MapStoreState } from '../../../reducers/store';
function mapStateToProps(state: MapStoreState) {
const layer = getSelectedLayer(state)!;
return {
layer: getSelectedLayer(state)!,
layer,
isFeatureEditorOpenForLayer: getEditState(state)?.layerId === layer.getId(),
};
}

View file

@ -79,6 +79,7 @@ export function JoinEditor({ joins, layer, onChange, leftJoinFields, layerDispla
function renderContent() {
const disabledReason = layer.getJoinsDisabledReason();
return disabledReason ? (
<EuiCallOut color="warning">{disabledReason}</EuiCallOut>
) : (

View file

@ -11,7 +11,6 @@ exports[`TOCEntry is rendered 1`] = `
>
<Connect(TOCEntryActionsPopover)
displayName="layer 1"
editModeActiveForLayer={false}
escapedDisplayName="layer_1"
isEditButtonDisabled={false}
layer={
@ -94,7 +93,6 @@ exports[`TOCEntry props Should shade background when not selected layer 1`] = `
>
<Connect(TOCEntryActionsPopover)
displayName="layer 1"
editModeActiveForLayer={false}
escapedDisplayName="layer_1"
isEditButtonDisabled={false}
layer={
@ -177,7 +175,6 @@ exports[`TOCEntry props Should shade background when selected layer 1`] = `
>
<Connect(TOCEntryActionsPopover)
displayName="layer 1"
editModeActiveForLayer={false}
escapedDisplayName="layer_1"
isEditButtonDisabled={false}
layer={
@ -260,7 +257,6 @@ exports[`TOCEntry props isReadOnly 1`] = `
>
<Connect(TOCEntryActionsPopover)
displayName="layer 1"
editModeActiveForLayer={false}
escapedDisplayName="layer_1"
isEditButtonDisabled={false}
layer={
@ -328,7 +324,6 @@ exports[`TOCEntry props should display layer details when isLegendDetailsOpen is
>
<Connect(TOCEntryActionsPopover)
displayName="layer 1"
editModeActiveForLayer={false}
escapedDisplayName="layer_1"
isEditButtonDisabled={false}
layer={

View file

@ -44,7 +44,7 @@ function mapStateToProps(state: MapStoreState, ownProps: OwnProps): ReduxStatePr
isLegendDetailsOpen: getOpenTOCDetails(state).includes(ownProps.layer.getId()),
isEditButtonDisabled:
flyoutDisplay !== FLYOUT_STATE.NONE && flyoutDisplay !== FLYOUT_STATE.LAYER_PANEL,
editModeActiveForLayer: getEditState(state)?.layerId === ownProps.layer.getId(),
isFeatureEditorOpenForLayer: getEditState(state)?.layerId === ownProps.layer.getId(),
};
}

View file

@ -65,7 +65,7 @@ const defaultProps = {
isEditButtonDisabled: false,
hideTOCDetails: () => {},
showTOCDetails: () => {},
editModeActiveForLayer: false,
isFeatureEditorOpenForLayer: false,
cancelEditing: () => {},
};

View file

@ -31,7 +31,7 @@ export interface ReduxStateProps {
hasDirtyStateSelector: boolean;
isLegendDetailsOpen: boolean;
isEditButtonDisabled: boolean;
editModeActiveForLayer: boolean;
isFeatureEditorOpenForLayer: boolean;
}
export interface ReduxDispatchProps {
@ -282,7 +282,6 @@ export class TOCEntry extends Component<Props, State> {
openLayerSettings={this._openLayerPanelWithCheck}
isEditButtonDisabled={this.props.isEditButtonDisabled}
supportsFitToBounds={this.state.supportsFitToBounds}
editModeActiveForLayer={this.props.editModeActiveForLayer}
/>
{this._renderQuickActions()}
@ -317,7 +316,7 @@ export class TOCEntry extends Component<Props, State> {
'mapTocEntry-isSelected':
this.props.layer.isPreviewLayer() ||
(this.props.selectedLayer && this.props.selectedLayer.getId() === this.props.layer.getId()),
'mapTocEntry-isInEditingMode': this.props.editModeActiveForLayer,
'mapTocEntry-isInEditingMode': this.props.isFeatureEditorOpenForLayer,
});
return (
@ -334,7 +333,7 @@ export class TOCEntry extends Component<Props, State> {
{this._renderCancelModal()}
{this.props.editModeActiveForLayer && (
{this.props.isFeatureEditorOpenForLayer && (
<div className="mapTocEntry-isInEditingMode__row">
<EuiIcon type="vector" size="s" />
<span className="mapTocEntry-isInEditingMode__editFeatureText">

View file

@ -48,7 +48,6 @@ const defaultProps = {
enableShapeEditing: () => {},
enablePointEditing: () => {},
openLayerSettings: () => {},
editModeActiveForLayer: false,
numLayers: 2,
showThisLayerOnly: () => {},
};
@ -105,9 +104,7 @@ describe('TOCEntryActionsPopover', () => {
});
test('should disable Edit features when edit mode active for layer', async () => {
const component = shallow(
<TOCEntryActionsPopover {...defaultProps} editModeActiveForLayer={true} />
);
const component = shallow(<TOCEntryActionsPopover {...defaultProps} />);
// Ensure all promises resolve
await new Promise((resolve) => process.nextTick(resolve));

View file

@ -36,7 +36,6 @@ export interface Props {
showThisLayerOnly: (layerId: string) => void;
supportsFitToBounds: boolean;
toggleVisible: (layerId: string) => void;
editModeActiveForLayer: boolean;
numLayers: number;
}
@ -90,9 +89,7 @@ export class TOCEntryActionsPopover extends Component<Props, State> {
}
if (
(source as ESSearchSource).getApplyGlobalQuery() ||
(source as ESSearchSource).getSyncMeta().scalingType === SCALING_TYPES.CLUSTERS ||
(await vectorLayer.isFilteredByGlobalTime()) ||
vectorLayer.isPreviewLayer() ||
!vectorLayer.isVisible() ||
vectorLayer.hasJoins()
@ -194,9 +191,9 @@ export class TOCEntryActionsPopover extends Component<Props, State> {
? null
: i18n.translate('xpack.maps.layerTocActions.editFeaturesTooltip.disabledMessage', {
defaultMessage:
'Edit features only supported for document layers without clustering, term joins, time filtering, or global search.',
'Edit features is only supported for layers without clustering and term joins',
}),
disabled: !this.state.isFeatureEditingEnabled || this.props.editModeActiveForLayer,
disabled: !this.state.isFeatureEditingEnabled,
onClick: async () => {
this._closePopover();
const supportedShapeTypes = await (