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

[TM-1343] add polygons and popup #618

Merged
merged 20 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bff6eab
[TM-1343] add polygons visible in dashboard with popups
egrojMonroy Oct 22, 2024
5b814a4
[TM-1343] remove useless lo
egrojMonroy Oct 22, 2024
3ce3ad2
[TM-1343[ remove logs
egrojMonroy Oct 22, 2024
ba1a3e0
[TM-1343] missing variable
egrojMonroy Oct 22, 2024
d689fb1
[TM-1343] start adding filter points by projects permission
egrojMonroy Oct 23, 2024
e7b9e5d
[TM-1343] remove useless endpoint
egrojMonroy Oct 23, 2024
80e826a
add basic refetch attempt
pachonjcl Oct 31, 2024
a3afc9d
[TM-1421] fix reference for jobs created on dashboard
cesarLima1 Nov 1, 2024
8796b68
add basic handling of falsy values
pachonjcl Nov 1, 2024
2a4841e
[TM-1421] add optional chaining in data
cesarLima1 Nov 1, 2024
d9337ae
[TM-1421] avoid undefined values
cesarLima1 Nov 1, 2024
3a1ef7e
[TM-1343] Merge branch 'staging' into feat/TM-1343-add-polygons-and-p…
egrojMonroy Nov 4, 2024
379131e
[TM-1343] Merge branch 'TM-1421_implement_cache_layer' into feat/TM-1…
egrojMonroy Nov 4, 2024
4eecb45
[TM-1343] add zoom to country selected
egrojMonroy Nov 4, 2024
cf2a6dc
[TM-1343] add and remove border country
egrojMonroy Nov 4, 2024
90de864
[TM-1343] add country border and filter centroids
egrojMonroy Nov 5, 2024
171a5cd
[TM-1343] Merge branch 'staging' into feat/TM-1343-add-polygons-and-p…
egrojMonroy Nov 5, 2024
9b2322c
[TM-1343] add not mandatory argument
egrojMonroy Nov 5, 2024
eb85bd8
[TM-1343] remove logs and return Log instead of console
egrojMonroy Nov 5, 2024
b6c2f73
[TM-1343] remove unused variable
egrojMonroy Nov 5, 2024
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
26 changes: 21 additions & 5 deletions src/components/elements/Map-mapbox/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { MapStyle } from "./MapControls/types";
import ViewImageCarousel from "./MapControls/ViewImageCarousel";
import { ZoomControl } from "./MapControls/ZoomControl";
import {
addBorderCountry,
addDeleteLayer,
addFilterOnLayer,
addGeojsonToDraw,
Expand All @@ -64,6 +65,7 @@ import {
addPopupsToMap,
addSourcesToLayers,
drawTemporaryPolygon,
removeBorderCountry,
removeMediaLayer,
removePopups,
startDrawing,
Expand Down Expand Up @@ -119,6 +121,9 @@ interface MapProps extends Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>
entityData?: any;
imageGalleryRef?: React.RefObject<HTMLDivElement>;
showImagesButton?: boolean;
listViewProjects?: any;
role?: any;
selectedCountry?: string | null;
}

export const MapContainer = ({
Expand Down Expand Up @@ -151,13 +156,15 @@ export const MapContainer = ({
entityData,
imageGalleryRef,
centroids,
listViewProjects,
showImagesButton,
...props
}: MapProps) => {
const [showMediaPopups, setShowMediaPopups] = useState<boolean>(true);
const [sourcesAdded, setSourcesAdded] = useState<boolean>(false);
const [viewImages, setViewImages] = useState(false);
const [currentStyle, setCurrentStyle] = useState(isDashboard ? MapStyle.Street : MapStyle.Satellite);
const { polygonsData, bbox, setPolygonFromMap, polygonFromMap, sitePolygonData } = props;
const { polygonsData, bbox, setPolygonFromMap, polygonFromMap, sitePolygonData, selectedCountry } = props;
const context = useSitePolygonData();
const contextMapArea = useMapAreaContext();
const { reloadSiteData } = context ?? {};
Expand Down Expand Up @@ -223,8 +230,10 @@ export const MapContainer = ({
if (map?.current && !_.isEmpty(polygonsData)) {
const currentMap = map.current as mapboxgl.Map;
const setupMap = () => {
addSourcesToLayers(currentMap, polygonsData, centroids);
const zoomFilter = isDashboard ? 7 : undefined;
addSourcesToLayers(currentMap, polygonsData, centroids, zoomFilter, listViewProjects);
setChangeStyle(true);
setSourcesAdded(true);
if (showPopups) {
addPopupsToMap(
currentMap,
Expand All @@ -239,14 +248,14 @@ export const MapContainer = ({
);
}
};

setSourcesAdded(false);
if (currentMap.isStyleLoaded()) {
setupMap();
} else {
currentMap.once("styledata", setupMap);
}
}
}, [sitePolygonData, polygonsData, showPopups]);
}, [sitePolygonData, polygonsData, showPopups, listViewProjects, centroids]);

useEffect(() => {
if (currentStyle) {
Expand All @@ -265,7 +274,14 @@ export const MapContainer = ({
zoomToBbox(bbox, map.current, hasControls);
}
}, [bbox]);

useEffect(() => {
if (!map.current || !styleLoaded || !sourcesAdded) return;
if (selectedCountry) {
addBorderCountry(map.current, selectedCountry);
} else {
removeBorderCountry(map.current);
}
}, [selectedCountry, styleLoaded, sourcesAdded]);
useEffect(() => {
const projectUUID = router.query.uuid as string;
const isProjectPath = router.isReady && router.asPath.includes("project");
Expand Down
195 changes: 155 additions & 40 deletions src/components/elements/Map-mapbox/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,27 @@ export const stopDrawing = (draw: MapboxDraw, map: mapboxgl.Map) => {
export const addFilterOnLayer = (layer: any, parsedPolygonData: Record<string, string[]>, map: mapboxgl.Map) => {
addSourceToLayer(layer, map, parsedPolygonData);
};

const filterLayerByZoom = (map: mapboxgl.Map, name: string, styles: LayerWithStyle[], zoomFilter: number) => {
const zoomLevel = map.getZoom();
if (zoomLevel < zoomFilter) {
styles.forEach((_: LayerWithStyle, index: number) => {
const layerName = `${name}-${index}`;
map.setLayoutProperty(layerName, "visibility", "none");
});
} else {
styles.forEach((_: LayerWithStyle, index: number) => {
const layerName = `${name}-${index}`;
map.setLayoutProperty(layerName, "visibility", "visible");
});
}
};
const showPolygons = (
styles: LayerWithStyle[],
name: string,
map: mapboxgl.Map,
field: string,
parsedPolygonData: any
parsedPolygonData: any,
zoomFilter?: number | undefined
) => {
styles.forEach((style: LayerWithStyle, index: number) => {
const layerName = `${name}-${index}`;
Expand All @@ -123,6 +137,11 @@ const showPolygons = (
map.setFilter(layerName, completeFilter);
map.setLayoutProperty(layerName, "visibility", "visible");
});
if (zoomFilter) {
map.on("zoom", () => {
filterLayerByZoom(map, name, styles, zoomFilter);
});
}
};

let popup: mapboxgl.Popup | null = null;
Expand All @@ -131,9 +150,14 @@ let popupAttachedMap: Record<string, mapboxgl.Popup[]> = {
MEDIA: []
};

export const loadLayersInMap = (map: mapboxgl.Map, polygonsData: Record<string, string[]> | undefined, layer: any) => {
export const loadLayersInMap = (
map: mapboxgl.Map,
polygonsData: Record<string, string[]> | undefined,
layer: any,
zoomFilter?: number | undefined
) => {
if (map) {
showPolygons(layer.styles, layer.name, map, "uuid", polygonsData);
showPolygons(layer.styles, layer.name, map, "uuid", polygonsData, zoomFilter);
}
};

Expand Down Expand Up @@ -359,18 +383,20 @@ export const addMediaSourceAndLayer = (
export const addSourcesToLayers = (
map: mapboxgl.Map,
polygonsData: Record<string, string[]> | undefined,
centroids: DashboardGetProjectsData[] | undefined
centroids: DashboardGetProjectsData[] | undefined,
zoomFilter?: number | undefined,
listViewProjects?: any
) => {
if (map) {
layersList.forEach((layer: LayerType) => {
if (layer.name === LAYERS_NAMES.POLYGON_GEOMETRY) {
addSourceToLayer(layer, map, polygonsData);
addSourceToLayer(layer, map, polygonsData, zoomFilter);
}
if (layer.name === LAYERS_NAMES.WORLD_COUNTRIES) {
addSourceToLayer(layer, map, undefined);
}
if (layer.name === LAYERS_NAMES.CENTROIDS) {
addGeojsonSourceToLayer(centroids, map, layer);
addGeojsonSourceToLayer(centroids, map, layer, zoomFilter, listViewProjects);
}
});
}
Expand Down Expand Up @@ -404,6 +430,7 @@ export const addPopupsToMap = (
});
}
};
const activeClickHandlers: Record<string, any> = {};

export const addPopupToLayer = (
map: mapboxgl.Map,
Expand All @@ -423,36 +450,39 @@ export const addPopupToLayer = (
let layers = map.getStyle().layers;

let targetLayers = layers.filter(layer => layer.id.startsWith(name));
if (name === LAYERS_NAMES.CENTROIDS) {
if (name === LAYERS_NAMES.CENTROIDS && targetLayers.length > 0) {
targetLayers = [targetLayers[0]];
}
const clickHandler = (e: any) => {
const currentMode = draw?.getMode();
if (currentMode === "draw_polygon" || currentMode === "draw_line_string") return;

const zoomLevel = map.getZoom();

if (name === LAYERS_NAMES.WORLD_COUNTRIES && zoomLevel > 4.5) return;

if (name === LAYERS_NAMES.CENTROIDS && zoomLevel <= 4.5) return;

handleLayerClick(
e,
popupComponent,
map,
setPolygonFromMap,
sitePolygonData,
type,
editPolygon,
setEditPolygon,
name,
isDashboard
);
};
targetLayers.forEach(targetLayer => {
if (!targetLayer?.id || !map.getLayer(targetLayer.id)) {
return;
if (activeClickHandlers[targetLayer.id]) {
map.off("click", targetLayer.id, activeClickHandlers[targetLayer.id]);
delete activeClickHandlers[targetLayer.id];
}
map.on("click", targetLayer.id, (e: any) => {
const currentMode = draw?.getMode();
if (currentMode === "draw_polygon" || currentMode === "draw_line_string") return;

const zoomLevel = map.getZoom();

if (name === LAYERS_NAMES.WORLD_COUNTRIES && zoomLevel > 4.5) return;

if (name === LAYERS_NAMES.CENTROIDS && zoomLevel <= 4.5) return;

handleLayerClick(
e,
popupComponent,
map,
setPolygonFromMap,
sitePolygonData,
type,
editPolygon,
setEditPolygon,
name,
isDashboard
);
});
activeClickHandlers[targetLayer.id] = clickHandler;
map.on("click", targetLayer.id, clickHandler);
});
}
};
Expand Down Expand Up @@ -491,10 +521,42 @@ export const addHoverEvent = (layer: LayerType, map: mapboxgl.Map) => {
});
}
};
const addZoomBasedFilter = (
map: mapboxgl.Map,
layerIds: any,
zoomLevel: number,
visibleProjectsUuids = [],
isAdmin = false
) => {
const updateFilter = () => {
const zoom = map.getZoom();
if (zoom >= zoomLevel) {
layerIds.forEach((layerId: any) => {
if (isAdmin) {
map.setFilter(layerId, ["!has", "uuid"]);
} else {
if (visibleProjectsUuids.length > 0) {
map.setFilter(layerId, ["match", ["get", "uuid"], visibleProjectsUuids, false, true]);
} else {
map.setFilter(layerId, null);
}
}
});
} else {
layerIds.forEach((layerId: any) => {
map.setFilter(layerId, null);
});
}
};
map.on("zoom", updateFilter);
updateFilter();
};
export const addGeojsonSourceToLayer = (
centroids: DashboardGetProjectsData[] | undefined,
map: mapboxgl.Map,
layer: LayerType
layer: LayerType,
zoomFilter?: number | undefined,
listViewProjects?: any
) => {
const { name, styles } = layer;
if (map && centroids) {
Expand Down Expand Up @@ -524,12 +586,21 @@ export const addGeojsonSourceToLayer = (
styles?.forEach((style: LayerWithStyle, index: number) => {
addLayerGeojsonStyle(map, name, name, style, index);
});
if (zoomFilter) {
addZoomBasedFilter(
map,
styles.map((_: unknown, index: number) => `${name}-${index}`),
zoomFilter,
listViewProjects?.projectsUuids
);
}
}
};
export const addSourceToLayer = (
layer: LayerType,
map: mapboxgl.Map,
polygonsData: Record<string, string[]> | undefined
polygonsData: Record<string, string[]> | undefined,
zoomFilter?: number | undefined
) => {
const { name, geoserverLayerName, styles } = layer;

Expand All @@ -549,7 +620,7 @@ export const addSourceToLayer = (
addLayerStyle(map, name, geoserverLayerName, style, index);
});
if (polygonsData) {
loadLayersInMap(map, polygonsData, layer);
loadLayersInMap(map, polygonsData, layer, zoomFilter);
}
if (name === LAYERS_NAMES.WORLD_COUNTRIES) {
addHoverEvent(layer, map);
Expand Down Expand Up @@ -620,21 +691,65 @@ export const addLayerGeojsonStyle = (
);
moveDeleteLayers(map);
};
export const setFilterCountry = (map: mapboxgl.Map, layerName: string, country: string) => {
const filter = ["==", ["get", "iso"], country];
map.setFilter(layerName, filter);
};
export const addBorderCountry = (map: mapboxgl.Map, country: string) => {
if (!country || !map) return;

const styleName = `${LAYERS_NAMES.WORLD_COUNTRIES}-line`;
const countryLayer = layersList.find(layer => layer.name === styleName);
if (!countryLayer) return;
const countryStyles = countryLayer.styles || [];
const sourceName = countryLayer.name;
const GEOSERVER_TILE_URL = getGeoserverURL(countryLayer.geoserverLayerName);

if (!map.getSource(sourceName)) {
map.addSource(sourceName, {
type: "vector",
tiles: [GEOSERVER_TILE_URL]
});
}
if (map.getLayer(sourceName)) {
map.removeLayer(sourceName);
}
const style = countryStyles[0];
map.addLayer({
...style,
id: sourceName,
source: sourceName,
"source-layer": countryLayer.geoserverLayerName
} as mapboxgl.AnyLayer);
setFilterCountry(map, sourceName, country);
};

export const removeBorderCountry = (map: mapboxgl.Map) => {
const layerName = `${LAYERS_NAMES.WORLD_COUNTRIES}-line`;
console.log("About to remove", layerName);
if (map.getLayer(layerName)) {
map.removeLayer(layerName);
}
if (map.getSource(layerName)) {
map.removeSource(layerName);
}
};

export const addLayerStyle = (
map: mapboxgl.Map,
layerName: string,
sourceName: string,
style: LayerWithStyle,
index: number
index_suffix: number | string
) => {
const beforeLayer = map.getLayer(LAYERS_NAMES.MEDIA_IMAGES) ? LAYERS_NAMES.MEDIA_IMAGES : undefined;
if (map.getLayer(`${layerName}-${index}`)) {
map.removeLayer(`${layerName}-${index}`);
if (map.getLayer(`${layerName}-${index_suffix}`)) {
map.removeLayer(`${layerName}-${index_suffix}`);
}
map.addLayer(
{
...style,
id: `${layerName}-${index}`,
id: `${layerName}-${index_suffix}`,
source: sourceName,
"source-layer": sourceName
} as mapboxgl.AnyLayer,
Expand Down
Loading