Skip to content

Commit

Permalink
Update PR from feedback
Browse files Browse the repository at this point in the history
Signed-off-by: Junqiu Lei <[email protected]>
  • Loading branch information
junqiu-lei committed Nov 6, 2022
1 parent 29e4444 commit 8051af1
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 207 deletions.
3 changes: 3 additions & 0 deletions maps_dashboards/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export const PLUGIN_NAME = 'Maps';
export const MAP_VECTOR_TILE_BASIC_STYLE = 'https://tiles.maps.opensearch.org/styles/basic.json';
export const MAP_GLYPHS = 'https://tiles.maps.opensearch.org/fonts/{fontstack}/{range}.pbf';
export const MAP_VECTOR_TILE_DATA_SOURCE = 'https://tiles.maps.opensearch.org/data/v1.json';
export const MAP_DEFAULT_MIN_ZOOM = 0;
export const MAP_DEFAULT_MAX_ZOOM = 22;
export const MAP_DEFAULT_OPACITY = 1;

// Starting position [lng, lat] and zoom
export const MAP_INITIAL_STATE = {
Expand Down
2 changes: 1 addition & 1 deletion maps_dashboards/public/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const MapsDashboardsApp = () => {
<div>
<Switch>
<Route path={[APP_PATH.CREATE_MAP, APP_PATH.EDIT_MAP]} render={() => <MapPage />} />
<Route exact path="/" render={() => <MapsList />} />
<Route exact path={APP_PATH.LANDING_PAGE_PATH} render={() => <MapsList />} />
</Switch>
</div>
</I18nProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useEffect, useState } from 'react';
import React, { memo, useEffect, useState } from 'react';
import {
EuiPanel,
EuiTitle,
Expand All @@ -25,11 +25,11 @@ import {
DASHBOARDS_MAPS_LAYER_TYPE,
LAYER_VISIBILITY,
MAP_VECTOR_TILE_BASIC_STYLE,
MAP_DEFAULT_OPACITY,
MAP_DEFAULT_MAX_ZOOM,
MAP_DEFAULT_MIN_ZOOM,
} from '../../../common';
import { layersFunctionMap } from '../../model/layersFunctions';
import { useOpenSearchDashboards } from '../../../../../src/plugins/opensearch_dashboards_react/public';
import { MapServices } from '../../types';
import { MapSavedObjectAttributes } from '../../../common/map_saved_object_attributes';

interface MaplibreRef {
current: Maplibre | null;
Expand All @@ -42,45 +42,18 @@ interface Props {
layers: ILayerConfig[];
}

const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Props) => {
const LayerControlPanel = memo(({ maplibreRef, mapIdFromUrl, setLayers, layers }: Props) => {
const [isLayerConfigVisible, setIsLayerConfigVisible] = useState(false);
const [isLayerControlVisible, setIsLayerControlVisible] = useState(true);
const {
services: {
savedObjects: { client: savedObjectsClient },
},
} = useOpenSearchDashboards<MapServices>();

const fetchLayers = useCallback(async (): Promise<{
layers: ILayerConfig[];
}> => {
const savedMapObject = await savedObjectsClient.get<MapSavedObjectAttributes>(
'map',
mapIdFromUrl
);
const SavedLayers = JSON.parse(savedMapObject.attributes.layerList as string);
return {
layers: SavedLayers,
};
}, [savedObjectsClient, mapIdFromUrl]);

const [selectedLayerConfig, setSelectedLayerConfig] = useState<ILayerConfig>({
iconType: '',
name: '',
type: '',
id: '',
zoomRange: [],
opacity: 1,
visibility: '',
});
const [selectedLayerConfig, setSelectedLayerConfig] = useState<ILayerConfig | undefined>();

const initialDefaultLayer: ILayerConfig = {
iconType: 'visMapRegion',
id: uuidv4(),
type: DASHBOARDS_MAPS_LAYER_TYPE.OPENSEARCH_MAP,
name: DASHBOARDS_MAPS_LAYER_TYPE.OPENSEARCH_MAP,
zoomRange: [0, 22],
opacity: 1,
zoomRange: [MAP_DEFAULT_MIN_ZOOM, MAP_DEFAULT_MAX_ZOOM],
opacity: MAP_DEFAULT_OPACITY,
visibility: LAYER_VISIBILITY.VISIBLE,
layerSpec: {
OSMUrl: MAP_VECTOR_TILE_BASIC_STYLE,
Expand All @@ -89,23 +62,24 @@ const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Pro

// Initially load the layers from the saved object
useEffect(() => {
maplibreRef.current?.on('load', function () {
if (!!mapIdFromUrl) {
fetchLayers().then((res) => {
const layersFromSavedMap = res.layers;
layersFromSavedMap.forEach((layer) => {
layersFunctionMap[layer.type]?.initial(maplibreRef, layer);
});
setLayers(res.layers);
});
} else {
layersFunctionMap[initialDefaultLayer.type]?.initial(maplibreRef, initialDefaultLayer);
setLayers([initialDefaultLayer]);
}
});
}, []);
if (layers && mapIdFromUrl) {
layers.forEach((layer) => {
layersFunctionMap[layer.type]?.initial(maplibreRef, layer);
});
} else {
maplibreRef.current?.on('load', function () {
if (!mapIdFromUrl) {
layersFunctionMap[initialDefaultLayer.type]?.initial(maplibreRef, initialDefaultLayer);
setLayers([initialDefaultLayer]);
}
});
}
}, [layers]);

const updateLayer = () => {
if (!selectedLayerConfig) {
return;
}
const layersClone = [...layers];
const index = layersClone.findIndex((layer) => layer.id === selectedLayerConfig.id);
if (index <= -1) {
Expand All @@ -118,9 +92,7 @@ const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Pro
};
}
setLayers(layersClone);
setTimeout(function () {
layersFunctionMap[selectedLayerConfig.type]?.update(maplibreRef, selectedLayerConfig);
}, 50);
layersFunctionMap[selectedLayerConfig.type]?.update(maplibreRef, selectedLayerConfig);
};

const removeLayer = (index: number) => {
Expand Down Expand Up @@ -181,7 +153,12 @@ const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Pro
aria-label="layer in the map layers list"
isDisabled={isDisabled}
onClick={() => {
if (selectedLayerConfig.id === layer.id && !isLayerConfigVisible) {
setSelectedLayerConfig(layer);
if (
selectedLayerConfig &&
selectedLayerConfig.id === layer.id &&
!isLayerConfigVisible
) {
setIsLayerConfigVisible(true);
}
}}
Expand Down Expand Up @@ -224,7 +201,7 @@ const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Pro
</div>
);
})}
{isLayerConfigVisible && (
{isLayerConfigVisible && selectedLayerConfig && (
<LayerConfigPanel
setIsLayerConfigVisible={setIsLayerConfigVisible}
selectedLayerConfig={selectedLayerConfig}
Expand Down Expand Up @@ -256,6 +233,6 @@ const LayerControlPanel = ({ maplibreRef, mapIdFromUrl, setLayers, layers }: Pro
</EuiButton>
</EuiFlexItem>
);
};
});

export { LayerControlPanel };
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const MapContainer = ({ mapIdFromUrl, setLayers, layers }: MapContainerPr
const [zoom, setZoom] = useState<number>(MAP_INITIAL_STATE.zoom);

useEffect(() => {
if (!mapContainer.current) return;
const mbStyle = {
version: 8 as 8,
sources: {},
Expand All @@ -38,21 +39,19 @@ export const MapContainer = ({ mapIdFromUrl, setLayers, layers }: MapContainerPr
style: mbStyle,
});

maplibreRef.current.addControl(new NavigationControl({ showCompass: false }), 'top-right');
maplibreRef.current.on('style.load', function () {
maplibreRef.current!.addSource('openmaptiles', {
const maplibreInstance = maplibreRef.current!;
maplibreInstance.addControl(new NavigationControl({ showCompass: false }), 'top-right');
maplibreInstance.on('style.load', function () {
maplibreInstance.addSource('openmaptiles', {
type: 'vector',
url: MAP_VECTOR_TILE_DATA_SOURCE,
});
setMounted(true);
});
}, []);

useEffect(() => {
maplibreRef.current!.on('move', () => {
return setZoom(Number(maplibreRef.current!.getZoom().toFixed(2)));
maplibreInstance.on('move', () => {
return setZoom(Number(maplibreInstance.getZoom().toFixed(2)));
});
}, [zoom]);
}, []);

return (
<div>
Expand Down
24 changes: 9 additions & 15 deletions maps_dashboards/public/components/map_page/map_page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { SimpleSavedObject } from 'opensearch-dashboards/public';
import { MapContainer } from '../map_container';
Expand All @@ -16,32 +16,26 @@ import { MapSavedObjectAttributes } from '../../../common/map_saved_object_attri
export const MapPage = () => {
const [layers, setLayers] = useState<ILayerConfig[]>([]);
const { id: mapIdFromUrl } = useParams<{ id: string }>();
const [savedMapObject, setSavedMapObject] = useState<SimpleSavedObject<
MapSavedObjectAttributes
> | null>();
const { services } = useOpenSearchDashboards<MapServices>();
const {
savedObjects: { client: savedObjectsClient },
} = services;

const fetchMapObject = useCallback(async (): Promise<
SimpleSavedObject<MapSavedObjectAttributes>
> => {
const savedMapObject = await savedObjectsClient.get<MapSavedObjectAttributes>(
'map',
mapIdFromUrl
);
return savedMapObject;
}, [savedObjectsClient, mapIdFromUrl]);

useEffect(() => {
if (mapIdFromUrl) {
fetchMapObject().then((savedMapObject) => {
setLayers(JSON.parse(savedMapObject.attributes.layerList as string));
savedObjectsClient.get<MapSavedObjectAttributes>('map', mapIdFromUrl).then((res) => {
setSavedMapObject(res);
setLayers(JSON.parse(res.attributes.layerList as string));
});
}
}, [fetchMapObject, mapIdFromUrl]);
}, [savedObjectsClient, mapIdFromUrl]);

return (
<div>
<MapTopNavMenu mapIdFromUrl={mapIdFromUrl} layers={layers} />
<MapTopNavMenu mapIdFromUrl={mapIdFromUrl} savedMapObject={savedMapObject} layers={layers} />
<MapContainer mapIdFromUrl={mapIdFromUrl} layers={layers} setLayers={setLayers} />
</div>
);
Expand Down
22 changes: 7 additions & 15 deletions maps_dashboards/public/components/map_top_nav/top_nav_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { SimpleSavedObject } from 'opensearch-dashboards/public';
import { PLUGIN_ID } from '../../../common';
import { getTopNavConfig } from './get_top_nav_config';
Expand All @@ -15,42 +15,34 @@ import { getSavedMapBreadcrumbs, getCreateBreadcrumbs } from '../../utils/breadc
interface MapTopNavMenuProps {
mapIdFromUrl: string;
layers: any;
savedMapObject: SimpleSavedObject<MapSavedObjectAttributes> | null | undefined;
}

export const MapTopNavMenu = ({ mapIdFromUrl, layers }: MapTopNavMenuProps) => {
export const MapTopNavMenu = ({ mapIdFromUrl, savedMapObject, layers }: MapTopNavMenuProps) => {
const { services } = useOpenSearchDashboards<MapServices>();
const {
setHeaderActionMenu,
navigation: {
ui: { TopNavMenu },
},
savedObjects: { client: savedObjectsClient },
chrome,
application: { navigateToApp },
} = services;

const [title, setTitle] = useState<string>('');
const [description, setDescription] = useState<string>('');

const fetchMapObject = useCallback(async (): Promise<
SimpleSavedObject<MapSavedObjectAttributes>
> => {
return await savedObjectsClient.get<MapSavedObjectAttributes>('map', mapIdFromUrl);
}, [savedObjectsClient, mapIdFromUrl]);

useEffect(() => {
if (mapIdFromUrl) {
fetchMapObject().then((object) => {
setTitle(object.attributes.title);
setDescription(object.attributes.description!);
});
if (savedMapObject) {
setTitle(savedMapObject.attributes.title);
setDescription(savedMapObject.attributes.description!);
chrome.setBreadcrumbs(getSavedMapBreadcrumbs(title, navigateToApp));
chrome.docTitle.change(title);
} else {
chrome.setBreadcrumbs(getCreateBreadcrumbs(navigateToApp));
chrome.docTitle.change('Create');
}
}, [chrome, fetchMapObject, mapIdFromUrl, navigateToApp, title]);
}, [chrome, savedMapObject, mapIdFromUrl, navigateToApp, title]);

return (
<TopNavMenu
Expand Down
31 changes: 17 additions & 14 deletions maps_dashboards/public/components/maps_list/maps_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { i18n } from '@osd/i18n';
import React, { useCallback, useEffect } from 'react';
import { I18nProvider } from '@osd/i18n/react';
import { EuiPage, EuiPageBody, EuiPageContentBody } from '@elastic/eui';
import { EuiPage, EuiPageBody, EuiPageContentBody, EuiLink } from '@elastic/eui';
import {
TableListView,
useOpenSearchDashboards,
Expand All @@ -31,13 +31,20 @@ export const MapsList = () => {
docTitle.change(i18n.translate('maps.listing.pageTitle', { defaultMessage: 'Maps' }));
}, [docTitle, navigateToApp, setBreadcrumbs]);

const navigateToSavedMapPage = (id: string) => {
navigateToApp(PLUGIN_ID, { path: `/${id}` });
};

const tableColumns = [
{
field: 'attributes.title',
name: i18n.translate('maps.listing.table.titleColumnName', {
defaultMessage: 'Title',
}),
sortable: true,
render: (title, record) => (
<EuiLink onClick={() => navigateToSavedMapPage(record.id)}>{title}</EuiLink>
),
},
{
field: 'attributes.description',
Expand All @@ -46,9 +53,16 @@ export const MapsList = () => {
}),
sortable: true,
},
{
field: 'updated_at',
name: i18n.translate('maps.listing.table.updatedTimeColumnName', {
defaultMessage: 'Last updated',
}),
sortable: true,
},
];

const createMap = () => {
const navigateToCreateMapPage = () => {
navigateToApp(PLUGIN_ID, { path: APP_PATH.CREATE_MAP });
};

Expand Down Expand Up @@ -81,16 +95,6 @@ export const MapsList = () => {
[savedObjectsClient, toasts]
);

const editMap = useCallback(
({ id }) => {
if (id) {
navigateToApp(PLUGIN_ID, { path: `/${id}` });
return;
}
},
[navigateToApp]
);

// Render the map list DOM.
return (
<I18nProvider>
Expand All @@ -100,10 +104,9 @@ export const MapsList = () => {
<EuiPageContentBody>
<TableListView
headingId="mapsListingHeading"
createItem={createMap}
createItem={navigateToCreateMapPage}
findItems={fetchMaps}
deleteItems={deleteMaps}
editItem={editMap}
tableColumns={tableColumns}
listingLimit={10}
initialPageSize={10}
Expand Down
Loading

0 comments on commit 8051af1

Please sign in to comment.