Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add before layer id when adding documents label #387

Merged
merged 1 commit into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
* Update draw filter shape ui properties ([#372](https://github.com/opensearch-project/dashboards-maps/pull/372))
* Add filter bar to display global geospatial filters ([#371](https://github.com/opensearch-project/dashboards-maps/pull/371))
* Change font opacity along with OpenSearch base map layer ([#373](https://github.com/opensearch-project/dashboards-maps/pull/373))
* Add before layer id when adding documents label ([#387](https://github.com/opensearch-project/dashboards-maps/pull/387))

### Bug Fixes
* Fix property value undefined check ([#276](https://github.com/opensearch-project/dashboards-maps/pull/276))
Expand Down
2 changes: 1 addition & 1 deletion common/map_saved_object_attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { SavedObjectAttributes } from 'opensearch-dashboards/server';
import { SavedObjectAttributes } from '../../../src/core/types';

export interface MapSavedObjectAttributes extends SavedObjectAttributes {
/** Title of the map */
Expand Down
1 change: 0 additions & 1 deletion public/components/layer_config/layer_config_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export const LayerConfigPanel = ({
updateLayer();
closeLayerConfigPanel(false);
setOriginLayerConfig(null);
setSelectedLayerConfig(undefined);
if (isNewLayer) {
setIsNewLayer(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,15 @@

import { EuiButtonIcon, EuiFlexItem } from '@elastic/eui';
import React, { useState } from 'react';
import { Map as Maplibre } from 'maplibre-gl';
import {
LAYER_PANEL_HIDE_LAYER_ICON,
LAYER_PANEL_SHOW_LAYER_ICON,
LAYER_VISIBILITY,
} from '../../../common';
import { MapLayerSpecification } from '../../model/mapLayerType';
import { updateLayerVisibilityHandler } from '../../model/map/layer_operations';
import { MaplibreRef } from '../../model/layersFunctions';

interface MaplibreRef {
current: Maplibre | null;
}
interface HideLayerProps {
layer: MapLayerSpecification;
maplibreRef: MaplibreRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import {
EuiToolTip,
} from '@elastic/eui';
import { I18nProvider } from '@osd/i18n/react';
import { Map as Maplibre } from 'maplibre-gl';
import './layer_control_panel.scss';
import { isEqual } from 'lodash';
import { i18n } from '@osd/i18n';
import { MaplibreRef } from 'public/model/layersFunctions';
import { IndexPattern } from '../../../../../src/plugins/data/public';
import { AddLayerPanel } from '../add_layer_panel';
import { LayerConfigPanel } from '../layer_config';
Expand All @@ -38,10 +38,6 @@ import { moveLayers, removeLayers } from '../../model/map/layer_operations';
import { DeleteLayerModal } from './delete_layer_modal';
import { HideLayer } from './hide_layer_button';

interface MaplibreRef {
current: Maplibre | null;
}

interface Props {
maplibreRef: MaplibreRef;
setLayers: (layers: MapLayerSpecification[]) => void;
Expand Down
1 change: 1 addition & 0 deletions public/components/map_container/map_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export const MapContainer = ({
maplibreRef
);
}
setSelectedLayerConfig(undefined);
} else {
renderDataLayers(layers, mapState, services, maplibreRef, dashboardProps);
renderBaseLayers(layers, maplibreRef);
Expand Down
7 changes: 2 additions & 5 deletions public/model/OSMLayerFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Map as Maplibre, LayerSpecification, SymbolLayerSpecification } from 'maplibre-gl';
import { LayerSpecification, SymbolLayerSpecification } from 'maplibre-gl';
import { OSMLayerSpecification } from './mapLayerType';
import {
addOSMLayerSource,
Expand All @@ -9,10 +9,7 @@ import {
updateOSMStyleLayer,
} from './map/layer_operations';
import { getMapLanguage } from '../../common/util';

interface MaplibreRef {
current: Maplibre | null;
}
import { MaplibreRef } from './layersFunctions';

// Fetch style layers from OpenSearch vector tile service
const fetchStyleLayers = (url: string) => {
Expand Down
7 changes: 2 additions & 5 deletions public/model/customLayerFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { Map as Maplibre, AttributionControl, RasterSourceSpecification } from 'maplibre-gl';
import { AttributionControl, RasterSourceSpecification } from 'maplibre-gl';
import { CustomLayerSpecification, OSMLayerSpecification } from './mapLayerType';
import { hasLayer, removeLayers } from './map/layer_operations';

interface MaplibreRef {
current: Maplibre | null;
}
import { MaplibreRef } from './layersFunctions';

const updateLayerConfig = (layerConfig: CustomLayerSpecification, maplibreRef: MaplibreRef) => {
const maplibreInstance = maplibreRef.current;
Expand Down
8 changes: 3 additions & 5 deletions public/model/documentLayerFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Map as Maplibre } from 'maplibre-gl';
import { parse } from 'wellknown';
import { DocumentLayerSpecification } from './mapLayerType';
import { convertGeoPointToGeoJSON, isGeoJSON } from '../utils/geo_formater';
Expand All @@ -21,10 +20,8 @@ import {
removeSymbolLayer,
createSymbolLayerSpecification,
} from './map/layer_operations';
import { getMaplibreAboveLayerId, MaplibreRef } from './layersFunctions';

interface MaplibreRef {
current: Maplibre | null;
}
// https://opensearch.org/docs/1.3/opensearch/supported-field-types/geo-shape
const openSearchGeoJSONMap = new Map<string, string>([
['point', 'Point'],
Expand Down Expand Up @@ -227,7 +224,8 @@ const renderLabelLayer = (layerConfig: DocumentLayerSpecification, maplibreRef:
if (hasLabelLayer) {
updateSymbolLayer(maplibreRef.current!, symbolLayerSpec);
} else {
addSymbolLayer(maplibreRef.current!, symbolLayerSpec);
const beforeLayerId = getMaplibreAboveLayerId(layerConfig.id, maplibreRef.current!);
addSymbolLayer(maplibreRef.current!, symbolLayerSpec, beforeLayerId);
}
} else {
// If the label set to disabled, remove the label layer if it exists
Expand Down
6 changes: 1 addition & 5 deletions public/model/layerRenderController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@ import {
Query,
TimeRange,
} from '../../../../src/plugins/data/common';
import { getBaseLayers, getDataLayers, layersFunctionMap } from './layersFunctions';
import { getBaseLayers, getDataLayers, layersFunctionMap, MaplibreRef } from './layersFunctions';
import { MapServices } from '../types';
import { MapState } from './mapState';
import { GeoBounds, getBounds } from './map/boundary';
import { buildBBoxFilter, buildGeoShapeFilter } from './geo/filter';
import { DashboardProps } from '../components/map_page/map_page';

interface MaplibreRef {
current: Maplibre | null;
}

interface MapGlobalStates {
timeRange: TimeRange;
query: Query;
Expand Down
105 changes: 105 additions & 0 deletions public/model/layersFunction.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
baseLayerTypeLookup,
getBaseLayers,
getDataLayers,
getMaplibreAboveLayerId,
layersFunctionMap,
layersTypeIconMap,
layersTypeNameMap,
} from './layersFunctions';
import { MapLayerSpecification } from './mapLayerType';
import { OSMLayerFunctions } from './OSMLayerFunctions';
import { DocumentLayerFunctions } from './documentLayerFunctions';
import { CustomLayerFunctions } from './customLayerFunctions';
import { MockMaplibreMap } from './map/__mocks__/map';
import { MockLayer } from './map/__mocks__/layer';
import { Map as Maplibre } from 'maplibre-gl';

describe('getDataLayers', () => {
it('should return an array of DataLayerSpecification objects', () => {
const layers = [
{ type: 'opensearch_vector_tile_map', name: 'layer1' },
{ type: 'custom_map', name: 'layer2' },
{ type: 'documents', name: 'layer3' },
{ type: 'opensearch_vector_tile_map', name: 'layer4' },
{ type: 'custom_map', name: 'layer5' },
] as unknown as MapLayerSpecification[];
const dataLayers = getDataLayers(layers);
expect(dataLayers).toHaveLength(1);
expect(dataLayers[0].name).toBe('layer3');
});
});

describe('getBaseLayers', () => {
it('should return an array of BaseLayerSpecification objects', () => {
const layers = [
{ type: 'opensearch_vector_tile_map', name: 'layer1' },
{ type: 'custom_map', name: 'layer2' },
{ type: 'documents', name: 'layer3' },
{ type: 'opensearch_vector_tile_map', name: 'layer4' },
{ type: 'custom_map', name: 'layer5' },
] as unknown as MapLayerSpecification[];
const baseLayers = getBaseLayers(layers);
expect(baseLayers).toHaveLength(4);
expect(baseLayers[0].name).toBe('layer1');
expect(baseLayers[1].name).toBe('layer2');
expect(baseLayers[2].name).toBe('layer4');
expect(baseLayers[3].name).toBe('layer5');
});
});

describe('Exported objects', () => {
it('should have the correct values assigned to their keys', () => {
expect(layersFunctionMap).toEqual({
opensearch_vector_tile_map: OSMLayerFunctions,
documents: DocumentLayerFunctions,
custom_map: CustomLayerFunctions,
});

expect(layersTypeNameMap).toEqual({
opensearch_vector_tile_map: 'OpenSearch map',
documents: 'Documents',
custom_map: 'Custom map',
});

expect(layersTypeIconMap).toEqual({
opensearch_vector_tile_map: 'globe',
documents: 'document',
custom_map: 'globe',
});

expect(baseLayerTypeLookup).toEqual({
opensearch_vector_tile_map: true,
custom_map: true,
documents: false,
});
});
});

describe('getMaplibreAboveLayerId', () => {
const mockMapLayer1Id = 'layer-1';
const mockMapLayer2Id = 'layer-2';
const mockMbLayer1: MockLayer = new MockLayer(`${mockMapLayer1Id}-1`);
const mockMbLayer2: MockLayer = new MockLayer(`${mockMapLayer1Id}-2`);
const mockMbLayer3: MockLayer = new MockLayer(`${mockMapLayer2Id}-1`);
const mockMap = new MockMaplibreMap([
mockMbLayer1,
mockMbLayer2,
mockMbLayer3,
]) as unknown as Maplibre;

it('should return the id of the layer above the given mapLayerId', () => {
const aboveLayerId = getMaplibreAboveLayerId(mockMapLayer1Id, mockMap);
expect(aboveLayerId).toBe(`${mockMapLayer2Id}-1`);
});

it('should return undefined if there is no layer above the given mapLayerId', () => {
const aboveLayerId = getMaplibreAboveLayerId(mockMapLayer2Id, mockMap);
expect(aboveLayerId).toBeUndefined();
});

it('should return undefined if the given mapLayerId is not found', () => {
const aboveLayerId = getMaplibreAboveLayerId('undefined-layer', mockMap);
expect(aboveLayerId).toBeUndefined();
});
});
44 changes: 15 additions & 29 deletions public/model/layersFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ import {
import { CustomLayerFunctions } from './customLayerFunctions';
import { getLayers } from './map/layer_operations';

interface MaplibreRef {
current: Maplibre | null;
}

interface MaplibreRef {
export interface MaplibreRef {
current: Maplibre | null;
}

Expand All @@ -39,21 +35,6 @@ export const layersTypeNameMap: { [key: string]: string } = {
[DASHBOARDS_MAPS_LAYER_TYPE.CUSTOM_MAP]: DASHBOARDS_MAPS_LAYER_NAME.CUSTOM_MAP,
};

export const getMaplibreBeforeLayerId = (
selectedLayer: MapLayerSpecification,
maplibreRef: MaplibreRef,
beforeLayerId: string | undefined
): string | undefined => {
const currentLoadedMbLayers = getLayers(maplibreRef.current!);
if (beforeLayerId) {
const beforeMbLayer = currentLoadedMbLayers.find((mbLayer) =>
mbLayer.id.includes(beforeLayerId)
);
return beforeMbLayer?.id;
}
return undefined;
};

export const layersTypeIconMap: { [key: string]: string } = {
[DASHBOARDS_MAPS_LAYER_TYPE.OPENSEARCH_MAP]: DASHBOARDS_MAPS_LAYER_ICON.OPENSEARCH_MAP,
[DASHBOARDS_MAPS_LAYER_TYPE.DOCUMENTS]: DASHBOARDS_MAPS_LAYER_ICON.DOCUMENTS,
Expand All @@ -74,15 +55,20 @@ export const getBaseLayers = (layers: MapLayerSpecification[]): BaseLayerSpecifi
return layers.filter((layer) => baseLayerTypeLookup[layer.type]) as BaseLayerSpecification[];
};

// Get layer id from layers that is above the selected layer
export const getMapBeforeLayerId = (
layers: MapLayerSpecification[],
selectedLayerId: string
export const getMaplibreAboveLayerId = (
mapLayerId: string,
maplibre: Maplibre
): string | undefined => {
const selectedLayerIndex = layers.findIndex((layer) => layer.id === selectedLayerId);
const beforeLayers = layers.slice(selectedLayerIndex + 1);
if (beforeLayers.length === 0) {
return undefined;
const currentLoadedMbLayers = getLayers(maplibre);
const matchingMbLayers = currentLoadedMbLayers.filter((mbLayer) =>
mbLayer.id.includes(mapLayerId)
);
if (matchingMbLayers.length > 0) {
const highestMbLayerIndex = currentLoadedMbLayers.indexOf(
matchingMbLayers[matchingMbLayers.length - 1]
);
const aboveMbLayer = currentLoadedMbLayers[highestMbLayerIndex + 1];
return aboveMbLayer?.id;
}
return beforeLayers[0]?.id;
return undefined;
};
Loading