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

Ajustements for igo-api & Make features clickable #149

Merged
merged 5 commits into from
May 15, 2018
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
9 changes: 5 additions & 4 deletions src/lib/datasource/shared/datasources/wfs-datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { HttpClient } from '@angular/common/http';
import * as ol from 'openlayers';

import { uuid } from '../../../utils';
import {
import {
IgoOgcFilterObject, OgcFilter, WFSWriteGetFeatureOptions,
AnyBaseOgcFilterOptions, OgcFilterWriter
AnyBaseOgcFilterOptions, OgcFilterWriter
} from '../../../filter/shared';

import { DataSource } from './datasource';
Expand Down Expand Up @@ -32,12 +32,13 @@ export class WFSDataSource extends DataSource implements OgcFilterableDataSource
this.ogcFilterWriter = new OgcFilterWriter;

this.dataSourceService.checkWfsOptions(options);
if (options['sourceFields'] === undefined) {
if (options['sourceFields'] === undefined ||
Object.keys(options['sourceFields']).length === 0) {
options['sourceFields'] = []
this.dataSourceService.wfsGetCapabilities(options)
.map(wfsCapabilities => options['wfsCapabilities'] = {
'xml': wfsCapabilities.body,
'GetPropertyValue': /GetPropertyValue/gi.test(wfsCapabilities.body) ? true : false
'GetPropertyValue': /GetPropertyValue/gi.test(wfsCapabilities.body) ? true : false
})
.subscribe(val => options['sourceFields'] =
this.dataSourceService.defineFieldAndValuefromWFS(options));
Expand Down
13 changes: 7 additions & 6 deletions src/lib/datasource/shared/datasources/wms-datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Md5 } from 'ts-md5/dist/md5';
import { QueryFormat, QueryOptions } from '../../../query';

import { DataSource } from './datasource';
import {
import {
DataSourceLegendOptions, TimeFilterableDataSource,
QueryableDataSource, OgcFilterableDataSource
QueryableDataSource, OgcFilterableDataSource
} from './datasource.interface';
import { WMSDataSourceOptions } from './wms-datasource.interface';
import { OgcFilterWriter, IgoOgcFilterObject, OgcFiltersOptions } from '../../../filter/shared';
Expand Down Expand Up @@ -55,11 +55,12 @@ export class WMSDataSource extends DataSource implements
sourceParams.VERSION = sourceParams.version;
}

if (options['sourceFields'] === undefined) {
if (options['sourceFields'] === undefined ||
Object.keys(options['sourceFields']).length === 0) {
options['sourceFields'] = [{ 'name': '', 'alias': '' }]
}
// WMS With linked wfs
if (options.wfsSource) {
if (options.wfsSource && Object.keys(options.wfsSource).length > 0) {
options.wfsSource = this.dataSourceService.checkWfsOptions(options.wfsSource);
delete options.wfsSource.ogcFilters;
options['fieldNameGeometry'] = options.wfsSource['fieldNameGeometry'];
Expand All @@ -68,7 +69,7 @@ export class WMSDataSource extends DataSource implements
this.dataSourceService.wfsGetCapabilities(options)
.map(wfsCapabilities => options.wfsSource['wfsCapabilities'] = {
'xml': wfsCapabilities.body,
'GetPropertyValue': /GetPropertyValue/gi.test(wfsCapabilities.body) ? true : false
'GetPropertyValue': /GetPropertyValue/gi.test(wfsCapabilities.body) ? true : false
})
.subscribe(val => options['sourceFields'] =
this.dataSourceService.defineFieldAndValuefromWFS(options.wfsSource));
Expand All @@ -94,7 +95,7 @@ export class WMSDataSource extends DataSource implements
'srsname=' + options.wfsSource.srsname : 'srsname=EPSG:3857';
const baseWfsQuery = this.dataSourceService.buildBaseWfsUrl(options.wfsSource, 'GetFeature');
this.options.download = Object.assign({}, this.options.download, {
'dynamicUrl': `${baseWfsQuery}&${outputFormat}&${srsname}&${maxFeatures}`
'dynamicUrl': `${baseWfsQuery}&${outputFormat}&${srsname}&${maxFeatures}`
});
}

Expand Down
59 changes: 30 additions & 29 deletions src/lib/download/shared/download.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,36 @@ export class DownloadService {
const translate = this.languageService.translate;
const title = translate.instant('igo.download.title');
this.messageService.success(translate.instant('igo.download.start'), title);

if (
layer.dataSource.options.download['dynamicUrl'] &&
layer.dataSource.options.download.url === undefined) {
let wfsOptions;
if (layer.dataSource.options['wfsSource']) {
wfsOptions = layer.dataSource.options['wfsSource'];
} else {
wfsOptions = layer.dataSource.options;
}

const outputFormatDownload =
wfsOptions['outputFormatDownload'] === undefined ?
'outputformat=' + wfsOptions['outputFormat'] :
'outputformat=' + wfsOptions['outputFormatDownload'];

const baseurl = layer.dataSource.options.download['dynamicUrl']
.replace(/&?outputformat=[^&]*/gi, '')
.replace(/&?filter=[^&]*/gi, '')
.replace(/&?bbox=[^&]*/gi, '');

const rebuildFilter = this.ogcFilterWriter.buildFilter(
layer.dataSource.options['ogcFilters']['filters'],
layer.map.getExtent(),
new ol.proj.Projection({ code: layer.map.projection }),
wfsOptions['fieldNameGeometry']);
window.open(`${baseurl}&${rebuildFilter}&${outputFormatDownload}`, '_blank');
} else if (layer.dataSource.options.download) {
window.open(layer.dataSource.options.download.url, '_blank');
if (Object.keys(layer.dataSource.options.download).length > 0 ) {
if (
layer.dataSource.options.download['dynamicUrl'] &&
layer.dataSource.options.download.url === undefined) {
let wfsOptions;
if (Object.keys(layer.dataSource.options['wfsSource']).length > 0) {
wfsOptions = layer.dataSource.options['wfsSource'];
} else {
wfsOptions = layer.dataSource.options;
}

const outputFormatDownload =
wfsOptions['outputFormatDownload'] === undefined ?
'outputformat=' + wfsOptions['outputFormat'] :
'outputformat=' + wfsOptions['outputFormatDownload'];

const baseurl = layer.dataSource.options.download['dynamicUrl']
.replace(/&?outputformat=[^&]*/gi, '')
.replace(/&?filter=[^&]*/gi, '')
.replace(/&?bbox=[^&]*/gi, '');

const rebuildFilter = this.ogcFilterWriter.buildFilter(
layer.dataSource.options['ogcFilters']['filters'],
layer.map.getExtent(),
new ol.proj.Projection({ code: layer.map.projection }),
wfsOptions['fieldNameGeometry']);
window.open(`${baseurl}&${rebuildFilter}&${outputFormatDownload}`, '_blank');
} else if (layer.dataSource.options.download) {
window.open(layer.dataSource.options.download.url, '_blank');
}
}
}
}
4 changes: 3 additions & 1 deletion src/lib/feature/shared/feature.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ export class FeatureService {
featuresAreTheSame(feature1, feature2) {
if (feature1 === undefined || feature2 === undefined) { return false; }

return feature1.id === feature2.id && feature1.source === feature2.source;
return feature1.id === feature2.id
&& feature1.source === feature2.source
&& feature1.properties === feature2.properties;
}

private sortFeatures(feature1, feature2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
</div>

<div class="igo-col igo-col-90 igo-col-100-m" *ngIf="(currentFilter.operator === 'Intersects' || currentFilter.operator === 'Contains' || currentFilter.operator === 'Within')">
<button mat-button [disabled]="!currentFilter.active" *ngIf="currentFilter['wkt_geometry'] && currentFilter.igoSpatialSelector === 'fixedExtent'"
<button mat-button [disabled]="!currentFilter.active" *ngIf="currentFilter.igoSpatialSelector === 'fixedExtent'"
matSuffix mat-icon-button aria-label="Clear" (click)="changeGeometry(currentFilter,value)" tooltip-position="below" matTooltipShowDelay="500"
[matTooltip]="'igo.spatialSelector.btnSetExtent' | translate">
<mat-icon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ export class OgcFilterableItemComponent implements OnInit, OnDestroy {
{
'propertyName': firstFieldName,
'operator': 'PropertyIsEqualTo',
'active': status
'active': status,
'igoSpatialSelector': 'fixedExtent'
}, fieldNameGeometry, lastLevel, this.defaultLogicalParent));
this.datasource.options.ogcFilters.interfaceOgcFilters = arr;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/layer/layer-item/layer-item.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ <h4 matLine [matTooltip]="layer.title +' ('+ id +') '" matTooltipShowDelay="500"
</button>

<button
*ngIf="layer.dataSource.options.download "
*ngIf="layer.dataSource.options.download && (layer.dataSource.options.download.dynamicUrl || layer.dataSource.options.download.url) "
mat-icon-button
tooltip-position="below"
matTooltipShowDelay="500"
Expand Down
113 changes: 90 additions & 23 deletions src/lib/query/shared/query.directive.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { Directive, Self, Input, Output, EventEmitter,
OnDestroy, AfterViewInit } from '@angular/core';
import {
Directive,
Self,
Input,
Output,
EventEmitter,
OnDestroy,
AfterViewInit
} from '@angular/core';

import { Subscription } from 'rxjs/Subscription';
import { Observable } from 'rxjs/Observable';
import { forkJoin } from 'rxjs/observable/forkJoin';

import * as ol from 'openlayers';

import { LanguageService } from '../../core';
import { IgoMap } from '../../map/shared';
import { MapBrowserComponent } from '../../map/map-browser';
import { Layer } from '../../layer';
import { Feature } from '../../feature';

import { QueryService } from '../shared/query.service';


@Directive({
selector: '[igoQuery]'
})
export class QueryDirective implements AfterViewInit, OnDestroy {

private queryLayers: Layer[];
private queryLayers$$: Subscription;
private queries$$: Subscription[] = [];
Expand All @@ -27,23 +35,30 @@ export class QueryDirective implements AfterViewInit, OnDestroy {
}

@Input()
get waitForAllQueries(): boolean { return this._waitForAllQueries; }
get waitForAllQueries(): boolean {
return this._waitForAllQueries;
}
set waitForAllQueries(value: boolean) {
this._waitForAllQueries = value;
}
private _waitForAllQueries: boolean = false;

@Output() query = new EventEmitter<{
features: Feature[] | Feature[][],
event: ol.MapBrowserEvent
@Output()
query = new EventEmitter<{
features: Feature[] | Feature[][];
event: ol.MapBrowserEvent;
}>();

constructor(@Self() private component: MapBrowserComponent,
private queryService: QueryService) {}
constructor(
@Self() private component: MapBrowserComponent,
private queryService: QueryService,
private languageService: LanguageService
) {}

ngAfterViewInit() {
this.queryLayers$$ = this.component.map.layers$
.subscribe((layers: Layer[]) => this.handleLayersChange(layers));
this.queryLayers$$ = this.component.map.layers$.subscribe(
(layers: Layer[]) => this.handleLayersChange(layers)
);

this.map.ol.on('singleclick', this.handleMapClick, this);
}
Expand All @@ -68,25 +83,77 @@ export class QueryDirective implements AfterViewInit, OnDestroy {
private handleMapClick(event: ol.MapBrowserEvent) {
this.unsubscribeQueries();

const clickedFeatures: ol.Feature[] = [];
const format = new ol.format.GeoJSON();
const mapProjection = this.map.projection;
this.map.ol.forEachFeatureAtPixel(
event.pixel,
(feature: ol.Feature, layer: ol.layer.Layer) => {
if (layer.getZIndex() !== 999) {
let title;
if (layer.get('title') !== undefined) {
title = layer.get('title');
} else {
title = this.map.layers.filter(
f => f['zIndex'] === layer.getZIndex()
)[0].dataSource['options']['title'];
}
feature.set('clickedTitle', title);
clickedFeatures.push(feature);
}
}
);
const featuresGeoJSON = JSON.parse(
format.writeFeatures(clickedFeatures, {
dataProjection: 'EPSG:4326',
featureProjection: mapProjection
})
);
let i = 0;
let parsedClickedFeatures: Feature[] = [];
parsedClickedFeatures = featuresGeoJSON.features.map(f =>
Object.assign({}, f, {
source: this.languageService.translate.instant(
'igo.clickOnMap.clickedFeature'
),
id: f.properties.clickedTitle + ' ' + String(i++),
icon: 'mouse',
title: f.properties.clickedTitle
})
);
parsedClickedFeatures.forEach(element => {
delete element.properties['clickedTitle'];
});
const view = this.map.ol.getView();
const queries$ = this.queryService.query(this.queryLayers, {
coordinates: event.coordinate,
projection: this.map.projection,
resolution: view.getResolution()
});

if (this.waitForAllQueries) {
this.queries$$.push(
forkJoin(...queries$).subscribe(
(features: Feature[][]) => this.query.emit({features: features, event: event})
)
);
if (queries$.length === 0) {
this.query.emit({ features: parsedClickedFeatures, event: event });
} else {
this.queries$$ = queries$.map((query$: Observable<Feature[]>) => {
return query$.subscribe(
(features: Feature[]) => this.query.emit({features: features, event: event})
if (this.waitForAllQueries) {
this.queries$$.push(
forkJoin(...queries$).subscribe((features: Feature[][]) =>
this.query.emit({
features: features
.filter(f => f.length > 0)
.concat(parsedClickedFeatures),
event: event
})
)
);
});
} else {
this.queries$$ = queries$.map((query$: Observable<Feature[]>) => {
return query$.subscribe((features: Feature[]) =>
this.query.emit({
features: parsedClickedFeatures.concat(features),
event: event
})
);
});
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"catalogTool": {
"baseLayers": "Base Layers"
},
"clickOnMap": {
"clickedFeature": "Clicked Feature"
},
"confirmDialog": {
"cancelBtn": "Cancel",
"confirmBtn": "Confirm",
Expand Down
3 changes: 3 additions & 0 deletions src/locale/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"catalogTool": {
"baseLayers": "Fonds de carte"
},
"clickOnMap": {
"clickedFeature": "Entités cliquées"
},
"confirmDialog": {
"cancelBtn": "Annuler",
"confirmBtn": "Confirmer",
Expand Down