diff --git a/demo/src/app/geo/layer/layer.component.ts b/demo/src/app/geo/layer/layer.component.ts index 0fc87836f8..8f4ae4c57e 100644 --- a/demo/src/app/geo/layer/layer.component.ts +++ b/demo/src/app/geo/layer/layer.component.ts @@ -95,8 +95,8 @@ export class AppLayerComponent { url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/igo_gouvouvert.fcgi', optionsFromCapabilities: true, params: { - layers: 'MELS_CS_ANGLO_S', - version: '1.3.0' + LAYERS: 'MELS_CS_ANGLO_S', + VERSION: '1.3.0' } } }) @@ -110,8 +110,8 @@ export class AppLayerComponent { type: 'wms', url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/swtq', params: { - layers: 'bgr_v_sous_route_res_sup_act', - version: '1.3.0' + LAYERS: 'bgr_v_sous_route_res_sup_act', + VERSION: '1.3.0' } } }) @@ -126,8 +126,8 @@ export class AppLayerComponent { url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/swtq', optionsFromCapabilities: true, params: { - layers: 'lieuhabite', - version: '1.3.0' + LAYERS: 'lieuhabite', + VERSION: '1.3.0' } } }) @@ -142,8 +142,8 @@ export class AppLayerComponent { url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/mffpecofor.fcgi', optionsFromCapabilities: true, params: { - layers: 'sh_dis_eco', - version: '1.3.0' + LAYERS: 'sh_dis_eco', + VERSION: '1.3.0' } } }) @@ -167,8 +167,8 @@ export class AppLayerComponent { url: 'https://demo.geo-solutions.it/geoserver/ows', optionsFromCapabilities: true, params: { - layers: 'nurc:Arc_Sample', // , test:Linea_costa - version: '1.3.0' + LAYERS: 'nurc:Arc_Sample', // , test:Linea_costa + VERSION: '1.3.0' } } }) @@ -182,8 +182,8 @@ export class AppLayerComponent { type: 'wms', url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/swtq', params: { - layers: 'evenements', - version: '1.3.0' + LAYERS: 'evenements', + VERSION: '1.3.0' } } }) @@ -194,8 +194,8 @@ export class AppLayerComponent { url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/igo_gouvouvert.fcgi', refreshIntervalSec: 15, params: { - layers: 'vg_observation_v_inondation_embacle_wmst', - version: '1.3.0' + LAYERS: 'vg_observation_v_inondation_embacle_wmst', + VERSION: '1.3.0' } }; diff --git a/demo/src/app/geo/ogc-filter/ogc-filter.component.ts b/demo/src/app/geo/ogc-filter/ogc-filter.component.ts index 10dd8dff45..a44ea879e4 100644 --- a/demo/src/app/geo/ogc-filter/ogc-filter.component.ts +++ b/demo/src/app/geo/ogc-filter/ogc-filter.component.ts @@ -124,8 +124,8 @@ export class AppOgcFilterComponent { url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/swtq', urlWfs: 'https://geoegl.msp.gouv.qc.ca/apis/ws/swtq', params: { - layers: 'radars_photos', - version: '1.3.0' + LAYERS: 'radars_photos', + VERSION: '1.3.0' }, ogcFilters: { enabled: true, @@ -296,8 +296,8 @@ export class AppOgcFilterComponent { // url: '/geoserver/wms', // urlWfs: '/geoserver/wfs', // params: { - // layers: 'water_areas', - // version: '1.3.0' + // LAYERS: 'water_areas', + // VERSION: '1.3.0' // }, // ogcFilters: { // enabled: true, diff --git a/demo/src/app/geo/print/print.component.ts b/demo/src/app/geo/print/print.component.ts index 80debb05ee..f4783f6631 100644 --- a/demo/src/app/geo/print/print.component.ts +++ b/demo/src/app/geo/print/print.component.ts @@ -47,8 +47,8 @@ export class AppPrintComponent { type: 'wms', url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/igo_gouvouvert.fcgi', params: { - layers: 'MELS_CS_ANGLO_S', - version: '1.3.0' + LAYERS: 'MELS_CS_ANGLO_S', + VERSION: '1.3.0' }, crossOrigin: 'anonymous' } @@ -62,8 +62,8 @@ export class AppPrintComponent { type: 'wms', url: 'https://geoegl.msp.gouv.qc.ca/apis/ws/igo_gouvouvert.fcgi', params: { - layers: 'vg_observation_v_inondation_embacle_wmst', - version: '1.3.0' + LAYERS: 'vg_observation_v_inondation_embacle_wmst', + VERSION: '1.3.0' }, crossOrigin: 'anonymous' } @@ -77,8 +77,8 @@ export class AppPrintComponent { // type: 'wms', // url: 'http://geo.weather.gc.ca/geomet/?lang=fr', // params: { - // layers: 'RADAR_1KM_RDBR', - // version: '1.3.0' + // LAYERS: 'RADAR_1KM_RDBR', + // VERSION: '1.3.0' // }, // crossOrigin: 'anonymous' // } diff --git a/demo/src/app/geo/time-filter/time-filter.component.ts b/demo/src/app/geo/time-filter/time-filter.component.ts index 99bc9d48dc..1aa5a1df80 100644 --- a/demo/src/app/geo/time-filter/time-filter.component.ts +++ b/demo/src/app/geo/time-filter/time-filter.component.ts @@ -70,8 +70,8 @@ export class AppTimeFilterComponent { type: 'wms', url: 'https://geoegl.msp.gouv.qc.ca/ws/igo_gouvouvert.fcgi', params: { - layers: 'vg_observation_v_inondation_embacle_wmst', - version: '1.3.0' + LAYERS: 'vg_observation_v_inondation_embacle_wmst', + VERSION: '1.3.0' }, timeFilterable: true, timeFilter: { diff --git a/demo/src/app/geo/workspace/workspace.component.ts b/demo/src/app/geo/workspace/workspace.component.ts index 140ea40cb0..2576b3643d 100644 --- a/demo/src/app/geo/workspace/workspace.component.ts +++ b/demo/src/app/geo/workspace/workspace.component.ts @@ -81,8 +81,8 @@ export class AppWorkspaceComponent implements OnInit { // url: 'https://ahocevar.com/geoserver/wms', // urlWfs: 'https://ahocevar.com/geoserver/wfs', // params: { - // layers: 'water_areas', - // version: '1.3.0' + // LAYERS: 'water_areas', + // VERSION: '1.3.0' // }, // paramsWFS: { // featureTypes: 'water_areas', diff --git a/packages/context/src/lib/share-map/shared/share-map.service.ts b/packages/context/src/lib/share-map/shared/share-map.service.ts index bdb4da76fb..bb987a14f7 100644 --- a/packages/context/src/lib/share-map/shared/share-map.service.ts +++ b/packages/context/src/lib/share-map/shared/share-map.service.ts @@ -93,7 +93,7 @@ export class ShareMapService { )) { if (contextLayersID.indexOf(layer.id) === -1) { const wmsUrl = (layer.dataSource.options as any).url; - const addedLayer = (layer.dataSource.options as any).params.layers; + const addedLayer = (layer.dataSource.options as any).params.LAYERS; const addedLayerPosition = `${addedLayer}:igoz${layer.zIndex}`; if ( diff --git a/packages/geo/src/lib/catalog/shared/catalog.service.ts b/packages/geo/src/lib/catalog/shared/catalog.service.ts index 40c6112b0c..6908a37eac 100644 --- a/packages/geo/src/lib/catalog/shared/catalog.service.ts +++ b/packages/geo/src/lib/catalog/shared/catalog.service.ts @@ -9,7 +9,8 @@ import { CapabilitiesService, WMSDataSourceOptions, WMTSDataSourceOptions, - generateIdFromSourceOptions + generateIdFromSourceOptions, + WMSDataSourceOptionsParams } from '../../datasource'; import { LayerOptions, @@ -225,10 +226,11 @@ export class CatalogService { : undefined; const params = Object.assign({}, catalogQueryParams, { - layers: layer.Name, - feature_count: catalog.count, - version: catalog.version || '1.3.0' - }); + LAYERS: layer.Name, + FEATURE_COUNT: catalog.count, + VERSION: catalog.version || '1.3.0' + } as WMSDataSourceOptionsParams + ); const baseSourceOptions = { type: 'wms', url: catalog.url, diff --git a/packages/geo/src/lib/datasource/shared/capabilities.service.ts b/packages/geo/src/lib/datasource/shared/capabilities.service.ts index 4e3e2db4db..d30a3a1bb7 100644 --- a/packages/geo/src/lib/datasource/shared/capabilities.service.ts +++ b/packages/geo/src/lib/datasource/shared/capabilities.service.ts @@ -38,7 +38,7 @@ export class CapabilitiesService { baseOptions: WMSDataSourceOptions ): Observable { const url = baseOptions.url; - const version = (baseOptions.params as any).version; + const version = (baseOptions.params as any).VERSION; return this.getCapabilities('wms', url, version).pipe( map((capabilities: any) => { @@ -151,7 +151,7 @@ export class CapabilitiesService { baseOptions: WMSDataSourceOptions, capabilities: any ): WMSDataSourceOptions { - const layers = (baseOptions.params as any).layers; + const layers = (baseOptions.params as any).LAYERS; const layer = this.findDataSourceInCapabilities( capabilities.Capability.Layer, layers diff --git a/packages/geo/src/lib/datasource/shared/datasource.service.ts b/packages/geo/src/lib/datasource/shared/datasource.service.ts index 9198dcc8dd..561d50503d 100644 --- a/packages/geo/src/lib/datasource/shared/datasource.service.ts +++ b/packages/geo/src/lib/datasource/shared/datasource.service.ts @@ -31,6 +31,7 @@ import { ClusterDataSource, ClusterDataSourceOptions } from './datasources'; +import { ObjectUtils } from '@igo2/utils'; @Injectable({ providedIn: 'root' @@ -62,7 +63,9 @@ export class DataSourceService { dataSource = this.createWFSDataSource(context as WFSDataSourceOptions); break; case 'wms': - dataSource = this.createWMSDataSource(context as WMSDataSourceOptions); + const wmsContext = context as WMSDataSourceOptions + ObjectUtils.removeDuplicateCaseInsensitive(wmsContext.params) + dataSource = this.createWMSDataSource(wmsContext); break; case 'wmts': dataSource = this.createWMTSDataSource( diff --git a/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts b/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts index b4e1de43d8..133db67bf2 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.interface.ts @@ -23,9 +23,15 @@ export interface WMSDataSourceOptions extends DataSourceOptions { } export interface WMSDataSourceOptionsParams { - layers: string; - version?: string; - time?: string; + LAYERS: string; + VERSION?: string; + TIME?: string; + FEATURE_COUNT?: number; + FILTER?: string; + INFO_FORMAT?: string; + DPI?: number; + MAP_RESOLUTION?: number; + FORMAT_OPTIONS?: string; } export interface WMSLayerOptionsFromCapabilities { diff --git a/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.ts b/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.ts index 9d6ea3e5d2..4663be862d 100644 --- a/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.ts +++ b/packages/geo/src/lib/datasource/shared/datasources/wms-datasource.ts @@ -44,40 +44,9 @@ export class WMSDataSource extends DataSource { protected wfsService: WFSService ) { super(options); - // Important: To use wms versions smaller than 1.3.0, SRS - // needs to be supplied in the source "params" - - // We need to do this to override the default version - // of openlayers which is uppercase const sourceParams: any = options.params; - if (sourceParams && sourceParams.version) { - sourceParams.VERSION = sourceParams.version; - } - - if (sourceParams && sourceParams.VERSION) { - if (sourceParams.version !== '1.3.0') { - if (!sourceParams.SRS && !sourceParams.srs) { - throw new Error( - `You must set a SRS (or srs) param for your WMS - (layer = ` + - sourceParams.layers + - `) because your want to use a WMS version under 1.3.0 - Ex: "srs": "EPSG:3857" ` - ); - } - } - } - - if (sourceParams && sourceParams.styles) { - sourceParams.STYLES = sourceParams.styles; - delete sourceParams.styles; - } - - if (sourceParams && sourceParams.INFO_FORMAT) { - sourceParams.info_format = sourceParams.INFO_FORMAT; - } - const dpi = sourceParams.dpi || 96; + const dpi = sourceParams.DPI || 96; sourceParams.DPI = dpi; sourceParams.MAP_RESOLUTION = dpi; sourceParams.FORMAT_OPTIONS = 'dpi:' + dpi; @@ -130,14 +99,14 @@ export class WMSDataSource extends DataSource { } if ( - sourceParams.layers.split(',').length > 1 && + sourceParams.LAYERS.split(',').length > 1 && initOgcFilters && initOgcFilters.enabled ) { console.log('*******************************'); console.log( 'BE CAREFULL, YOUR WMS LAYERS (' + - sourceParams.layers + + sourceParams.LAYERS + ') MUST SHARE THE SAME FIELDS TO ALLOW ogcFilters TO WORK !! ' ); console.log('*******************************'); @@ -151,7 +120,7 @@ export class WMSDataSource extends DataSource { options, fieldNameGeometry ); - this.ol.updateParams({ filter: filterQueryString }); + sourceParams.FILTER = filterQueryString; } refresh() { @@ -178,8 +147,8 @@ export class WMSDataSource extends DataSource { const sourceParams = this.params; let layers = []; - if (sourceParams.layers !== undefined) { - layers = sourceParams.layers.split(','); + if (sourceParams.LAYERS !== undefined) { + layers = sourceParams.LAYERS.split(','); } const baseUrl = this.options.url.replace(/\?$/, ''); @@ -188,7 +157,7 @@ export class WMSDataSource extends DataSource { 'SERVICE=wms', 'FORMAT=image/png', 'SLD_VERSION=1.1.0', - `VERSION=${sourceParams.version || '1.3.0'}` + `VERSION=${sourceParams.VERSION || '1.3.0'}` ]; if (style !== undefined) { params.push(`STYLE=${style}`); diff --git a/packages/geo/src/lib/datasource/utils/id-generator.ts b/packages/geo/src/lib/datasource/utils/id-generator.ts index d9061d7a12..32bef5b01c 100644 --- a/packages/geo/src/lib/datasource/utils/id-generator.ts +++ b/packages/geo/src/lib/datasource/utils/id-generator.ts @@ -30,7 +30,7 @@ export function generateIdFromSourceOptions(options: DataSourceOptions): string * @returns A md5 hash of the the url and layers */ export function generateWMSIdFromSourceOptions(options: WMSDataSourceOptions) { - const layers = options.params.layers; + const layers = options.params.LAYERS; const url = options.url.charAt(0) === '/' ? window.location.origin + options.url : options.url; const chain = 'wms' + url + layers; return Md5.hashStr(chain) as string; diff --git a/packages/geo/src/lib/filter/shared/ogc-filter.service.ts b/packages/geo/src/lib/filter/shared/ogc-filter.service.ts index 595fd0d1b7..1575ef1bf4 100644 --- a/packages/geo/src/lib/filter/shared/ogc-filter.service.ts +++ b/packages/geo/src/lib/filter/shared/ogc-filter.service.ts @@ -9,8 +9,8 @@ export class OGCFilterService { constructor() {} public filterByOgc(wmsDatasource: WMSDataSource, filterString: string) { - const appliedFilter = new OgcFilterWriter().formatProcessedOgcFilter(filterString, wmsDatasource.options.params.layers); - wmsDatasource.ol.updateParams({ filter: appliedFilter }); + const appliedFilter = new OgcFilterWriter().formatProcessedOgcFilter(filterString, wmsDatasource.options.params.LAYERS); + wmsDatasource.ol.updateParams({ FILTER: appliedFilter }); } public setOgcWFSFiltersOptions(wfsDatasource: OgcFilterableDataSource) { diff --git a/packages/geo/src/lib/filter/shared/ogc-filter.ts b/packages/geo/src/lib/filter/shared/ogc-filter.ts index b01a78053f..d1f5f9dba3 100644 --- a/packages/geo/src/lib/filter/shared/ogc-filter.ts +++ b/packages/geo/src/lib/filter/shared/ogc-filter.ts @@ -494,7 +494,7 @@ export class OgcFilterWriter { let filterQueryString = ogcFilters.advancedOgcFilters ? filterQueryStringAdvancedFilters : filterQueryStringPushButton; if (options.type === 'wms') { - filterQueryString = this.formatProcessedOgcFilter(filterQueryString, (options as any).params.layers); + filterQueryString = this.formatProcessedOgcFilter(filterQueryString, (options as any).params.LAYERS); } if (options.type === 'wfs') { filterQueryString = this.formatProcessedOgcFilter(filterQueryString, (options as any).params.featureTypes); diff --git a/packages/geo/src/lib/filter/shared/time-filter.service.ts b/packages/geo/src/lib/filter/shared/time-filter.service.ts index 7f2cb41fee..78f813ece5 100644 --- a/packages/geo/src/lib/filter/shared/time-filter.service.ts +++ b/packages/geo/src/lib/filter/shared/time-filter.service.ts @@ -42,7 +42,7 @@ export class TimeFilterService { time = newdateform; } - const params = { time }; + const params = { TIME: time }; datasource.ol.updateParams(params); } @@ -78,7 +78,7 @@ export class TimeFilterService { time = year; } - const params = { time }; + const params = { TIME: time }; datasource.ol.updateParams(params); } diff --git a/packages/geo/src/lib/filter/time-filter-item/time-filter-item.component.html b/packages/geo/src/lib/filter/time-filter-item/time-filter-item.component.html index b5cfcdbf19..9b9e75affb 100644 --- a/packages/geo/src/lib/filter/time-filter-item/time-filter-item.component.html +++ b/packages/geo/src/lib/filter/time-filter-item/time-filter-item.component.html @@ -25,7 +25,7 @@

diff --git a/packages/geo/src/lib/layer/layer-legend/layer-legend.component.ts b/packages/geo/src/lib/layer/layer-legend/layer-legend.component.ts index 89c8864cd3..9a5f9506a3 100644 --- a/packages/geo/src/lib/layer/layer-legend/layer-legend.component.ts +++ b/packages/geo/src/lib/layer/layer-legend/layer-legend.component.ts @@ -121,9 +121,9 @@ export class LayerLegendComponent implements OnInit, OnDestroy { return of(layerLegend.title); } - const layers = layerOptions.params.layers.split(','); + const layers = layerOptions.params.LAYERS.split(','); const localLayerOptions = JSON.parse(JSON.stringify(layerOptions)); // to avoid to alter the original options. - localLayerOptions.params.layers = layers.find(layer => layer === layerLegend.title); + localLayerOptions.params.LAYERS = layers.find(layer => layer === layerLegend.title); return this.capabilitiesService .getWMSOptions(localLayerOptions) .pipe(map(wmsDataSourceOptions => { diff --git a/packages/geo/src/lib/query/shared/query.service.ts b/packages/geo/src/lib/query/shared/query.service.ts index 4e5348fa6a..19a8b70d75 100644 --- a/packages/geo/src/lib/query/shared/query.service.ts +++ b/packages/geo/src/lib/query/shared/query.service.ts @@ -498,10 +498,10 @@ export class QueryService { const WMSGetFeatureInfoOptions = { INFO_FORMAT: - wmsDatasource.params.info_format || + wmsDatasource.params.INFO_FORMAT || this.getMimeInfoFormat(datasource.options.queryFormat), - QUERY_LAYERS: wmsDatasource.params.layers, - FEATURE_COUNT: wmsDatasource.params.feature_count || '5' + QUERY_LAYERS: wmsDatasource.params.LAYERS, + FEATURE_COUNT: wmsDatasource.params.FEATURE_COUNT || '5' }; if (forceGML2) { @@ -516,14 +516,14 @@ export class QueryService { options.projection, WMSGetFeatureInfoOptions ); - const wmsVersion = - wmsDatasource.params.VERSION || - wmsDatasource.params.version || - '1.3.0'; - if (wmsVersion !== '1.3.0') { - url = url.replace('&I=', '&X='); - url = url.replace('&J=', '&Y='); - } + // const wmsVersion = + // wmsDatasource.params.VERSION || + // wmsDatasource.params.version || + // '1.3.0'; + // if (wmsVersion !== '1.3.0') { + // url = url.replace('&I=', '&X='); + // url = url.replace('&J=', '&Y='); + // } break; case CartoDataSource: const cartoDatasource = datasource as CartoDataSource; diff --git a/packages/geo/src/lib/search/shared/sources/ilayer.ts b/packages/geo/src/lib/search/shared/sources/ilayer.ts index 525d488129..738e547fc9 100644 --- a/packages/geo/src/lib/search/shared/sources/ilayer.ts +++ b/packages/geo/src/lib/search/shared/sources/ilayer.ts @@ -224,7 +224,7 @@ export class ILayerSearchSource extends SearchSource implements TextSearch { queryHtmlTarget: queryParams.queryHtmlTarget, queryable: data.properties.queryable, params: { - layers: data.properties.name + LAYERS: data.properties.name } }, title: data.properties.title, diff --git a/packages/utils/src/lib/object-utils.ts b/packages/utils/src/lib/object-utils.ts index 26b1088b40..ffb7d66064 100644 --- a/packages/utils/src/lib/object-utils.ts +++ b/packages/utils/src/lib/object-utils.ts @@ -68,6 +68,50 @@ export class ObjectUtils { return target; } + static removeDuplicateCaseInsensitive(obj: object) { + const summaryCapitalizeObject = {}; + const capitalizeObject = {}; + const upperCaseCount = []; + + for (const property in obj) { + const upperCaseProperty = property.toUpperCase() + if (!summaryCapitalizeObject.hasOwnProperty(upperCaseProperty)) { + summaryCapitalizeObject[upperCaseProperty] = [{ [property]: obj[property] }]; + } + else { + summaryCapitalizeObject[upperCaseProperty].push({ [property]: obj[property] }); + } + // counting the number of uppercase letters + upperCaseCount.push({ key: property, count: property.replace(/[^A-Z]/g, "").length }) + } + for (const capitalizedProperty in summaryCapitalizeObject) { + if (summaryCapitalizeObject.hasOwnProperty(capitalizedProperty)) { + const capitalizedPropertyObject = summaryCapitalizeObject[capitalizedProperty] + if (capitalizedPropertyObject.length === 1) { + // for single params (no duplicates) + const singlePossibility = capitalizedPropertyObject[0] + capitalizeObject[capitalizedProperty] = singlePossibility[Object.keys(singlePossibility)[0]] + } else if (capitalizedPropertyObject.length > 1) { + // defining the closest to lowercase property + const paramClosestToLowercase = upperCaseCount + .filter(f => f.key.toLowerCase() === capitalizedProperty.toLowerCase()) + .reduce((prev, current) => { + return (prev.y < current.y) ? prev : current + }); + capitalizeObject[paramClosestToLowercase.key.toUpperCase()] = obj[paramClosestToLowercase.key]; + } + + } + } + for (const property in obj) { + delete obj[property] + } + + for (const property in capitalizeObject) { + obj[property] = capitalizeObject[property] + } + } + static removeUndefined(obj: object): any { const output = {}; if (ObjectUtils.isObject(obj)) {