Skip to content

Commit

Permalink
[Maps] layer groups (#142528)
Browse files Browse the repository at this point in the history
* [Maps] layer groups

* createLayerGroup

* create layer group

* setChildren

* display layer group legend

* display nested layers in TOC

* setLayerVisibility

* set parent on layer re-order

* LayerGroup.getBounds

* clean-up LayerGroup

* edit layer panel

* LayerGroup.cloneDescriptor

* clean up

* remove layer

* fix reorder bug

* move children on layer move

* fix re-order bug when dragging layer group with collapsed details

* add check for dragging to same location

* add logic to prevent dragging layer group into its own family tree

* [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

* add layer to layer group combine action with layer group

* clean up

* fix bug where unable to move layer to bottom

* mouse cursor styles

* clean up combine styling

* fix jest tests

* update toc_entry_actions_popover snapshots

* click confirm model on removeLayer in functional tests

* update cloneLayer to move clones beneath parent

* LayerGroup.getErrors

* Update x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts

Co-authored-by: Nick Peihl <nickpeihl@gmail.com>

* fix show this layer only action when layer is nested

* recursive count children for remove layer warning

* Update x-pack/plugins/maps/public/components/remove_layer_confirm_modal.tsx

Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com>

* resolve error with show this layer only on layer group

* update remove statement to support plural

* perserve layer order when cloning layer group

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Nick Peihl <nickpeihl@gmail.com>
Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com>
  • Loading branch information
4 people authored Oct 13, 2022
1 parent 97eb9b6 commit e45170e
Show file tree
Hide file tree
Showing 37 changed files with 2,063 additions and 974 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 @@ -53,6 +53,7 @@ export enum LAYER_TYPE {
HEATMAP = 'HEATMAP',
BLENDED_VECTOR = 'BLENDED_VECTOR',
MVT_VECTOR = 'MVT_VECTOR',
LAYER_GROUP = 'LAYER_GROUP',
}

export enum SOURCE_TYPES {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export type LayerDescriptor = {
style?: StyleDescriptor | null;
query?: Query;
includeInFitToBounds?: boolean;
parent?: string;
};

export type VectorLayerDescriptor = LayerDescriptor & {
Expand All @@ -89,3 +90,10 @@ export type EMSVectorTileLayerDescriptor = LayerDescriptor & {
type: LAYER_TYPE.EMS_VECTOR_TILE;
style: EMSVectorTileStyleDescriptor;
};

export type LayerGroupDescriptor = LayerDescriptor & {
type: LAYER_TYPE.LAYER_GROUP;
label: string;
sourceDescriptor: null;
visible: boolean;
};
69 changes: 13 additions & 56 deletions x-pack/plugins/maps/public/actions/data_request_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@

import { AnyAction, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import bbox from '@turf/bbox';
import uuid from 'uuid/v4';
import { multiPoint } from '@turf/helpers';
import { FeatureCollection } from 'geojson';
import { Adapters } from '@kbn/inspector-plugin/common/adapters';
import { MapStoreState } from '../reducers/store';
Expand Down Expand Up @@ -49,7 +47,9 @@ import { ILayer } from '../classes/layers/layer';
import { IVectorLayer } from '../classes/layers/vector_layer';
import { DataRequestMeta, MapExtent, DataFilters } from '../../common/descriptor_types';
import { DataRequestAbortError } from '../classes/util/data_request';
import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util';
import { scaleBounds } from '../../common/elasticsearch_util';
import { getLayersExtent } from './get_layers_extent';
import { isLayerGroup } from '../classes/layers/layer_group';

const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1;

Expand Down Expand Up @@ -101,7 +101,7 @@ export function cancelAllInFlightRequests() {
export function updateStyleMeta(layerId: string | null) {
return async (dispatch: Dispatch, getState: () => MapStoreState) => {
const layer = getLayerById(layerId, getState());
if (!layer) {
if (!layer || isLayerGroup(layer)) {
return;
}

Expand Down Expand Up @@ -378,8 +378,8 @@ export function fitToLayerExtent(layerId: string) {

if (targetLayer) {
try {
const bounds = await targetLayer.getBounds(
getDataRequestContext(dispatch, getState, layerId, false, false)
const bounds = await targetLayer.getBounds((boundsLayerId) =>
getDataRequestContext(dispatch, getState, boundsLayerId, false, false)
);
if (bounds) {
await dispatch(setGotoWithBounds(scaleBounds(bounds, FIT_TO_BOUNDS_SCALE_FACTOR)));
Expand All @@ -401,65 +401,22 @@ export function fitToLayerExtent(layerId: string) {

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

if (!layerList.length) {
return;
}

const boundsPromises = layerList.map(async (layer: ILayer) => {
if (!(await layer.isFittable())) {
return null;
}
return layer.getBounds(
getDataRequestContext(dispatch, getState, layer.getId(), false, false)
);
const rootLayers = getLayerList(getState()).filter((layer) => {
return layer.getParent() === undefined;
});

let bounds;
try {
bounds = await Promise.all(boundsPromises);
} catch (error) {
if (!(error instanceof DataRequestAbortError)) {
// eslint-disable-next-line no-console
console.warn(
'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced',
error
);
}
// new fitToDataBounds request has superseded this thread of execution. Results no longer needed.
return;
}

const corners = [];
for (let i = 0; i < bounds.length; i++) {
const b = bounds[i];

// filter out undefined bounds (uses Infinity due to turf responses)
if (
b === null ||
b.minLon === Infinity ||
b.maxLon === Infinity ||
b.minLat === -Infinity ||
b.maxLat === -Infinity
) {
continue;
}

corners.push([b.minLon, b.minLat]);
corners.push([b.maxLon, b.maxLat]);
}
const extent = await getLayersExtent(rootLayers, (boundsLayerId) =>
getDataRequestContext(dispatch, getState, boundsLayerId, false, false)
);

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

const dataBounds = turfBboxToBounds(bbox(multiPoint(corners)));

dispatch(setGotoWithBounds(scaleBounds(dataBounds, FIT_TO_BOUNDS_SCALE_FACTOR)));
dispatch(setGotoWithBounds(scaleBounds(extent, FIT_TO_BOUNDS_SCALE_FACTOR)));
};
}

Expand Down
66 changes: 66 additions & 0 deletions x-pack/plugins/maps/public/actions/get_layers_extent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import bbox from '@turf/bbox';
import { multiPoint } from '@turf/helpers';
import { MapExtent } from '../../common/descriptor_types';
import { turfBboxToBounds } from '../../common/elasticsearch_util';
import { ILayer } from '../classes/layers/layer';
import type { DataRequestContext } from './data_request_actions';
import { DataRequestAbortError } from '../classes/util/data_request';

export async function getLayersExtent(
layers: ILayer[],
getDataRequestContext: (layerId: string) => DataRequestContext
): Promise<MapExtent | null> {
if (!layers.length) {
return null;
}

const boundsPromises = layers.map(async (layer: ILayer) => {
if (!(await layer.isFittable())) {
return null;
}
return layer.getBounds(getDataRequestContext);
});

let bounds;
try {
bounds = await Promise.all(boundsPromises);
} catch (error) {
if (!(error instanceof DataRequestAbortError)) {
// eslint-disable-next-line no-console
console.warn(
'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced',
error
);
}
// new fitToDataBounds request has superseded this thread of execution. Results no longer needed.
return null;
}

const corners = [];
for (let i = 0; i < bounds.length; i++) {
const b = bounds[i];

// filter out undefined bounds (uses Infinity due to turf responses)
if (
b === null ||
b.minLon === Infinity ||
b.maxLon === Infinity ||
b.minLat === -Infinity ||
b.maxLat === -Infinity
) {
continue;
}

corners.push([b.minLon, b.minLat]);
corners.push([b.maxLon, b.maxLat]);
}

return corners.length ? turfBboxToBounds(bbox(multiPoint(corners))) : null;
}
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ export {
openOnHoverTooltip,
updateOpenTooltips,
} from './tooltip_actions';
export { getLayersExtent } from './get_layers_extent';
Loading

0 comments on commit e45170e

Please sign in to comment.