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

feat-fix(layers-event): Add getGeoJSON for vector layer, patch timing… #2382

Merged
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
15 changes: 15 additions & 0 deletions packages/geoview-core/public/configs/OSDP/function-event.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"labeled": true
},
"listOfGeoviewLayerConfig": [
{
"geoviewLayerType": "geoCore",
"geoviewLayerId": "f4c51eaa-a6ca-48b9-a1fc-b0651da20509"
},
{
"geoviewLayerId": "airborne_radioactivity",
"geoviewLayerName": {
Expand All @@ -25,6 +29,17 @@
}
]
},
{
"geoviewLayerId": "errorId",
"geoviewLayerName": { "en": "uniqerrorLayerueValue" },
"metadataAccessPath": { "en": "https://maps-cartes.ec.gc.ca/arcgis/rest/services/CESI/MapServer1/" },
"geoviewLayerType": "esriFeature",
"listOfLayerEntryConfig": [
{
"layerId": "1"
}
]
},
{
"geoviewLayerId": "uniqueValueId",
"geoviewLayerName": { "en": "uniqueValue" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ <h3>Events that will generate notifications:</h3>
<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((mapId) => {
cgpv.init(async (mapId) => {
listenToLegendLayerSetChanges('HMap1-state', 'Map1');

// Events=====================================================================================================================
Expand All @@ -192,6 +192,12 @@ <h3>Events that will generate notifications:</h3>
cgpv.api.maps.Map1.notifications.addNotificationSuccess(payload.layerPath + ' loaded');
});

// 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
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');
Expand All @@ -203,14 +209,24 @@ <h3>Events that will generate notifications:</h3>
cgpv.api.maps.Map1.notifications.addNotificationSuccess(payload.layerPath + ' removed');
});

// listen to layer visibility changed event
// 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}`);
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('rcs.f4c51eaa-a6ca-48b9-a1fc-b0651da20509.en').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`);
});

// listen to layer item visibility changed event
// listen to layer item visibility changed event (any layers)
cgpv.api.maps.Map1.layer.onLayerItemVisibilityToggled((sender, payload) => {
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${payload.itemName} on layer ${payload.layerPath} visibility set to ${payload.visibility}`);
cgpv.api.maps.Map1.notifications.addNotificationSuccess(`${payload.itemName} on layer ${payload.layerPath} visibility set to ${payload.visibility} - global`);
});

// listen to map zoom event
Expand Down
2 changes: 1 addition & 1 deletion packages/geoview-core/src/api/config/config-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class ConfigApi {
* @returns {boolean} Returns true if the UUID respect the format.
* @static
*/
static isValidUUID(uuid: string) {
static isValidUUID(uuid: string): boolean {
const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
return regex.test(uuid);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,43 +550,11 @@ export class MapEventProcessor extends AbstractEventProcessor {
}

static setOrToggleMapLayerVisibility(mapId: string, layerPath: string, newValue?: boolean): void {
// Apply some visibility logic
const curOrderedLayerInfo = this.getMapStateProtected(mapId).orderedLayerInfo;
const layerVisibility = this.getMapVisibilityFromOrderedLayerInfo(mapId, layerPath);
// Determine the outcome of the new visibility based on parameters
const newVisibility = newValue !== undefined ? newValue : !layerVisibility;
const layerInfos = curOrderedLayerInfo.filter((info) => info.layerPath.startsWith(layerPath));
const parentLayerPathArray = layerPath.split('/');
parentLayerPathArray.pop();
const parentLayerPath = parentLayerPathArray.join('/');
const parentLayerInfo = curOrderedLayerInfo.find((info) => info.layerPath === parentLayerPath);

layerInfos.forEach((layerInfo) => {
if (layerInfo) {
// If the new visibility is different than before
if (newVisibility !== layerVisibility) {
// Go for it
// eslint-disable-next-line no-param-reassign
layerInfo.visible = newVisibility;
this.getMapViewerLayerAPI(mapId).getGeoviewLayerHybrid(layerInfo.layerPath)?.setVisible(layerInfo.visible, layerInfo.layerPath);
}
}
});

if (parentLayerInfo !== undefined) {
const parentLayerVisibility = this.getMapVisibilityFromOrderedLayerInfo(mapId, parentLayerPath);
if ((!layerVisibility || newValue) && parentLayerVisibility === false) {
if (parentLayerInfo) {
parentLayerInfo.visible = true;
this.getMapViewerLayerAPI(mapId).getGeoviewLayerHybrid(parentLayerPath)?.setVisible(true, parentLayerPath);
}
}
const children = curOrderedLayerInfo.filter(
(info) => info.layerPath.startsWith(parentLayerPath) && info.layerPath !== parentLayerPath
);
if (!children.some((child) => child.visible === true)) this.setOrToggleMapLayerVisibility(mapId, parentLayerPath, false);
}
// Redirect to layerAPI
this.getMapViewerLayerAPI(mapId).setOrToggleLayerVisibility(layerPath, newValue);
}

static setOrderedLayerInfoWithNoOrderChangeState(mapId: string, curOrderedLayerInfo: TypeOrderedLayerInfo[]): void {
// Redirect
this.getMapStateProtected(mapId).setterActions.setOrderedLayerInfo([...curOrderedLayerInfo]);
}
Expand Down
28 changes: 18 additions & 10 deletions packages/geoview-core/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,25 @@ function init(callbackMapInit?: (mapId: string) => void, callbackMapLayersLoaded
// Log
logger.logInfo('Map initialized', mapElement.getAttribute('id')!);

// Callback about it
// 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')!;
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);
});
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);
})
.catch((error) => {
// Log
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ export abstract class AbstractGeoViewLayer {
const curVisible = this.getVisible(layerPath);
olLayer.setVisible(layerVisibility);
// olLayer.changed();
if (layerVisibility !== curVisible) this.#emitVisibleChanged({ visible: layerVisibility });
if (layerVisibility !== curVisible) this.#emitVisibleChanged({ layerPath, visible: layerVisibility });
}
}

Expand Down Expand Up @@ -1954,6 +1954,7 @@ type LegendQueriedDelegate = EventDelegateBase<AbstractGeoViewLayer, LegendQueri
* Define an event for the delegate
*/
export type VisibleChangedEvent = {
layerPath: string;
visible: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Vector as VectorSource } from 'ol/source';
import { Options as SourceOptions } from 'ol/source/Vector';
import { VectorImage as VectorLayer } from 'ol/layer';
import { Options as VectorLayerOptions } from 'ol/layer/VectorImage';
import { GeoJSON as FormatGeoJSON } from 'ol/format';
import { all, bbox } from 'ol/loadingstrategy';
import { ReadOptions } from 'ol/format/Feature';
import BaseLayer from 'ol/layer/Base';
Expand Down Expand Up @@ -507,6 +508,24 @@ export abstract class AbstractGeoViewVector extends AbstractGeoViewLayer {
return Promise.resolve(undefined);
}

/**
* Return the vector layer as a GeoJSON object
* @param {string} layerPath - Layer path to get GeoJSON
* @returns {JSON} Layer's features as GeoJSON
*/
getFeaturesAsGeoJSON(layerPath: string): JSON {
// Get map projection
const mapProjection: ProjectionLike = this.getMapViewer().getProjection().getCode();

const format = new FormatGeoJSON();
const geoJsonStr = format.writeFeatures((this.getOLLayer(layerPath) as VectorLayer<Feature>).getSource()!.getFeatures(), {
dataProjection: 'EPSG:4326', // Output projection,
featureProjection: mapProjection,
});

return JSON.parse(geoJsonStr);
}

/**
* Overrides when the layer gets in loaded status.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ export abstract class AbstractGVLayer {
setVisible(layerVisibility: boolean): void {
const curVisible = this.getVisible();
this.getOLLayer().setVisible(layerVisibility);
if (layerVisibility !== curVisible) this.#emitVisibleChanged({ visible: layerVisibility });
if (layerVisibility !== curVisible) this.#emitVisibleChanged({ layerPath: this.getLayerPath(), visible: layerVisibility });
}

/**
Expand Down Expand Up @@ -1187,6 +1187,8 @@ type LegendQueriedDelegate = EventDelegateBase<AbstractGVLayer, LegendQueriedEve
* Define an event for the delegate
*/
export type VisibleChangedEvent = {
// TODO: Refactor - Layers refactoring. Remove the layerPath parameter once hybrid work is done
layerPath: string;
visible: boolean;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import BaseLayer from 'ol/layer/Base';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Options as VectorLayerOptions } from 'ol/layer/VectorImage';
import { GeoJSON as FormatGeoJSON } from 'ol/format';
import Style from 'ol/style/Style';
import { Coordinate } from 'ol/coordinate';
import { Extent } from 'ol/extent';
import { Pixel } from 'ol/pixel';
import Feature, { FeatureLike } from 'ol/Feature';
import { ProjectionLike } from 'ol/proj';

import { getUid } from 'ol/util';
import { DateMgt } from '@/core/utils/date-mgt';
Expand Down Expand Up @@ -286,6 +288,23 @@ export abstract class AbstractGVVector extends AbstractGVLayer {
return Promise.resolve(undefined);
}

/**
* Return the vector layer as a GeoJSON object
* @returns {JSON} Layer's features as GeoJSON
*/
getFeaturesAsGeoJSON(): JSON {
// Get map projection
const mapProjection: ProjectionLike = this.getMapViewer().getProjection().getCode();

const format = new FormatGeoJSON();
const geoJsonStr = format.writeFeatures((this.getOLLayer() as VectorLayer<Feature>).getSource()!.getFeatures(), {
dataProjection: 'EPSG:4326', // Output projection,
featureProjection: mapProjection,
});

return JSON.parse(geoJsonStr);
}

/**
* Calculates a style for the given feature, based on the layer current style and options.
* @param {AbstractGeoViewLayer | AbstractGVLayer} layer - The layer on which to work for the style.
Expand Down
Loading
Loading