mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[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:
parent
ab795cca6b
commit
a2acfe5117
29 changed files with 130 additions and 57 deletions
|
@ -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*.
|
||||
|
|
|
@ -41,6 +41,7 @@ export type VectorSourceRequestMeta = DataFilters & {
|
|||
sourceQuery?: Query;
|
||||
sourceMeta: object | null;
|
||||
isForceRefresh: boolean;
|
||||
isFeatureEditorOpenForLayer: boolean;
|
||||
};
|
||||
|
||||
export type VectorJoinSourceRequestMeta = Omit<VectorSourceRequestMeta, 'geogridPrecision'>;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -237,7 +237,8 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer {
|
|||
syncContext.isForceRefresh,
|
||||
syncContext.dataFilters,
|
||||
source,
|
||||
style
|
||||
style,
|
||||
syncContext.isFeatureEditorOpenForLayer
|
||||
),
|
||||
syncContext,
|
||||
source,
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -178,6 +178,7 @@ describe('ESGeoGridSource', () => {
|
|||
sourceMeta: null,
|
||||
zoom: 0,
|
||||
isForceRefresh: false,
|
||||
isFeatureEditorOpenForLayer: false,
|
||||
};
|
||||
|
||||
describe('getGeoJsonWithMeta', () => {
|
||||
|
|
|
@ -106,6 +106,7 @@ describe('ESSearchSource', () => {
|
|||
applyGlobalTime: true,
|
||||
applyForceRefresh: true,
|
||||
isForceRefresh: false,
|
||||
isFeatureEditorOpenForLayer: false,
|
||||
};
|
||||
|
||||
it('Should only include required props', async () => {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -42,6 +42,7 @@ export interface BoundsRequestMeta {
|
|||
sourceQuery?: Query;
|
||||
timeFilters: TimeRange;
|
||||
timeslice?: Timeslice;
|
||||
isFeatureEditorOpenForLayer: boolean;
|
||||
joinKeyFilter?: Filter;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
@ -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={
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ const defaultProps = {
|
|||
isEditButtonDisabled: false,
|
||||
hideTOCDetails: () => {},
|
||||
showTOCDetails: () => {},
|
||||
editModeActiveForLayer: false,
|
||||
isFeatureEditorOpenForLayer: false,
|
||||
cancelEditing: () => {},
|
||||
};
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue