Skip to content

Commit

Permalink
2611 visibility refresh (#2627)
Browse files Browse the repository at this point in the history
* Visibility updated on language change (#2611)

* Revert small changes

* Properly handle re-removing layers on reload

* Update method description and parameters

* Slight adjustments

* Remove return type from method description

* Remove commented code

* Add TODO for getAllChildPaths function

* Switch to onLayerLoaded for visibility
  • Loading branch information
MatthewMuehlhauserNRCan authored Dec 6, 2024
1 parent 2c33a79 commit ce0e3df
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ export class MapEventProcessor extends AbstractEventProcessor {

let configLayerEntryConfig;
if (geoviewLayerConfig) {
configLayerEntryConfig = (geoviewLayerConfig as TypeGeoviewLayerConfig).listOfLayerEntryConfig.find(
configLayerEntryConfig = (geoviewLayerConfig as TypeGeoviewLayerConfig).listOfLayerEntryConfig?.find(
(nextEntryConfig: TypeLayerEntryConfig) => nextEntryConfig.layerId === pathArray[1]
);
for (let i = 2; i < pathArray.length; i++) {
Expand Down
113 changes: 74 additions & 39 deletions packages/geoview-core/src/geo/layer/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,53 +559,88 @@ export class LayerApi {
logger.logError(`Duplicate use of geoview layer identifier ${mapConfigLayerEntry.geoviewLayerId} on map ${this.getMapId()}`);
}

/**
* TODO Add this function to utilties
* Gets all child paths from a parent path
* @param {string} parentPath - The parent path
* @returns {string[]} Child layer paths
*/
#getAllChildPaths(parentPath: string): string[] {
const parentLayerEntryConfig = this.getLayerEntryConfig(parentPath)?.geoviewLayerConfig.listOfLayerEntryConfig;

if (!parentLayerEntryConfig) return [];

function getChildPaths(listOfLayerEntryConfig: TypeLayerEntryConfig[]): string[] {
const layerPaths: string[] = [];
listOfLayerEntryConfig.forEach((entryConfig) => {
layerPaths.push(entryConfig.layerPath);
if (entryConfig.listOfLayerEntryConfig) {
layerPaths.push(...getChildPaths(entryConfig.listOfLayerEntryConfig));
}
});
return layerPaths;
}

const layerPaths = getChildPaths(parentLayerEntryConfig);
return layerPaths;
}

/**
* Refreshes GeoCore Layers
* @returns {Promise<void>} A promise which resolves when done refreshing
*/
reloadGeocoreLayers(): Promise<void> {
reloadGeocoreLayers(): void {
const configs = this.getLayerEntryConfigs();
const originalMapOrderedLayerInfo = MapEventProcessor.getMapOrderedLayerInfo(this.getMapId());
const promisesOfGeoCoreGeoviewLayers: Promise<TypeGeoviewLayerConfig[]>[] = [];

configs
.filter((config) => {
// Filter to just Geocore layers and not child layers
if (api.config.isValidUUID(config.geoviewLayerConfig.geoviewLayerId) && config.parentLayerConfig === undefined) {
return true;
}
return false;
})
.forEach((config) => {
// Remove and add back in GeoCore Layers and return their promises
this.removeLayerUsingPath(config.layerPath);
const geoCore = new GeoCore(this.getMapId(), this.mapViewer.getDisplayLanguage());
promisesOfGeoCoreGeoviewLayers.push(geoCore.createLayersFromUUID(config.geoviewLayerConfig.geoviewLayerId));
});

return Promise.allSettled(promisesOfGeoCoreGeoviewLayers)
.then((promisedLayers) => {
promisedLayers
.filter((promise) => promise.status === 'fulfilled')
.map((promise) => promise as PromiseFulfilledResult<TypeGeoviewLayerConfig[]>)
.forEach((promise) => {
promise.value.forEach((geoviewLayerConfig) => {
this.addGeoviewLayer(geoviewLayerConfig);
const parentPaths: string[] = [];

// Have to do the Promise allSettled so the new MapOrderedLayerInfo has all the children layerPaths
Promise.allSettled(
configs
.filter((config) => {
// Filter to just Geocore layers and not child layers
if (api.config.isValidUUID(config.geoviewLayerConfig.geoviewLayerId) && config.parentLayerConfig === undefined) {
return true;
}
return false;
})
.map((config) => {
// Remove and add back in GeoCore Layers and return their promises
parentPaths.push(config.layerPath);
this.removeLayerUsingPath(config.layerPath);
return this.addGeoviewLayerByGeoCoreUUID(config.geoviewLayerConfig.geoviewLayerId);
})
)
.then(() => {
const originalLayerPaths = originalMapOrderedLayerInfo.map((info) => info.layerPath);

// Prepare listeners for removing previously removed layers
parentPaths.forEach((parentPath) => {
function removeChildLayers(sender: LayerApi): void {
const childPaths = sender.#getAllChildPaths(parentPath);
childPaths.forEach((childPath) => {
if (!originalLayerPaths.includes(childPath)) {
sender.removeLayerUsingPath(childPath);
}
});
});
const newMapOrderedLayerInfo = MapEventProcessor.getMapOrderedLayerInfo(this.getMapId());
const originalLayerPaths = originalMapOrderedLayerInfo.map((layer) => layer.layerPath);
const childLayersToRemove = newMapOrderedLayerInfo
.map((layer) => layer.layerPath)
.filter((path) => !originalLayerPaths.includes(path));
if (childLayersToRemove) {
childLayersToRemove.forEach((childPath) => {
this.removeLayerUsingPath(childPath);
});
}
sender.offLayerAdded(removeChildLayers);
}
this.onLayerAdded(removeChildLayers);
});

// Prepare listeners for changing the visibility
MapEventProcessor.setMapOrderedLayerInfo(this.getMapId(), originalMapOrderedLayerInfo);
originalMapOrderedLayerInfo.forEach((layerInfo) => {
function setLayerVisibility(sender: LayerApi, event: LayerLoadedEvent): void {
if (layerInfo.layerPath === event.layerPath) {
const { visible } = originalMapOrderedLayerInfo.filter((info) => info.layerPath === event.layerPath)[0];
event.layer?.setVisible(visible, event.layerPath);
sender.offLayerLoaded(setLayerVisibility);
}
}
this.onLayerLoaded(setLayerVisibility);
});
})
.catch((error) => logger.logError(error));
.catch((err) => logger.logError(err));
}

/**
Expand Down
16 changes: 7 additions & 9 deletions packages/geoview-core/src/geo/map/map-viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -918,28 +918,26 @@ export class MapViewer {
*
* @param {TypeDisplayLanguage} displayLanguage - The language to use (en, fr)
* @param {boolean} resetLayer - Optional flag to ask viewer to reload layers with the new localize language
* @returns {Promise<[void, void]>}
* @returns {Promise<void>}
*/
setLanguage(displayLanguage: TypeDisplayLanguage, reloadLayers?: boolean | false): Promise<[void, void]> {
async setLanguage(displayLanguage: TypeDisplayLanguage, reloadLayers?: boolean | false): Promise<void> {
// If the language hasn't changed don't do anything
if (AppEventProcessor.getDisplayLanguage(this.mapId) === displayLanguage) return Promise.resolve([undefined, undefined]);
if (AppEventProcessor.getDisplayLanguage(this.mapId) === displayLanguage) return;
if (VALID_DISPLAY_LANGUAGE.includes(displayLanguage)) {
const promise = AppEventProcessor.setDisplayLanguage(this.mapId, displayLanguage);
await AppEventProcessor.setDisplayLanguage(this.mapId, displayLanguage);

// if flag is true, reload GeoCore layers
// if flag is true, reload just the GeoCore layers instead of reloading the whole map with current state
if (reloadLayers) {
this.layer.reloadGeocoreLayers().catch((error) => logger.logError(error));
this.layer.reloadGeocoreLayers();
}

// Emit language changed event
this.#emitMapLanguageChanged({ language: displayLanguage });
// Return the promise
return promise;
return;
}

// Unsupported
this.notifications.addNotificationError(getLocalizedMessage('validation.changeDisplayLanguage', displayLanguage));
return Promise.resolve([undefined, undefined]);
}

/**
Expand Down

0 comments on commit ce0e3df

Please sign in to comment.