From c2206f8d4f776e52f623ccef0b7677e438753410 Mon Sep 17 00:00:00 2001 From: "stuart.woodman" Date: Thu, 26 Sep 2024 13:54:11 +1000 Subject: [PATCH] Any layer that has no supported resource but does have a defined bbox can now be added to the map. Replaces existing cswrenderer functionality. --- src/app/browsepanel/browsepanel.component.ts | 23 ++-- src/app/cesium-map/csmap.component.ts | 129 +++++++++--------- .../activelayerspanel.component.scss | 2 +- .../activelayerspanel.component.ts | 2 +- .../filterpanel/filterpanel.component.ts | 18 ++- .../common/model/ui/uilayer.model.ts | 4 +- .../custompanel/custompanel.component.ts | 7 +- .../data-explorer/data-explorer.component.ts | 5 +- .../data-explorer/data-explorer.service.ts | 2 +- .../search/searchpanel.component.html | 2 +- .../menupanel/search/searchpanel.component.ts | 17 ++- .../permanentlinks.modal.component.ts | 2 +- src/app/services/ui/layer-manager.service.ts | 36 ++--- src/app/services/ui/uilayer-model.service.ts | 4 + src/environments/config.ts | 33 ----- 15 files changed, 129 insertions(+), 157 deletions(-) diff --git a/src/app/browsepanel/browsepanel.component.ts b/src/app/browsepanel/browsepanel.component.ts index e077e720..4f18bd6b 100644 --- a/src/app/browsepanel/browsepanel.component.ts +++ b/src/app/browsepanel/browsepanel.component.ts @@ -52,7 +52,6 @@ export class BrowsePanelComponent implements OnInit, AfterViewInit, OnDestroy { * Initialise Component */ public ngOnInit() { - const me = this; this.sidebarSubscription = this.sidebarService.isSidebarOpen$.subscribe( isOpen => { this.isSidebarOpen = isOpen; @@ -61,22 +60,23 @@ export class BrowsePanelComponent implements OnInit, AfterViewInit, OnDestroy { // Initialise layers and groups in sidebar this.layerHandlerService.getLayerRecord().subscribe( response => { - me.layerGroupColumn = response; + this.layerGroupColumn = response; // Loop over each group of layers - for (const group in me.layerGroupColumn) { + for (const group in this.layerGroupColumn) { // Loop over each layer in a group - for (let layer_idx = 0; layer_idx < me.layerGroupColumn[group].length; layer_idx++) { + for (let layer_idx = 0; layer_idx < this.layerGroupColumn[group].length; layer_idx++) { // Initialise a list of cesium layers - me.layerGroupColumn[group][layer_idx].csLayers = []; + this.layerGroupColumn[group][layer_idx].csLayers = []; + // Initialise UILayerModel - const uiLayerModel = new UILayerModel(me.layerGroupColumn[group][layer_idx].id, me.renderStatusService.getStatusBSubject(me.layerGroupColumn[group][layer_idx])); - me.uiLayerModelService.setUILayerModel(me.layerGroupColumn[group][layer_idx].id, uiLayerModel); + const uiLayerModel = new UILayerModel(this.layerGroupColumn[group][layer_idx].id, 100, this.renderStatusService.getStatusBSubject(this.layerGroupColumn[group][layer_idx])); + this.uiLayerModelService.setUILayerModel(this.layerGroupColumn[group][layer_idx].id, uiLayerModel); } } // Sort alphabetically by group name - Object.keys(me.layerGroupColumn).forEach(group => { - me.layerGroupColumn[group].sort((a, b) => a.name.localeCompare(b.name)); + Object.keys(this.layerGroupColumn).forEach(group => { + this.layerGroupColumn[group].sort((a, b) => a.name.localeCompare(b.name)); }); } ); @@ -86,11 +86,10 @@ export class BrowsePanelComponent implements OnInit, AfterViewInit, OnDestroy { * Called after Angular has initialised the view */ public ngAfterViewInit() { - const me = this; this.userStateService.getBookmarks().subscribe(bookMarkList => { - me.layerBookmarked = {} + this.layerBookmarked = {} for (const bookMark of bookMarkList) { - me.layerBookmarked[bookMark.fileIdentifier] = true; + this.layerBookmarked[bookMark.fileIdentifier] = true; } }); } diff --git a/src/app/cesium-map/csmap.component.ts b/src/app/cesium-map/csmap.component.ts index 5ee64719..560eb411 100644 --- a/src/app/cesium-map/csmap.component.ts +++ b/src/app/cesium-map/csmap.component.ts @@ -343,6 +343,7 @@ export class CsMapComponent implements AfterViewInit { this.displayModal(mapClickInfo.clickCoord); // VT: if it is a csw renderer layer, handling of the click is slightly different + // SW: Note that we no longer use cswrenderer, instead if layer has no WMS/KML etc we look at GeographicElement bbox if (config.cswrenderer.includes(entity.layer.id) || CsCSWService.cswDiscoveryRendered.includes(entity.layer.id)) { this.setModalHTML(this.parseCSWtoHTML(entity.cswRecord), entity.cswRecord.name, entity, this.bsModalRef); } @@ -385,88 +386,84 @@ export class CsMapComponent implements AfterViewInit { for (const i of maplayer.clickCSWRecordsIndex) { const cswRecord = maplayer.cswRecords[i]; - // Bail if no OnlineResources - if (!cswRecord.onlineResources || cswRecord.onlineResources.length === 0) { - continue; - } - // Get the WMS OnlineResource, if that fails use the first in the list - let onlineResource = cswRecord.onlineResources.find(or => or.type === ResourceType.WMS); - if (!onlineResource && cswRecord.onlineResources[0]) { + let onlineResource = cswRecord.onlineResources?.find(or => or.type === ResourceType.WMS); + + if (!onlineResource && cswRecord.onlineResources?.length > 0) { onlineResource = cswRecord.onlineResources[0]; } if (onlineResource) { - // Display CSW record info - if (config.cswrenderer.includes(maplayer.id)) { + + if (!UtilitiesService.getLayerHasSupportedOnlineResourceType(maplayer) && UtilitiesService.layerContainsBboxGeographicElement(maplayer)) { + // Display CSW record info this.displayModal(mapClickInfo.clickCoord); this.setModalHTML(this.parseCSWtoHTML(cswRecord), cswRecord.name, maplayer, this.bsModalRef); + } - // Display WMS layer info + // Display WMS layer info + const params = this.getParams(maplayer.clickPixel[0], maplayer.clickPixel[1]); + if (!params) { + continue; + } + let sldBody = maplayer.sldBody; + let postMethod = false; + let infoFormat: string; + if (sldBody) { + sldBody = SimpleXMLService.extractIntersectsFiltersFromSld(sldBody); + postMethod = true; } else { - const params = this.getParams(maplayer.clickPixel[0], maplayer.clickPixel[1]); - if (!params) { - continue; - } - let sldBody = maplayer.sldBody; - let postMethod = false; - let infoFormat: string; - if (sldBody) { - sldBody = SimpleXMLService.extractIntersectsFiltersFromSld(sldBody); - postMethod = true; - } else { - sldBody = ''; - } - - // WMS 1.3.0 GetFeatureInfo requests will have had their lat,lng coords swapped to lng,lat - if (maplayer.sldBody130) { - sldBody = maplayer.sldBody130; - } + sldBody = ''; + } - // Layer specific SLD_BODY, INFO_FORMAT and postMethod - if (onlineResource.name.indexOf('ProvinceFullExtent') >= 0) { - infoFormat = 'application/vnd.ogc.gml'; - } else { - infoFormat = 'application/vnd.ogc.gml/3.1.1'; - } + // WMS 1.3.0 GetFeatureInfo requests will have had their lat,lng coords swapped to lng,lat + if (maplayer.sldBody130) { + sldBody = maplayer.sldBody130; + } - if (UtilitiesService.resourceIsArcGIS(onlineResource)) { - infoFormat = 'text/xml'; - sldBody = ''; - postMethod = false; - } + // Layer specific SLD_BODY, INFO_FORMAT and postMethod + if (onlineResource.name.indexOf('ProvinceFullExtent') >= 0) { + infoFormat = 'application/vnd.ogc.gml'; + } else { + infoFormat = 'application/vnd.ogc.gml/3.1.1'; + } - // GSKY and some Loop3D layers require JSON response - if (config.wmsGetFeatureJSON.indexOf(maplayer.id) !== -1) { - infoFormat = 'application/json'; - } + if (UtilitiesService.resourceIsArcGIS(onlineResource)) { + infoFormat = 'text/xml'; + sldBody = ''; + postMethod = false; + } - if (onlineResource.description.indexOf('EMAG2 - Total Magnetic Intensity') >= 0) { - infoFormat = 'text/xml'; - } + // GSKY and some Loop3D layers require JSON response + if (config.wmsGetFeatureJSON.indexOf(maplayer.id) !== -1) { + infoFormat = 'application/json'; + } - if (onlineResource.description.indexOf('Onshore Seismic Surveys') >= 0) { - infoFormat = 'text/xml'; - } + if (onlineResource.description.indexOf('EMAG2 - Total Magnetic Intensity') >= 0) { + infoFormat = 'text/xml'; + } - // Build GetFeatureInfo requests - getFeatureInfoRequests.push( - this.queryWMSService.getFeatureInfo(onlineResource, sldBody, infoFormat, postMethod, maplayer.clickCoord[0], - maplayer.clickCoord[1], params.x, params.y, params.width, params.height, params.bbox).pipe( - timeout(5000), - tap(result => { - // Update the modal features as each request completes - const feature = { onlineResource: onlineResource, layer: maplayer }; - const numberOfLayerFeatures = this.setModal(maplayer.id, result, feature, mapClickInfo.clickCoord); - if (numberOfLayerFeatures > 0) { - numberOfFeatures += numberOfLayerFeatures; - } - }), catchError((error) => { - return throwError(error); - }) - ) - ); + if (onlineResource.description.indexOf('Onshore Seismic Surveys') >= 0) { + infoFormat = 'text/xml'; } + + // Build GetFeatureInfo requests + getFeatureInfoRequests.push( + this.queryWMSService.getFeatureInfo(onlineResource, sldBody, infoFormat, postMethod, maplayer.clickCoord[0], + maplayer.clickCoord[1], params.x, params.y, params.width, params.height, params.bbox).pipe( + timeout(5000), + tap(result => { + // Update the modal features as each request completes + const feature = { onlineResource: onlineResource, layer: maplayer }; + const numberOfLayerFeatures = this.setModal(maplayer.id, result, feature, mapClickInfo.clickCoord); + if (numberOfLayerFeatures > 0) { + numberOfFeatures += numberOfLayerFeatures; + } + }), catchError((error) => { + return throwError(error); + }) + ) + ); } } } diff --git a/src/app/menupanel/activelayers/activelayerspanel.component.scss b/src/app/menupanel/activelayers/activelayerspanel.component.scss index c89a3a35..339e86e2 100644 --- a/src/app/menupanel/activelayers/activelayerspanel.component.scss +++ b/src/app/menupanel/activelayers/activelayerspanel.component.scss @@ -137,7 +137,7 @@ .activeLayerContent { width:100%; - color: $text-colour; // XXX Needs to be darker but may be fixed at a higher level + color: $text-colour; } .activeLayerDragMessagePanel { diff --git a/src/app/menupanel/activelayers/activelayerspanel.component.ts b/src/app/menupanel/activelayers/activelayerspanel.component.ts index c3e3a68e..dc242993 100644 --- a/src/app/menupanel/activelayers/activelayerspanel.component.ts +++ b/src/app/menupanel/activelayers/activelayerspanel.component.ts @@ -413,7 +413,7 @@ export class ActiveLayersPanelComponent implements AfterViewInit { * @returns true if supported layer, false otherwise */ public isMapSupportedLayer(layer: LayerModel): boolean { - return this.csMapService.isMapSupportedLayer(layer); + return UtilitiesService.isMapSupportedLayer(layer); } /** diff --git a/src/app/menupanel/common/filterpanel/filterpanel.component.ts b/src/app/menupanel/common/filterpanel/filterpanel.component.ts index 25a6c941..cb5d615f 100644 --- a/src/app/menupanel/common/filterpanel/filterpanel.component.ts +++ b/src/app/menupanel/common/filterpanel/filterpanel.component.ts @@ -73,7 +73,6 @@ export class FilterPanelComponent implements OnInit, AfterViewInit { } } - // XXX Sidebar only..? if (this.layer.filterCollection && this.layer.filterCollection['mandatoryFilters']) { const mandatoryFilters = this.layer.filterCollection['mandatoryFilters']; for (const mandatoryFilter of mandatoryFilters) { @@ -152,9 +151,8 @@ export class FilterPanelComponent implements OnInit, AfterViewInit { return optFilt; }); - const me = this; setTimeout(() => { - for (const optFilter of me.optionalFilters) { + for (const optFilter of this.optionalFilters) { if (optFilter['value'] && optFilter['type'] === 'OPTIONAL.POLYGONBBOX') { const geometry = optFilter['value']; const swappedGeometry = this.csClipboardService.swapGeometry(geometry); @@ -170,13 +168,13 @@ export class FilterPanelComponent implements OnInit, AfterViewInit { this.appRef.tick(); } } - me.layerManagerService.addLayer(me.layer, me.optionalFilters, me.layerFilterCollection, me.layerTimes.currentTime); + this.layerManagerService.addLayer(this.layer, this.optionalFilters, this.layerFilterCollection, this.layerTimes.currentTime); // Set opacity of the layer on the map - if (UtilitiesService.layerContainsResourceType(me.layer, ResourceType.WMS)) { - me.csWMSService.setOpacity(this.layer, layerState.opacity / 100.0 ); - } else if (this.conf.cswrenderer && this.conf.cswrenderer.includes(me.layer.id)) { - me.csCSWService.setOpacity(this.layer, layerState.opacity / 100.0 ); + if (UtilitiesService.layerContainsResourceType(this.layer, ResourceType.WMS)) { + this.csWMSService.setLayerOpacity(this.layer, layerState.opacity / 100.0 ); + } else if (UtilitiesService.layerContainsBboxGeographicElement(this.layer)) { + this.csCSWService.setLayerOpacity(this.layer, layerState.opacity / 100.0 ); } }, 500); } @@ -208,7 +206,7 @@ export class FilterPanelComponent implements OnInit, AfterViewInit { * @returns true if supported layer, false otherwise */ public isMapSupportedLayer(layer: LayerModel): boolean { - return this.csMapService.isMapSupportedLayer(layer); + return UtilitiesService.isMapSupportedLayer(layer); } /** @@ -217,7 +215,7 @@ export class FilterPanelComponent implements OnInit, AfterViewInit { */ public getUnsupportedLayerMessage(): string { return 'This layer cannot be displayed. Only the following online resource types can be added to the map: ' + - this.csMapService.getSupportedOnlineResourceTypes(); + UtilitiesService.getSupportedOnlineResourceTypes(); } /** diff --git a/src/app/menupanel/common/model/ui/uilayer.model.ts b/src/app/menupanel/common/model/ui/uilayer.model.ts index 39be1c85..e2e3311f 100644 --- a/src/app/menupanel/common/model/ui/uilayer.model.ts +++ b/src/app/menupanel/common/model/ui/uilayer.model.ts @@ -11,10 +11,10 @@ export class UILayerModel { statusMap: StatusMapModel; opacity: number; - constructor(public id: string, public loadingSubject: BehaviorSubject) { + constructor(id: string, opacity: number, loadingSubject: BehaviorSubject) { this.tabpanel = new UITabPanel(); this.expanded = false; - this.opacity = 100; + this.opacity = opacity; loadingSubject.subscribe((value) => { this.statusMap = value; }); diff --git a/src/app/menupanel/custompanel/custompanel.component.ts b/src/app/menupanel/custompanel/custompanel.component.ts index d6e06b9f..505cd6a1 100644 --- a/src/app/menupanel/custompanel/custompanel.component.ts +++ b/src/app/menupanel/custompanel/custompanel.component.ts @@ -256,8 +256,9 @@ export class CustomPanelComponent { for (const layerRec of layerRecs) { // Make the layer group listing visible in the UI this.urlLayers.unshift(layerRec); + // Configure layers so they can be added to map - const uiLayerModel = new UILayerModel(layerRec.id, this.renderStatusService.getStatusBSubject(layerRec)); + const uiLayerModel = new UILayerModel(layerRec.id, 100, this.renderStatusService.getStatusBSubject(layerRec)); this.uiLayerModelService.setUILayerModel(layerRec.id, uiLayerModel); } } @@ -391,8 +392,8 @@ export class CustomPanelComponent { layerRec.group = 'kml-layer'; } // Configure layers so it can be added to map - const uiLayerModel = new UILayerModel(layerRec.id, me.renderStatusService.getStatusBSubject(layerRec)); - me.uiLayerModelService.setUILayerModel(layerRec.id, uiLayerModel); + const uiLayerModel = new UILayerModel(layerRec.id, 100, me.renderStatusService.getStatusBSubject(layerRec)); + this.uiLayerModelService.setUILayerModel(layerRec.id, uiLayerModel); // Make the layer group listing visible in the UI if (sourceType == "URL" && !this.recordsListContainsRecord(me.urlLayers, name, proxyUrl)) { me.urlLayers.unshift(layerRec); diff --git a/src/app/menupanel/data-explorer/data-explorer.component.ts b/src/app/menupanel/data-explorer/data-explorer.component.ts index 751e93d6..dc3995ce 100644 --- a/src/app/menupanel/data-explorer/data-explorer.component.ts +++ b/src/app/menupanel/data-explorer/data-explorer.component.ts @@ -260,7 +260,7 @@ export class DataExplorerComponent implements OnInit { response["data"].searchErrors[registry.id]; } for (const item of response["itemLayers"]) { - const uiLayerModel = new UILayerModel(item.id, this.renderStatusService.getStatusBSubject(item)); + const uiLayerModel = new UILayerModel(item.id, 100, this.renderStatusService.getStatusBSubject(item)); this.uiLayerModelService.setUILayerModel(item.id, uiLayerModel); } response["itemLayers"].useDefaultProxy = true; @@ -364,9 +364,10 @@ export class DataExplorerComponent implements OnInit { registry.recordsMatched = response["data"].recordsMatched; for (const item of response["itemLayers"]) { - const uiLayerModel = new UILayerModel(item.id, this.renderStatusService.getStatusBSubject(item)); + const uiLayerModel = new UILayerModel(item.id, 100, this.renderStatusService.getStatusBSubject(item)); this.uiLayerModelService.setUILayerModel(item.id, uiLayerModel); } + response["itemLayers"].useDefaultProxy = true; response["itemLayers"].useProxyWhitelist = false; if (response["data"].searchErrors && response["data"].searchErrors.length > 0) { diff --git a/src/app/menupanel/data-explorer/data-explorer.service.ts b/src/app/menupanel/data-explorer/data-explorer.service.ts index 7230dd4d..bbb00df9 100644 --- a/src/app/menupanel/data-explorer/data-explorer.service.ts +++ b/src/app/menupanel/data-explorer/data-explorer.service.ts @@ -75,7 +75,7 @@ export class DataExplorerService { * @param type * @param comparison */ - // XXX GET RID OF THIS AND REPLACE WITH NEXT METHOD + // TODO: GET RID OF THIS AND REPLACE WITH NEXT METHOD public getFacetedSearch(serviceId: string, start: number, limit: number, field: string[], value: string[], type: string[], comparison: string[]): Observable { diff --git a/src/app/menupanel/search/searchpanel.component.html b/src/app/menupanel/search/searchpanel.component.html index dca5da1d..49ffd301 100644 --- a/src/app/menupanel/search/searchpanel.component.html +++ b/src/app/menupanel/search/searchpanel.component.html @@ -138,7 +138,7 @@ {{ searchResult.layer.name }} CSW Featured - +