Skip to content

Commit

Permalink
[Maps] add initial location option that fits to data bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
nreese committed Aug 6, 2020
1 parent b71b9c2 commit 95c05bb
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 29 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/maps/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export enum INITIAL_LOCATION {
LAST_SAVED_LOCATION = 'LAST_SAVED_LOCATION',
FIXED_LOCATION = 'FIXED_LOCATION',
BROWSER_LOCATION = 'BROWSER_LOCATION',
AUTO_FIT_TO_BOUNDS = 'AUTO_FIT_TO_BOUNDS',
}

export enum LAYER_WIZARD_CATEGORY {
Expand Down
33 changes: 31 additions & 2 deletions x-pack/plugins/maps/public/actions/data_request_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { Dispatch } from 'redux';
import bbox from '@turf/bbox';
import uuid from 'uuid/v4';
import { multiPoint } from '@turf/helpers';
import { FeatureCollection } from 'geojson';
import { MapStoreState } from '../reducers/store';
Expand Down Expand Up @@ -133,7 +134,7 @@ export function syncDataForAllLayers() {
};
}

export function syncDataForAllJoinLayers() {
function syncDataForAllJoinLayers() {
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
const syncPromises = getLayerList(getState())
.filter((layer) => {
Expand Down Expand Up @@ -318,7 +319,7 @@ export function fitToLayerExtent(layerId: string) {
};
}

export function fitToDataBounds() {
export function fitToDataBounds(onNoBounds?: () => void) {
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
const layerList = getFittableLayers(getState());

Expand Down Expand Up @@ -365,6 +366,9 @@ export function fitToDataBounds() {
}

if (!corners.length) {
if (onNoBounds) {
onNoBounds();
}
return;
}

Expand All @@ -374,6 +378,31 @@ export function fitToDataBounds() {
};
}

let lastSetQueryCallId: string = '';
export function autoFitToBounds() {
return async (dispatch: Dispatch) => {
// Joins are performed on the client.
// As a result, bounds for join layers must also be performed on the client.
// Therefore join layers need to fetch data prior to auto fitting bounds.
const localSetQueryCallId = uuid();
lastSetQueryCallId = localSetQueryCallId;
await dispatch<any>(syncDataForAllJoinLayers());

// autoFitToBounds can be triggered before async data fetching completes
// Only continue execution path if autoFitToBounds has not been re-triggered.
if (localSetQueryCallId === lastSetQueryCallId) {
// In cases where there are no bounds, such as no matching documents, fitToDataBounds does not trigger setGotoWithBounds.
// Ensure layer syncing occurs when setGotoWithBounds is not triggered.
function onNoBounds() {
if (localSetQueryCallId === lastSetQueryCallId) {
dispatch<any>(syncDataForAllLayers());
}
}
dispatch<any>(fitToDataBounds(onNoBounds));
}
};
}

function setGotoWithBounds(bounds: MapExtent) {
return {
type: SET_GOTO,
Expand Down
2 changes: 0 additions & 2 deletions x-pack/plugins/maps/public/actions/layer_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@ export function addLayer(layerDescriptor: LayerDescriptor) {
};
}

// Do not use when rendering a map. Method exists to enable selectors for getLayerList when
// rendering is not needed.
export function addLayerWithoutDataSync(layerDescriptor: LayerDescriptor) {
return {
type: ADD_LAYER,
Expand Down
40 changes: 16 additions & 24 deletions x-pack/plugins/maps/public/actions/map_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import { Dispatch } from 'redux';
import turfBboxPolygon from '@turf/bbox-polygon';
import turfBooleanContains from '@turf/boolean-contains';
import uuid from 'uuid/v4';

import { Filter, Query, TimeRange } from 'src/plugins/data/public';
import { MapStoreState } from '../reducers/store';
Expand Down Expand Up @@ -44,19 +43,16 @@ import {
UPDATE_DRAW_STATE,
UPDATE_MAP_SETTING,
} from './map_action_constants';
import {
fitToDataBounds,
syncDataForAllJoinLayers,
syncDataForAllLayers,
} from './data_request_actions';
import { addLayer } from './layer_actions';
import { autoFitToBounds, syncDataForAllLayers } from './data_request_actions';
import { addLayer, addLayerWithoutDataSync } from './layer_actions';
import { MapSettings } from '../reducers/map';
import {
DrawState,
MapCenterAndZoom,
MapExtent,
MapRefreshConfig,
} from '../../common/descriptor_types';
import { INITIAL_LOCATION } from '../../common/constants';
import { scaleBounds } from '../elasticsearch_geo_utils';

export function setMapInitError(errorMessage: string) {
Expand Down Expand Up @@ -98,13 +94,21 @@ export function mapReady() {
type: MAP_READY,
});

getWaitingForMapReadyLayerListRaw(getState()).forEach((layerDescriptor) => {
dispatch<any>(addLayer(layerDescriptor));
});

const waitingForMapReadyLayerList = getWaitingForMapReadyLayerListRaw(getState());
dispatch({
type: CLEAR_WAITING_FOR_MAP_READY_LAYER_LIST,
});

if (getMapSettings(getState()).initialLocation === INITIAL_LOCATION.AUTO_FIT_TO_BOUNDS) {
waitingForMapReadyLayerList.forEach((layerDescriptor) => {
dispatch<any>(addLayerWithoutDataSync(layerDescriptor));
});
dispatch<any>(autoFitToBounds());
} else {
waitingForMapReadyLayerList.forEach((layerDescriptor) => {
dispatch<any>(addLayer(layerDescriptor));
});
}
};
}

Expand Down Expand Up @@ -196,7 +200,6 @@ function generateQueryTimestamp() {
return new Date().toISOString();
}

let lastSetQueryCallId: string = '';
export function setQuery({
query,
timeFilters,
Expand Down Expand Up @@ -227,18 +230,7 @@ export function setQuery({
});

if (getMapSettings(getState()).autoFitToDataBounds) {
// Joins are performed on the client.
// As a result, bounds for join layers must also be performed on the client.
// Therefore join layers need to fetch data prior to auto fitting bounds.
const localSetQueryCallId = uuid();
lastSetQueryCallId = localSetQueryCallId;
await dispatch<any>(syncDataForAllJoinLayers());

// setQuery can be triggered before async data fetching completes
// Only continue execution path if setQuery has not been re-triggered.
if (localSetQueryCallId === lastSetQueryCallId) {
dispatch<any>(fitToDataBounds());
}
dispatch<any>(autoFitToBounds());
} else {
await dispatch<any>(syncDataForAllLayers());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,10 @@ export async function getInitialView(
});
}

if (settings.initialLocation === INITIAL_LOCATION.AUTO_FIT_TO_BOUNDS) {
// map bounds pulled from data sources. Just use default map location
return null;
}

return goto && goto.center ? goto.center : null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ const initialLocationOptions = [
defaultMessage: 'Map location at save',
}),
},
{
id: INITIAL_LOCATION.AUTO_FIT_TO_BOUNDS,
label: i18n.translate('xpack.maps.mapSettingsPanel.autoFitToBoundsLocationLabel', {
defaultMessage: 'Auto fit map to data bounds',
}),
},
{
id: INITIAL_LOCATION.FIXED_LOCATION,
label: i18n.translate('xpack.maps.mapSettingsPanel.fixedLocationLabel', {
Expand Down Expand Up @@ -125,7 +131,10 @@ export function NavigationPanel({ center, settings, updateMapSetting, zoom }: Pr
};

function renderInitialLocationInputs() {
if (settings.initialLocation === INITIAL_LOCATION.LAST_SAVED_LOCATION) {
if (
settings.initialLocation === INITIAL_LOCATION.LAST_SAVED_LOCATION ||
settings.initialLocation === INITIAL_LOCATION.AUTO_FIT_TO_BOUNDS
) {
return null;
}

Expand Down

0 comments on commit 95c05bb

Please sign in to comment.