diff --git a/demo/src/app/common/action/action.component.html b/demo/src/app/common/action/action.component.html index 839105e2bc..abbfcf3733 100644 --- a/demo/src/app/common/action/action.component.html +++ b/demo/src/app/common/action/action.component.html @@ -14,5 +14,21 @@ +

+ + + Common + Action context-menu +
+
+ + + + + diff --git a/demo/src/app/common/action/action.component.ts b/demo/src/app/common/action/action.component.ts index c807a1d60a..e383d6b922 100644 --- a/demo/src/app/common/action/action.component.ts +++ b/demo/src/app/common/action/action.component.ts @@ -1,11 +1,8 @@ -import { - Component, - OnInit, - OnDestroy -} from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Media, MediaOrientation, MediaService } from '@igo2/core'; import { ActionStore, ActionbarMode } from '@igo2/common'; +import { Overlay } from '@angular/cdk/overlay'; @Component({ selector: 'app-action', @@ -13,7 +10,6 @@ import { ActionStore, ActionbarMode } from '@igo2/common'; styleUrls: ['./action.component.scss'] }) export class AppActionComponent implements OnInit, OnDestroy { - public store = new ActionStore([]); private added = false; @@ -27,7 +23,7 @@ export class AppActionComponent implements OnInit, OnDestroy { return ActionbarMode.Overlay; } - constructor(private mediaService: MediaService) {} + constructor(private mediaService: MediaService, public overlay: Overlay) {} ngOnInit() { const added = () => this.added === true; @@ -42,7 +38,7 @@ export class AppActionComponent implements OnInit, OnDestroy { alert('Add!'); this.added = true; this.store.updateActionsAvailability(); - }, + } }, { id: 'edit', @@ -74,5 +70,4 @@ export class AppActionComponent implements OnInit, OnDestroy { ngOnDestroy() { this.store.destroy(); } - } diff --git a/demo/src/app/common/action/action.module.ts b/demo/src/app/common/action/action.module.ts index 38a43e53d2..d9dea28299 100644 --- a/demo/src/app/common/action/action.module.ts +++ b/demo/src/app/common/action/action.module.ts @@ -1,20 +1,19 @@ import { NgModule } from '@angular/core'; import { MatButtonModule, MatCardModule } from '@angular/material'; -import { IgoActionModule } from '@igo2/common'; +import { IgoActionModule, IgoContextMenuModule } from '@igo2/common'; import { AppActionComponent } from './action.component'; import { AppActionRoutingModule } from './action-routing.module'; @NgModule({ - declarations: [ - AppActionComponent - ], + declarations: [AppActionComponent], imports: [ AppActionRoutingModule, MatButtonModule, MatCardModule, - IgoActionModule + IgoActionModule, + IgoContextMenuModule ], exports: [AppActionComponent] }) diff --git a/demo/src/app/geo/search/search.component.html b/demo/src/app/geo/search/search.component.html index 1ad9e77ee7..8609f08078 100644 --- a/demo/src/app/geo/search/search.component.html +++ b/demo/src/app/geo/search/search.component.html @@ -10,7 +10,7 @@
- + @@ -26,6 +26,20 @@ (resultFocus)="onResultFocus($event)" (resultSelect)="onResultSelect($event)"> + + + + + + + + + + diff --git a/demo/src/app/geo/search/search.component.ts b/demo/src/app/geo/search/search.component.ts index f4f306e627..3d986834ae 100644 --- a/demo/src/app/geo/search/search.component.ts +++ b/demo/src/app/geo/search/search.component.ts @@ -1,27 +1,41 @@ -import { Component } from '@angular/core'; +import { + Component, + ElementRef, + OnDestroy, + OnInit, + ViewChild +} from '@angular/core'; +import * as proj from 'ol/proj'; import { LanguageService } from '@igo2/core'; -import { EntityStore } from '@igo2/common'; +import { EntityStore, ActionStore } from '@igo2/common'; import { FEATURE, Feature, FeatureMotion, + GoogleLinks, IgoMap, LayerService, + MapService, Layer, LAYER, LayerOptions, Research, - SearchResult + SearchResult, + SearchService } from '@igo2/geo'; +import { SearchState } from '@igo2/integration'; + @Component({ selector: 'app-search', templateUrl: './search.component.html', styleUrls: ['./search.component.scss'] }) -export class AppSearchComponent { - map = new IgoMap({ +export class AppSearchComponent implements OnInit, OnDestroy { + public store = new ActionStore([]); + + public map = new IgoMap({ overlay: true, controls: { attribution: { @@ -30,19 +44,33 @@ export class AppSearchComponent { } }); - view = { + public view = { center: [-73, 47.2], zoom: 7 }; - searchStore: EntityStore = new EntityStore([]); + public osmLayer: Layer; + + @ViewChild('mapBrowser', { read: ElementRef }) mapBrowser: ElementRef; + + public lonlat; + public mapProjection: string; + + get searchStore(): EntityStore { + return this.searchState.store; + } - osmLayer: Layer; + selectedFeature: Feature; constructor( private languageService: LanguageService, - private layerService: LayerService + private mapService: MapService, + private layerService: LayerService, + private searchState: SearchState, + private searchService: SearchService ) { + this.mapService.setMap(this.map); + this.layerService .createAsyncLayer({ title: 'OSM', @@ -59,6 +87,7 @@ export class AppSearchComponent { onSearchTermChange(term?: string) { if (term === undefined || term === '') { this.searchStore.clear(); + this.selectedFeature = undefined; } } @@ -98,14 +127,14 @@ export class AppSearchComponent { if (result.meta.dataType !== FEATURE) { return undefined; } - const feature = (result as SearchResult).data; + this.selectedFeature = (result as SearchResult).data; // Somethimes features have no geometry. It happens with some GetFeatureInfo - if (feature.geometry === undefined) { + if (this.selectedFeature.geometry === undefined) { return; } - this.map.overlay.setFeatures([feature], FeatureMotion.Default); + this.map.overlay.setFeatures([this.selectedFeature], FeatureMotion.Default); } /** @@ -125,4 +154,77 @@ export class AppSearchComponent { .createAsyncLayer(layerOptions) .subscribe(layer => this.map.addLayer(layer)); } + + ngOnInit() { + this.store.load([ + { + id: 'coordinates', + title: 'coordinates', + handler: this.onSearchCoordinate.bind(this) + }, + { + id: 'googleMaps', + title: 'googleMap', + handler: this.onOpenGoogleMaps.bind(this), + args: ['1'] + }, + { + id: 'googleStreetView', + title: 'googleStreetView', + handler: this.onOpenGoogleStreetView.bind(this) + } + ]); + } + + ngOnDestroy() { + this.store.destroy(); + } + + onContextMenuOpen(event: { x: number; y: number }) { + const position = this.mapPosition(event); + const coord = this.mapService.getMap().ol.getCoordinateFromPixel(position); + this.mapProjection = this.mapService.getMap().projection; + this.lonlat = proj.transform(coord, this.mapProjection, 'EPSG:4326'); + } + + mapPosition(event: { x: number; y: number }) { + const contextmenuPoint = event; + contextmenuPoint.y = + contextmenuPoint.y - + this.mapBrowser.nativeElement.getBoundingClientRect().top + + window.scrollY; + contextmenuPoint.x = + contextmenuPoint.x - + this.mapBrowser.nativeElement.getBoundingClientRect().left + + window.scrollX; + const position = [contextmenuPoint.x, contextmenuPoint.y]; + return position; + } + + onSearchCoordinate() { + this.searchStore.clear(); + const results = this.searchService.reverseSearch(this.lonlat); + + for (const i in results) { + if (results.length > 0) { + results[i].request.subscribe((_results: SearchResult[]) => { + this.onSearch({ research: results[i], results: _results }); + /*if (_results[i].source.options.title === 'Coordinates') { + this.onResultSelect(_results[0]); + }*/ + console.log(_results[0]); + }); + } + } + } + + onOpenGoogleMaps() { + window.open(GoogleLinks.getGoogleMapsLink(this.lonlat[0], this.lonlat[1])); + } + + onOpenGoogleStreetView() { + window.open( + GoogleLinks.getGoogleStreetViewLink(this.lonlat[0], this.lonlat[1]) + ); + } } diff --git a/demo/src/app/geo/search/search.module.ts b/demo/src/app/geo/search/search.module.ts index f0107e758d..9db87568ee 100644 --- a/demo/src/app/geo/search/search.module.ts +++ b/demo/src/app/geo/search/search.module.ts @@ -8,13 +8,20 @@ import { MatTooltipModule } from '@angular/material'; -import { IgoPanelModule } from '@igo2/common'; import { + IgoPanelModule, + IgoActionbarModule, + IgoContextMenuModule +} from '@igo2/common'; +import { + IgoFeatureModule, IgoMapModule, IgoSearchModule, provideIChercheSearchSource, provideILayerSearchSource, - provideNominatimSearchSource + provideNominatimSearchSource, + provideIChercheReverseSearchSource, + provideCoordinatesReverseSearchSource } from '@igo2/geo'; import { IgoAppSearchModule } from '@igo2/integration'; @@ -34,13 +41,18 @@ import { AppSearchRoutingModule } from './search-routing.module'; IgoPanelModule, IgoMapModule, IgoSearchModule.forRoot(), - IgoAppSearchModule + IgoAppSearchModule, + IgoActionbarModule, + IgoContextMenuModule, + IgoFeatureModule ], exports: [AppSearchComponent], providers: [ + provideCoordinatesReverseSearchSource(), provideIChercheSearchSource(), provideILayerSearchSource(), - provideNominatimSearchSource() + provideNominatimSearchSource(), + provideIChercheReverseSearchSource() ] }) export class AppSearchModule {} diff --git a/demo/src/environments/environment.ts b/demo/src/environments/environment.ts index daa0527193..e03083f3a5 100644 --- a/demo/src/environments/environment.ts +++ b/demo/src/environments/environment.ts @@ -55,7 +55,7 @@ export const environment: Environment = { }, searchSources: { nominatim: { - enabled: true + enabled: false }, reseautq: { searchUrl: 'https://ws.mapserver.transports.gouv.qc.ca/swtq', @@ -78,11 +78,14 @@ export const environment: Environment = { distance : 0.5 }, icherche: { - searchUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/geocode', - locateUrl: 'https://geoegl.msp.gouv.qc.ca/icherche/xy', + searchUrl: '/icherche/geocode', zoomMaxOnSelect: 10, enabled: true }, + icherchereverse: { + searchUrl: '/icherche/xy', + enabled: true + }, datasource: { searchUrl: 'https://geoegl.msp.gouv.qc.ca/igo2/api/layers/search', enabled: false diff --git a/demo/src/locale/en.json b/demo/src/locale/en.json index 5dcff725c2..c7f8a0ff3d 100644 --- a/demo/src/locale/en.json +++ b/demo/src/locale/en.json @@ -1,5 +1,8 @@ { "welcome": "Welcome to {{title}}", "About": "About", - "Salutation": "Salutation" + "Salutation": "Salutation", + "coordinates": "Show coordinates,", + "googleMap": "Show in Google maps", + "googleStreetView": "Show in Google Street view" } diff --git a/demo/src/locale/fr.json b/demo/src/locale/fr.json index 60372768d3..087dc8bb4f 100644 --- a/demo/src/locale/fr.json +++ b/demo/src/locale/fr.json @@ -1,5 +1,8 @@ { "welcome": "Bienvenue à {{title}}", "About": "À propos", - "Salutation": "Salutation" + "Salutation": "Salutation", + "coordinates": "Afficher les coordonnées", + "googleMap": "Afficher sur Google maps", + "googleStreetView": "Afficher sur Google Street view" } diff --git a/package-lock.json b/package-lock.json index 87bb0bc496..0c00fa340c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8806,14 +8806,34 @@ "dev": true }, "geojson-rbush": { +<<<<<<< HEAD +<<<<<<< HEAD "version": "3.1.2", "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.1.2.tgz", "integrity": "sha512-grkfdg3HIeTjwTfiJe5FT8+fGU3fABCc+vRJDBwdQz9kkLF0Sbif2gs2JUzjewwgmnvLGy9fInySDeADoNuk7w==", +======= + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.1.1.tgz", + "integrity": "sha512-Bl6U75yDCsERl2P6PiBkvxIoXsSv5SEEiDJy+a7JarcEe17jEm8zamAmi82KLRcIlcuRZxgeVCl1xw5UkxOREw==", +>>>>>>> get mapbrowser coordinate +======= + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.1.2.tgz", + "integrity": "sha512-grkfdg3HIeTjwTfiJe5FT8+fGU3fABCc+vRJDBwdQz9kkLF0Sbif2gs2JUzjewwgmnvLGy9fInySDeADoNuk7w==", +>>>>>>> fix(*): fix import/export and lint "requires": { "@turf/bbox": "*", "@turf/helpers": "6.x", "@turf/meta": "6.x", +<<<<<<< HEAD +<<<<<<< HEAD "rbush": "^2.0.0" +======= + "rbush": "*" +>>>>>>> get mapbrowser coordinate +======= + "rbush": "^2.0.0" +>>>>>>> fix(*): fix import/export and lint } }, "get-caller-file": { @@ -11345,7 +11365,6 @@ "integrity": "sha512-J9X76xnncMw+wIqb15HeWfPMqPwYxSpPY8yWPJ7rAZN/ZDzFkjCSZObryCyUe8zbrVRNiuCnIeQteCzMn7GnWw==", "requires": { "canvg": "1.5.3", - "file-saver": "github:eligrey/FileSaver.js#e865e37af9f9947ddcced76b549e27dc45c1cb2e", "html2canvas": "1.0.0-alpha.12", "omggif": "1.0.7", "promise-polyfill": "8.1.0", @@ -11354,7 +11373,7 @@ "dependencies": { "file-saver": { "version": "github:eligrey/FileSaver.js#e865e37af9f9947ddcced76b549e27dc45c1cb2e", - "from": "github:eligrey/FileSaver.js#1.3.8" + "from": "github:eligrey/FileSaver.js#e865e37af9f9947ddcced76b549e27dc45c1cb2e" } } }, @@ -13598,6 +13617,124 @@ "lru-cache": "^4.1.3", "make-fetch-happen": "^4.0.1", "npm-package-arg": "^6.1.0" +<<<<<<< HEAD +======= + }, + "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" +>>>>>>> Added an action bar mode for context menu + } + }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } } }, "npm-run-all": { @@ -15850,6 +15987,18 @@ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, +<<<<<<< HEAD +======= + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, +>>>>>>> Added an action bar mode for context menu "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -20225,9 +20374,15 @@ "dev": true }, "write-file-atomic": { +<<<<<<< HEAD "version": "2.4.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", +======= + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=", +>>>>>>> Added an action bar mode for context menu "dev": true, "requires": { "graceful-fs": "^4.1.11", diff --git a/packages/common/src/lib/action/actionbar/actionbar-item.component.html b/packages/common/src/lib/action/actionbar/actionbar-item.component.html index fdd2341d92..fa553d0abe 100644 --- a/packages/common/src/lib/action/actionbar/actionbar-item.component.html +++ b/packages/common/src/lib/action/actionbar/actionbar-item.component.html @@ -4,7 +4,7 @@ [matTooltip]="tooltip | translate" [ngClass]="{'igo-actionbar-item-disabled': disabled}" (click)="onClick()"> -