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

fix(click-static-map) Prevents click/hover queries on a static map #1864

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
14 changes: 10 additions & 4 deletions packages/geoview-core/public/templates/sandbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ <h4 id="HLCONF1">Sanbox Map</h4>
<a class="ref-link" href="#top">Top</a>
</div>
<div id="mapSection">
<div id="sandboxMap" class="" data-lang="en"></div>
<div id="sandboxMap"></div>
</div>
<p>This map loads it's configurations from the text area.</p>
<hr />
Expand Down Expand Up @@ -194,11 +194,17 @@ <h4 id="HLCONF1">Sanbox Map</h4>
// add an event listener when a button is clicked
createMapButton.addEventListener('click', function (e) {
// delete old map
const mapDiv = cgpv.api.maps['sandboxMap'].remove(false);
mapDiv.classList.remove('geoview-map');
cgpv.api.maps['sandboxMap'].remove(true);

// create new map in a new dom node
const newDiv = document.createElement('div');
const a = document.createAttribute("id");
a.value = "sandboxMap";
newDiv.setAttributeNode(a);
document.getElementById('mapSection').appendChild(newDiv);

// create map
setTimeout(() => cgpv.api.createMapFromConfig('sandboxMap', document.getElementById('configGeoview').value), 1000);
setTimeout(() => cgpv.api.createMapFromConfig('sandboxMap', document.getElementById('configGeoview').value), 300);
});

// Editor script section===================================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,13 @@ export class MapEventProcessor extends AbstractEventProcessor {
// TODO: destroy events on map destruction
map.on('change:size', store.getState().mapState.events.onMapChangeSize);
map.on('moveend', store.getState().mapState.events.onMapMoveEnd);
map.on('pointermove', store.getState().mapState.events.onMapPointerMove);
map.on('singleclick', store.getState().mapState.events.onMapSingleClick);

// If not on a static map, wire handlers on pointermove and singleclick
if (store.getState().mapState.interaction !== 'static') {
map.on('pointermove', store.getState().mapState.events.onMapPointerMove);
map.on('singleclick', store.getState().mapState.events.onMapSingleClick);
}

map.getView().on('change:resolution', store.getState().mapState.events.onMapZoomEnd);
map.getView().on('change:rotation', store.getState().mapState.events.onMapRotation);

Expand Down
2 changes: 1 addition & 1 deletion packages/geoview-core/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ async function renderMap(mapElement: Element): Promise<void> {
reactRoot[mapId] = createRoot(mapElement!);
addReloadListener(mapId);

// TODO: Refactor #1810 - Activate <React.StrictMode>
// TODO: Refactor #1810 - Activate <React.StrictMode> here or in app-start.tsx?
reactRoot[mapId].render(<AppStart mapFeaturesConfig={configObj} />);
// reactRoot[mapId].render(
// <React.StrictMode>
Expand Down
8 changes: 7 additions & 1 deletion packages/geoview-core/src/core/app-start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,14 @@ function AppStart(props: AppStartProps): JSX.Element {
if (!Object.keys(api.maps).includes(mapId)) api.maps[mapId] = new MapViewer(mapFeaturesConfig, i18nInstance);

// Start the process of checking for map readiness
api.maps[mapId].mapReady();
api.maps[mapId].mapReady().then(() => {
// Start the process of checking for layers result set readiness
api.maps[mapId].layerResultSetReady().then(() => {
// Write app-start code logic here to do something when the layers resultset is ready for all layer path
});
});

// TODO: Refactor #1810 - Activate <React.StrictMode> here or in app.tsx?
return (
<I18nextProvider i18n={i18nInstance}>
<MapContext.Provider value={mapContextValue}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ export abstract class AbstractGeoViewLayer {
*
* @param {TypeBaseLayerEntryConfig} layerConfig The layer config to register.
*/
registerToLayerSets(layerConfig: TypeBaseLayerEntryConfig) {
registerToLayerSets(layerConfig: TypeBaseLayerEntryConfig): void {
const { layerPath } = layerConfig;
if (!this.registerToLayerSetListenerFunctions[layerPath]) this.registerToLayerSetListenerFunctions[layerPath] = {};

Expand Down Expand Up @@ -1037,7 +1037,7 @@ export abstract class AbstractGeoViewLayer {
*
* @param {TypeBaseLayerEntryConfig} layerConfig The layer entry to register.
*/
unregisterFromLayerSets(layerConfig: TypeBaseLayerEntryConfig) {
unregisterFromLayerSets(layerConfig: TypeBaseLayerEntryConfig): void {
const { layerPath } = layerConfig;
api.event.emit(LayerSetPayload.createLayerRegistrationPayload(this.mapId, layerPath, 'remove'));

Expand Down
99 changes: 74 additions & 25 deletions packages/geoview-core/src/geo/map/map-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,36 +219,85 @@ export class MapViewer {
}

/**
* Function called when the map has been rendered and ready to be customized
* Function called to monitor when the map is actually ready.
* Important: This function is also responsible for calling the MapEventProcessor.setMapLoaded after 1 second has ellapsed.
*/
mapReady(): void {
mapReady(): Promise<void> {
// Log Marker Start
logger.logMarkerStart(`mapReady-${this.mapId}`);

const layerInterval = setInterval(() => {
// Log
logger.logTraceDetailed('map-viewer.mapReady?', this.mapId);

if (this.layer?.geoviewLayers) {
const { geoviewLayers } = this.layer;
let allGeoviewLayerReady =
this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0;
Object.keys(geoviewLayers).forEach((geoviewLayerId) => {
const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreGreaterThanOrEqualTo('processed');
logger.logTraceDetailed('map-viewer.mapReady? geoview layer ready?', geoviewLayerId, layerIsReady);
allGeoviewLayerReady &&= layerIsReady;
});
if (allGeoviewLayerReady) {
// Log
logger.logInfo('Map is ready', this.mapId);
logger.logMarkerCheck(`mapReady-${this.mapId}`, 'for map to be ready');
// ! We added processed to layers check so this map loaded event is fired faster
// TODO: solve this without using a timeout...
setTimeout(() => MapEventProcessor.setMapLoaded(this.mapId), 1000);
clearInterval(layerInterval);
return new Promise<void>((resolve) => {
// Start an interval checker
const mapInterval = setInterval(() => {
if (this.layer?.geoviewLayers) {
const { geoviewLayers } = this.layer;
let allGeoviewLayerReady =
this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0;
Object.keys(geoviewLayers).forEach((geoviewLayerId) => {
const layerIsReady = geoviewLayers[geoviewLayerId].allLayerStatusAreGreaterThanOrEqualTo('processed');
if (!layerIsReady) logger.logTraceDetailed('map-viewer.mapReady? geoview layer not ready, waiting...', geoviewLayerId);
allGeoviewLayerReady &&= layerIsReady;
});
if (allGeoviewLayerReady) {
// Clear interval
clearInterval(mapInterval);

// Log
logger.logInfo('Map is ready', this.mapId);
logger.logMarkerCheck(`mapReady-${this.mapId}`, 'for map to be ready');

// Resolve the promise
resolve();

// ! We added processed to layers check so this map loaded event is fired faster
// TODO: solve this without using a timeout...
setTimeout(() => MapEventProcessor.setMapLoaded(this.mapId), 1000);
}
}
}
}, 250);
}, 250);
});
}

/**
* Function called to monitor when the layers result sets are actually ready
*/
layerResultSetReady(): Promise<void> {
// Start another interval checker
return new Promise<void>((resolve) => {
const layersInterval = setInterval(() => {
if (api.maps[this.mapId].layer) {
// Check if all registered layers have their results set
let allGood = true;
Object.entries(api.maps[this.mapId].layer.registeredLayers).forEach(([layerPath, registeredLayer]) => {
// If not queryable, don't expect a result set
if (!registeredLayer.source?.featureInfo?.queryable) return;

const { resultSet } = api.getFeatureInfoLayerSet(this.mapId);
const layerResultSetReady = Object.keys(resultSet).includes(layerPath);
if (!layerResultSetReady) {
logger.logTraceDetailed('layer resultset not ready, waiting...', layerPath);
allGood = false;
}
});

// If all good
if (allGood) {
// Clear interval
clearInterval(layersInterval);

// How many layers resultset?
const resultSetCount = Object.keys(api.getFeatureInfoLayerSet(this.mapId).resultSet).length;

// Log
logger.logInfo(`All (${resultSetCount}) Layers ResultSet are ready`, this.mapId);
logger.logMarkerCheck(`mapReady-${this.mapId}`, `for all (${resultSetCount}) Layers ResultSet to be ready`);

// Resolve the promise
resolve();
}
}
}, 250);
});
}

/**
Expand Down
Loading