Skip to content

Commit

Permalink
feat(ogcFilters): OgcFilters simplification, PushButtons and fields &…
Browse files Browse the repository at this point in the history
… operator control (#361)

* refactor(ogc-filter) Manage ogcfilterwriter usage.

* refactor(ogc-filter) interface modified

* refactor(wfs-datasource) simplification

* feat(wfs-datasource) only call needed fields

* refactor(wms-wfs-datasource)Filters to igoFilters

* refactor(*) geometry name for filters

* refactor(wms-wfs) Moving common utils/methods

* refactor(wms-wfs) using shared method and const.

* refactor(*) various minor fix

* feat(pushButtons)Adding pushbutton over ogcfilters

* refactor(*)  ogcfilters result from buildFilter

* wip(ogc-filters)

* feat (wfs,ogcfilters)Enable wfs to have pushbutton

* refactor(wfs) build url on empty pushbutton

* typo(togglebuttons)

* refactor(ogc-filter) switch to mdi SVG icon

* feat(ogc-filters) exclude field from sourceFields

* refactor(ogc-filter)remove geometry as overlay

* refactor(ogc-filter) Minor fixes

* feat(ogc-filter) Limit operators's list by type

* feat(demo) Add ogcfilters pushButtons example

* refactor(*) PR 631 simple reviews part 1

* refactor(ogc) place setter before getter

* refactor(ogc) remove mention to showfeatureonmap

* refactor(*) PR 631 simple reviews part 2

* refactor(wms & wfs & ogcfilters) defaut values

* refactor(wfs) removing mention to wfscapabilities

* refactor(wfs) default options for filters.

* refactor(wms) way to manage empty sourcefields & pushbuttons

* refactor(wfs-service) Simplification

* refactor(ogc-filter-toggle-button.component) Simplification by binding a boolean.

* refactor(ogc-filter) removing usage of feature extent
  • Loading branch information
pelord authored and mbarbeau committed Aug 7, 2019
1 parent 2e37a44 commit 1466996
Show file tree
Hide file tree
Showing 33 changed files with 806 additions and 792 deletions.
116 changes: 114 additions & 2 deletions demo/src/app/geo/ogc-filter/ogc-filter.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
WFSDataSourceOptions,
WFSDataSourceOptionsParams,
OgcFilterableDataSourceOptions,
AnyBaseOgcFilterOptions
AnyBaseOgcFilterOptions,
OgcFilterOperatorType
} from '@igo2/geo';

@Component({
Expand Down Expand Up @@ -66,12 +67,13 @@ export class AppOgcFilterComponent {
},
sourceFields: [
{ name: 'code_municipalite', alias: '# de la municipalitée' },
{ name: 'date_observation' },
{ name: 'date_observation', excludeFromOgcFilters: true },
{ name: 'urgence', values: ['immédiate', 'inconnue'] }
],
ogcFilters: {
enabled: true,
editable: true,
allowedOperatorsType: OgcFilterOperatorType.All,
filters: {
logical: 'Or',
filters: [
Expand Down Expand Up @@ -117,6 +119,116 @@ export class AppOgcFilterComponent {
extends WMSDataSourceOptions,
OgcFilterableDataSourceOptions {}

const filterableWMSwithPushButtons: WMSoptions = {
type: 'wms',
url: 'https://ws.mapserver.transports.gouv.qc.ca/swtq',
urlWfs: 'https://ws.mapserver.transports.gouv.qc.ca/swtq',
params: {
layers: 'radars_photos',
version: '1.3.0'
},
ogcFilters: {
enabled: true,
editable: true,
pushButtons: [{
logical: 'Or',
ogcPushButtons: [{
title: 'Radar photo fixe',
enabled: true,
color: '0,0,255',
tooltip: 'Here a tooltip explaning ...',
filters: {
operator: 'PropertyIsEqualTo',
propertyName: 'typeAppareil',
expression: 'Radar photo fixe'
}
},
{
title: 'Radar photo mobile',
enabled: false,
color: '255,200,0',
tooltip: 'Here a tooltip explaning ...',
filters: {
operator: 'PropertyIsEqualTo',
propertyName: 'typeAppareil',
expression: 'Radar photo mobile'
}
},
{
title: 'Radar photo fixe + feu rouge',
enabled: false,
color: '0,200,0',
tooltip: 'Here a tooltip explaning ...',
filters: {
operator: 'PropertyIsEqualTo',
propertyName: 'typeAppareil',
expression: 'Radar photo fixe et surveillance au feu rouge'
}
},
{
title: 'Radar feu rouge',
enabled: false,
color: '255,0,0',
tooltip: 'Here a tooltip explaning ...',
filters: {
operator: 'PropertyIsEqualTo',
propertyName: 'typeAppareil',
expression: 'Appareil de surveillance au feu rouge'
}
}
]
},
{
logical: 'Or',
vertical: true,
ogcPushButtons: [{
title: 'Montréal & Laval',
enabled: false,
tooltip: 'Here a tooltip explaning ...',
filters: {
logical: 'Or',
filters: [
{ operator: 'PropertyIsEqualTo', propertyName: 'region', expression: 'Montréal'},
{ operator: 'PropertyIsEqualTo', propertyName: 'region', expression: 'Laval'}]
}
},
{
title: 'Outside Montréal & Laval',
enabled: false,
tooltip: 'Here a tooltip explaning ...',
filters: {
logical: 'And',
filters: [
{ operator: 'PropertyIsNotEqualTo', propertyName: 'region', expression: 'Montréal'},
{ operator: 'PropertyIsNotEqualTo', propertyName: 'region', expression: 'Laval'}]
}
}
]
}
],
allowedOperatorsType: OgcFilterOperatorType.Basic,
},
paramsWFS: {
featureTypes: 'radars_photos',
fieldNameGeometry: 'geometry',
maxFeatures: 10000,
version: '1.1.0',
outputFormat: 'geojson',
outputFormatDownload: 'shp'
} as WFSDataSourceOptionsParams
};

this.dataSourceService
.createAsyncDataSource(filterableWMSwithPushButtons)
.subscribe(dataSource => {
this.map.addLayer(
this.layerService.createLayer({
title: 'Filterable WMS layers with predefined filters (buttons)',
source: dataSource
})
);
});

const datasourceWmsWith2Layers: WMSoptions = {
type: 'wms',
url: 'https://ws.mapserver.transports.gouv.qc.ca/swtq',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ export interface SourceFieldsOptionsParams {
name: any;
alias?: any;
values?: any;
excludeFromOgcFilters?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './wfs-datasource.interface';
export * from './wfs.service';
export * from './wms-datasource';
export * from './wms-datasource.interface';
export * from './wms-wfs.utils';
export * from './wmts-datasource';
export * from './wmts-datasource.interface';
export * from './carto-datasource';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,4 @@ export interface WFSDataSourceOptionsParams {
outputFormatDownload?: string;
srsName?: string;
xmlFilter?: string;
wfsCapabilities?: WFSCapabilitiesParams;
}

export interface WFSCapabilitiesParams {
xmlBody?: string;
GetPropertyValue?: boolean;
}
147 changes: 49 additions & 98 deletions packages/geo/src/lib/datasource/shared/datasources/wfs-datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,139 +2,90 @@ import olSourceVector from 'ol/source/Vector';
import * as OlLoadingStrategy from 'ol/loadingstrategy';
import * as OlFormat from 'ol/format';

import { uuid } from '@igo2/utils';

import { DataSource } from './datasource';
import { WFSDataSourceOptions } from './wfs-datasource.interface';
import { WFSService } from './wfs.service';

import { OgcFilterWriter } from '../../../filter/shared/ogc-filter';
import { OgcFilterableDataSourceOptions } from '../../../filter/shared/ogc-filter.interface';
import {
formatWFSQueryString,
defaultFieldNameGeometry,
gmlRegex,
jsonRegex,
checkWfsParams
} from './wms-wfs.utils';

export class WFSDataSource extends DataSource {
public ol: olSourceVector;
public ogcFilterWriter: OgcFilterWriter;

constructor(
public options: WFSDataSourceOptions,
protected wfsService: WFSService
) {
super(options);
this.options = this.wfsService.checkWfsOptions(options);
this.ogcFilterWriter = new OgcFilterWriter();
this.wfsService.getSourceFieldsFromWFS(this.options);
super(checkWfsParams(options, 'wfs'));

const ogcFilters = (this.options as OgcFilterableDataSourceOptions).ogcFilters;
const fieldNameGeometry = this.options.paramsWFS.fieldNameGeometry || defaultFieldNameGeometry;
const ogcFilterWriter = new OgcFilterWriter();
(this.options as OgcFilterableDataSourceOptions).ogcFilters = ogcFilterWriter.defineOgcFiltersDefaultOptions(ogcFilters, fieldNameGeometry);
if ((this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled) {
this.wfsService.getSourceFieldsFromWFS(this.options);
}
}

protected createOlSource(): olSourceVector {
// reassignation of params to paramsWFS and url to urlWFS to have a common interface with wms-wfs datasources
this.options.paramsWFS = this.options.params;
this.options.urlWfs = this.options.url;
// default wfs version
this.options.paramsWFS.version = this.options.paramsWFS.version
? this.options.paramsWFS.version
: '2.0.0';
const ogcFiltersDefaultValue = true; // default values for wfs.
(this.options as OgcFilterableDataSourceOptions).ogcFilters =
(this.options as OgcFilterableDataSourceOptions).ogcFilters === undefined
? {}
: (this.options as OgcFilterableDataSourceOptions).ogcFilters;
(this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled =
(this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled ===
undefined
? ogcFiltersDefaultValue
: (this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled;
(this.options as OgcFilterableDataSourceOptions).ogcFilters.editable =
(this.options as OgcFilterableDataSourceOptions).ogcFilters.editable ===
undefined
? ogcFiltersDefaultValue
: (this.options as OgcFilterableDataSourceOptions).ogcFilters.editable;

const baseWfsQuery = 'service=WFS&request=GetFeature';
// Mandatory
const url = this.options.urlWfs;
// Optional
const outputFormat = this.options.paramsWFS.outputFormat
? 'outputFormat=' + this.options.paramsWFS.outputFormat
: '';
const wfsVersion = this.options.paramsWFS.version
? 'version=' + this.options.paramsWFS.version
: 'version=' + '2.0.0';

let paramTypename = 'typename';
let paramMaxFeatures = 'maxFeatures';
if (
this.options.paramsWFS.version === '2.0.0' ||
!this.options.paramsWFS.version
) {
paramTypename = 'typenames';
paramMaxFeatures = 'count';
}

const featureTypes =
paramTypename + '=' + this.options.paramsWFS.featureTypes;

const maxFeatures = this.options.paramsWFS.maxFeatures
? paramMaxFeatures + '=' + this.options.paramsWFS.maxFeatures
: paramMaxFeatures + '=5000';

let downloadBaseUrl = `${url}?${baseWfsQuery}&${wfsVersion}&${featureTypes}&`;
downloadBaseUrl += `${outputFormat}&${maxFeatures}`;

this.options.download = Object.assign({}, this.options.download, {
dynamicUrl: downloadBaseUrl
});

return new olSourceVector({
format: this.getFormatFromOptions(),
overlaps: false,
url: (extent, resolution, proj) => {
const srsname = this.options.paramsWFS.srsName
? 'srsname=' + this.options.paramsWFS.srsName
: 'srsname=' + proj.getCode();

let filters;
if (
(this.options as OgcFilterableDataSourceOptions).ogcFilters &&
(this.options as OgcFilterableDataSourceOptions).ogcFilters.enabled
) {
filters = (this.options as OgcFilterableDataSourceOptions).ogcFilters.filters;
}
this.options.paramsWFS.xmlFilter = this.ogcFilterWriter.buildFilter(
filters,
return this.buildUrl(
extent,
proj,
this.options.paramsWFS.fieldNameGeometry
);

let baseUrl = `${url}?${baseWfsQuery}&${wfsVersion}&${featureTypes}&`;
baseUrl += `${outputFormat}&${srsname}&${maxFeatures}`;

const patternFilter = /(filter|bbox)=.*/gi;
if (patternFilter.test(this.options.paramsWFS.xmlFilter)) {
baseUrl += `&${this.options.paramsWFS.xmlFilter}`;
}

this.options.download = Object.assign({}, this.options.download, {
dynamicUrl: baseUrl
});

return baseUrl;
(this.options as OgcFilterableDataSourceOptions).ogcFilters);
},
strategy: OlLoadingStrategy.bbox
});
}

private buildUrl(extent, proj, ogcFilters): string {
const paramsWFS = this.options.paramsWFS;
const queryStringValues = formatWFSQueryString(this.options, undefined, proj.getCode());
let igoFilters;
if (ogcFilters && ogcFilters.enabled) {
igoFilters = ogcFilters.filters;
}
const ogcFilterWriter = new OgcFilterWriter();
const filterOrBox = ogcFilterWriter.buildFilter(igoFilters, extent, proj, ogcFilters.geometryName);
let filterOrPush = ogcFilterWriter.handleOgcFiltersAppliedValue(this.options, ogcFilters.geometryName);

let prefix = 'filter';
if (!filterOrPush) {
prefix = 'bbox';
filterOrPush = extent.join(',') + ',' + proj.getCode();
}

paramsWFS.xmlFilter = ogcFilters.advancedOgcFilters ? filterOrBox : `${prefix}=${filterOrPush}`;
let baseUrl = queryStringValues.find(f => f.name === 'getfeature').value;
const patternFilter = /(filter|bbox)=.*/gi;
baseUrl = patternFilter.test(paramsWFS.xmlFilter) ? `${baseUrl}&${paramsWFS.xmlFilter}` : baseUrl;
this.options.download = Object.assign({}, this.options.download, { dynamicUrl: baseUrl });
return baseUrl.replace(/&&/g, '&');
}

private getFormatFromOptions() {
let olFormatCls;

const outputFormat = this.options.paramsWFS.outputFormat.toLowerCase();
const patternGml3 = new RegExp('.*?gml.*?');
const patternGeojson = new RegExp('.*?json.*?');
let outputFormat;
if (this.options.paramsWFS.outputFormat) {
outputFormat = this.options.paramsWFS.outputFormat.toLowerCase();
}

if (patternGeojson.test(outputFormat)) {
if (jsonRegex.test(outputFormat)) {
olFormatCls = OlFormat.GeoJSON;
}
if (patternGml3.test(outputFormat)) {
if (gmlRegex.test(outputFormat) || !outputFormat) {
olFormatCls = OlFormat.WFS;
}

Expand Down
Loading

0 comments on commit 1466996

Please sign in to comment.