Skip to content

Commit

Permalink
Introduction of 4 distinct callbacks for cgpv. To better distinguish …
Browse files Browse the repository at this point in the history
…when it's possible to start listening to events

Minor ESLint fixes elsewhere
  • Loading branch information
Alex-NRCan committed Oct 11, 2024
1 parent d07aff8 commit 81c6894
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 91 deletions.
145 changes: 95 additions & 50 deletions packages/geoview-core/public/templates/demos/demo-function-event.html
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,44 @@ <h3>Events that will generate notifications:</h3>
<script src="codedoc.js"></script>
<script src="layerlib.js"></script>
<script>
// initialize cgpv and api events, a callback is optional, used if calling api's after the rendering is ready
cgpv.init(async (mapId) => {
listenToLegendLayerSetChanges('HMap1-state', 'Map1');
// Register a handler when the map is init
cgpv.onMapInit((mapId) => {
// !!
// GV This callback is executed when map is init, but map isn't ready nor layers registered
// !!

listenToLegendLayerSetChanges('HMap1-state', 'Map1');

// listen to map language changed event
cgpv.api.maps.Map1.onMapLanguageChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Map language changed to ${payload.language}`);
});

// listen to basemap changed event
cgpv.api.maps.Map1.basemap.onBasemapChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Basemap changed to ${payload.basemap.basemapId}`);
});

// listen to layer reordered event
cgpv.api.maps.Map1.stateApi.onLayersReordered((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Layers reordered to ${payload.orderedLayers.map((layer) => layer.layerPath)}`);
});

// listen to map added to div event
cgpv.api.onMapAddedToDiv((sender, payload) => {
cgpv.api.maps[payload.mapId].notifications.addNotificationSuccess(`Map ${payload.mapId} added`);
});

// listen to map zoom event
cgpv.api.maps.Map1.onMapZoomEnd((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Zoomed to level ${payload.zoom}`);
});

// listen to map move event
cgpv.api.maps.Map1.onMapMoveEnd((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Map moved to center latitude ${payload.lnglat[1]} and longitude ${payload.lnglat[0]}`);
});

// Events=====================================================================================================================
// listen to layer added event
cgpv.api.maps.Map1.layer.onLayerAdded((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(payload.layer.geoviewLayerId + ' added');
Expand All @@ -220,31 +253,15 @@ <h3>Events that will generate notifications:</h3>

// listen to layer error events
cgpv.api.maps.Map1.layer.onLayerError((sender, payload) => {
// NOTE: The event added layer will be trigger first as the layer, even in error, has been added to ui
// NOTE: The event added layer will be trigger first as the layer, even in error, has been added to ui
cgpv.api.maps.Map1.notifications.addNotificationError(payload.layerPath + ' error');
});

// listen to individual layer loaded event
cgpv.api.maps.Map1.layer.getGeoviewLayer('nonmetalmines/5').onIndividualLayerLoaded((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess('Nonmetal mines has finished loading');
console.log(sender.olRootLayer.getSource().getFeatures());
});

// listen to layer removed event
cgpv.api.maps.Map1.layer.onLayerRemoved((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(payload.layerPath + ' removed');
});

// listen to layer visibility changed event (individual geoview layer)
cgpv.api.maps.Map1.layer.getGeoviewLayer('uniqueValueId/1').onVisibleChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`uniqueValueId/1 visibility set to ${payload.visible} - individual`);
});

// listen to layer visibility changed event (individual geoview layer)
cgpv.api.maps.Map1.layer.getGeoviewLayer('f4c51eaa-a6ca-48b9-a1fc-b0651da20509').onVisibleChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`layer ${payload.layerPath} visibility set to ${payload.visible} - individual`);
});

// listen to layer item visibility changed event (any layers)
cgpv.api.maps.Map1.layer.onLayerVisibilityToggled((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`layer ${payload.layerPath} visibility set to ${payload.visibility} - global`);
Expand All @@ -255,51 +272,79 @@ <h3>Events that will generate notifications:</h3>
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${payload.itemName} on layer ${payload.layerPath} visibility set to ${payload.visibility} - global`);
});

// listen to map zoom event
cgpv.api.maps.Map1.onMapZoomEnd((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Zoomed to level ${payload.zoom}`);
});
// Add more registrations of listeners when the map has been initialized here...

// listen to map move event
cgpv.api.maps.Map1.onMapMoveEnd((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Map moved to center latitude ${payload.lnglat[1]} and longitude ${payload.lnglat[0]}`);
});
});

// Register a handler when the map is ready
cgpv.onMapReady((mapId) => {
// !!
// GV This callback is executed when map is ready / layers registered, but layers aren't necessarily processed
// !!

// listen to layer status change event
cgpv.api.maps.Map1.layer.getLayerEntryConfig('uniqueValueId/1').onLayerStatusChanged((sender, payload) => {
cgpv.api.maps.Map1.layer.getLayerEntryConfig('uniqueValueId/1')?.onLayerStatusChanged((sender, payload) => {
// debugger;
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`uniqueValueId/1 status changed to ${payload.layerStatus}`);
});

// listen to layer filter applied event
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('uniqueValueId/1').onLayerFilterApplied((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Filter ${payload.filter} applied to ${payload.layerPath}`);
// listen to individual layer loaded event
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('nonmetalmines/5')?.onIndividualLayerLoaded((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess('Nonmetal mines has finished loading');
console.log(sender.olRootLayer.getSource().getFeatures());
});

// listen to map language changed event
cgpv.api.maps.Map1.onMapLanguageChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Map language changed to ${payload.language}`);
});
// Add more registrations of listeners when the map is ready / layers registered here...

// listen to basemap changed event
cgpv.api.maps.Map1.basemap.onBasemapChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Basemap changed to ${payload.basemap.basemapId}`);
});

// Register a handler when the layers are init
cgpv.onLayersProcessed((mapId) => {
// !!
// GV This callback is executed when map is init, but layers aren't necessarily loaded
// !!

// Add more registrations of listeners when the layers have been processed here...

});

// Register a handler when the layers are loaded
cgpv.onLayersLoaded((mapId) => {
// !!
// GV This callback is executed when all layers are loaded
// !!

// listen to layer visibility changed event (individual geoview layer)
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('uniqueValueId/1')?.onVisibleChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`uniqueValueId/1 visibility set to ${payload.visible} - individual`);
});

// listen to layer reordered event
cgpv.api.maps.Map1.stateApi.onLayersReordered((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Layers reordered to ${payload.orderedLayers.map((layer) => layer.layerPath)}`);
// listen to layer visibility changed event (individual geoview layer)
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('f4c51eaa-a6ca-48b9-a1fc-b0651da20509')?.onVisibleChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`layer ${payload.layerPath} visibility set to ${payload.visible} - individual`);
});

// listen to layer opacity changed event
cgpv.api.maps.Map1.layer.getGeoviewLayer('uniqueValueId/1').onLayerOpacityChanged((sender, payload) => {
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('uniqueValueId/1')?.onLayerOpacityChanged((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${payload.layerPath} opacity changed to ${payload.opacity}`);
});

// listen to map added to div event
cgpv.api.onMapAddedToDiv((sender, payload) => {
cgpv.api.maps[payload.mapId].notifications.addNotificationSuccess(`Map ${payload.mapId} added`);
// listen to layer filter applied event
cgpv.api.maps.Map1.layer.getGeoviewLayerHybrid('uniqueValueId/1')?.onLayerFilterApplied((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`Filter ${payload.filter} applied to ${payload.layerPath}`);
});
})

// Add more registrations of listeners when the layers have been loaded here...
});

// Initialize cgpv
cgpv.init(async (mapId) => {
// Obsolete callback
// debugger;
}, () => {
// Obsolete callback
// debugger;
});

// Add WMS Button======================================================================================================
// find the button element by ID
var addLayerButton = document.getElementById('Add-layer');
Expand Down Expand Up @@ -682,7 +727,7 @@ <h3>Events that will generate notifications:</h3>
zoomToMarkerGroupButton.addEventListener('click', () => {
cgpv.api.maps.Map1.layer.featureHighlight.pointMarkers.zoomToPointMarkerGroup('group1');
});

// create snippets
window.addEventListener('load', () => {
createCodeSnippet();
Expand Down
110 changes: 88 additions & 22 deletions packages/geoview-core/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export const api = new API();

const reactRoot: Record<string, Root> = {};

let cgpvCallbackMapInit: (mapId: string) => void | undefined;
let cgpvCallbackMapReady: (mapId: string) => void | undefined;
let cgpvCallbackLayersProcessed: (mapId: string) => void | undefined;
let cgpvCallbackLayersLoaded: (mapId: string) => void | undefined;

/**
* Function to unmount a map element
*
Expand Down Expand Up @@ -204,11 +209,10 @@ export async function initMapDivFromFunctionCall(mapDiv: HTMLElement, mapConfig:
}

/**
* Initialize the cgpv and render it to root element
* Initializes the cgpv and render it to root element
*
* @param {(mapId: string) => void} callbackMapInit optional callback function to run once the map rendering is ready
* @param {(mapId: string) => void} callbackMapLayersLoaded optional callback function to run once layers are loaded on the map
* @returns {Promise<void>}
*/
function init(callbackMapInit?: (mapId: string) => void, callbackMapLayersLoaded?: (mapId: string) => void): void {
const mapElements = document.getElementsByClassName('geoview-map');
Expand All @@ -220,31 +224,53 @@ function init(callbackMapInit?: (mapId: string) => void, callbackMapLayersLoaded
// Render the map
const promiseMapInit = renderMap(mapElement);

// The callback for the map init when the promiseMapInit will resolve
const theCallbackMapInit = cgpvCallbackMapInit;

// The callback for the map ready when the promiseMapInit will resolve
const theCallbackMapReady = cgpvCallbackMapReady;

// The callback for the layers processed when the promiseMapInit will resolve
const theCallbackLayersProcessed = cgpvCallbackLayersProcessed;

// The callback for the layers loaded when the promiseMapInit will resolve
const theCallbackLayersLoaded = cgpvCallbackLayersLoaded;

// When the map init is done
promiseMapInit
.then(() => {
// Log
logger.logInfo('Map initialized', mapElement.getAttribute('id')!);

// TODO: Fix this timeout issue when geoCore layer are use in config: https://github.com/Canadian-Geospatial-Platform/geoview/issues/2380
// Set a timeout value if one of thelaeyrs is a geoCore type
const mapId = mapElement.getAttribute('id')!;
const layerTypes = api.maps[mapId].mapFeaturesConfig.map.listOfGeoviewLayerConfig?.map((item) => item.geoviewLayerType) || [];
const geoCoreTimeout = layerTypes.includes('geoCore') ? 500 : 0;

// TODO: Fix this timeout issue when geoCore layer are use in config: https://github.com/Canadian-Geospatial-Platform/geoview/issues/2380
setTimeout(() => {
// Callback about it
callbackMapInit?.(mapId);

// Register when the map viewer will have loaded layers
api.maps[mapId].onMapLayersLoaded((mapViewerLoaded) => {
logger.logInfo('Map layers loaded', mapViewerLoaded.mapId);

// Callback for that particular map
callbackMapLayersLoaded?.(mapViewerLoaded.mapId);
});
}, geoCoreTimeout);
logger.logInfo('Map initialized', mapId);

// Callback about it
theCallbackMapInit?.(mapId);
callbackMapInit?.(mapId); // TODO: Obsolete call, remove it eventually

// Register when the map viewer will have a map ready
api.maps[mapId].onMapReady((mapViewer) => {
logger.logInfo('Map ready / layers registered', mapViewer.mapId);

// Callback for that particular map
theCallbackMapReady?.(mapViewer.mapId);
});

// Register when the map viewer will have loaded layers
api.maps[mapId].onMapLayersProcessed((mapViewer) => {
logger.logInfo('Map layers processed', mapViewer.mapId);

// Callback for that particular map
theCallbackLayersProcessed?.(mapViewer.mapId);
});

// Register when the map viewer will have loaded layers
api.maps[mapId].onMapLayersLoaded((mapViewer) => {
logger.logInfo('Map layers loaded', mapViewer.mapId);

// Callback for that particular map
theCallbackLayersLoaded?.(mapViewer.mapId);
callbackMapLayersLoaded?.(mapViewer.mapId); // TODO: Obsolete call, remove it eventually
});
})
.catch((error) => {
// Log
Expand All @@ -254,9 +280,49 @@ function init(callbackMapInit?: (mapId: string) => void, callbackMapLayersLoaded
}
}

/**
* Registers a callback when the map has been initialized
* @param {(mapId: string) => void} callback - The callback to be called
*/
export function onMapInit(callback: (mapId: string) => void): void {
// Keep the callback
cgpvCallbackMapInit = callback;
}

/**
* Registers a callback when the map has been initialized
* @param {(mapId: string) => void} callback - The callback to be called
*/
export function onMapReady(callback: (mapId: string) => void): void {
// Keep the callback
cgpvCallbackMapReady = callback;
}

/**
* Registers a callback when the layers have been processed
* @param {(mapId: string) => void} callback - The callback to be called
*/
export function onLayersProcessed(callback: (mapId: string) => void): void {
// Keep the callback
cgpvCallbackLayersProcessed = callback;
}

/**
* Registers a callback when the layers have been loaded
* @param {(mapId: string) => void} callback - The callback to be called
*/
export function onLayersLoaded(callback: (mapId: string) => void): void {
// Keep the callback
cgpvCallbackLayersLoaded = callback;
}

// cgpv object to be exported with the api for outside use
export const cgpv: TypeCGPV = {
init,
onMapInit,
onMapReady,
onLayersProcessed,
onLayersLoaded,
api,
react: React,
createRoot,
Expand Down
5 changes: 5 additions & 0 deletions packages/geoview-core/src/core/types/global-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export interface TypeWindow extends Window {
*/
export type TypeCGPV = {
init: CGPVInitCallback;
onMapInit: CGPVCallback;
onMapReady: CGPVCallback;
onLayersProcessed: CGPVCallback;
onLayersLoaded: CGPVCallback;
api: API;
react: typeof React;
createRoot: typeof createRoot;
Expand All @@ -64,6 +68,7 @@ export type TypeCGPV = {
* Type used for a callback function.
*/
export type CGPVInitCallback = (callbackMapsInit?: (mapId: string) => void, callbackMapsLayersLoaded?: (mapId: string) => void) => void;
export type CGPVCallback = (callback: (mapId: string) => void) => void;

/** ******************************************************************************************************************************
* Type used for exporting UI
Expand Down
Loading

0 comments on commit 81c6894

Please sign in to comment.