| /******************************************************************************** |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ********************************************************************************/ |
| |
| import {HttpClient} from "@angular/common/http"; |
| import {Inject, Injectable} from "@angular/core"; |
| import {Actions, createEffect, ofType} from "@ngrx/effects"; |
| import {Action} from "@ngrx/store"; |
| import {Observable, of} from "rxjs"; |
| import {ignoreElements, switchMap} from "rxjs/operators"; |
| import {APP_CONFIGURATION, GeoApiService, IAPIGeographicPositions, IAppConfiguration, WINDOW} from "../../../../core"; |
| import {ILeafletBounds} from "../../../../features/map"; |
| import {catchErrorTo, ignoreError} from "../../../../util/rxjs"; |
| import {EErrorCode, setErrorAction} from "../../../root"; |
| import {openGisAction} from "../../actions"; |
| |
| @Injectable({providedIn: "root"}) |
| export class OpenGisEffect { |
| |
| public open$ = createEffect(() => this.actions.pipe( |
| ofType(openGisAction), |
| switchMap((action) => this.openGis(action.bounds, action.user)) |
| )); |
| |
| /** |
| * URL Template to connect with GIS. |
| */ |
| public gisUrlTemplate = this.configuration.gis.urlTemplate; |
| |
| /** |
| * Expected projection format for the given Leaflet coordinates. |
| */ |
| public projectionFrom = this.configuration.gis.projectionFrom; |
| |
| /** |
| * Expected projection required for the GIS. |
| */ |
| public projectionTo = this.configuration.gis.projectionTo; |
| |
| /** |
| * Search parameter keys which are transformed in the GIS URL template. |
| */ |
| public coordinateKeys: Array<keyof ILeafletBounds> = ["center", "northEast", "northWest", "southEast", "southWest"]; |
| |
| public constructor( |
| public actions: Actions, |
| public geoApiService: GeoApiService, |
| public http: HttpClient, |
| @Inject(WINDOW) public window: Window, |
| @Inject(APP_CONFIGURATION) public configuration: IAppConfiguration |
| ) { |
| |
| } |
| |
| public openGis(bounds: ILeafletBounds, user: string): Observable<Action> { |
| return of(bounds).pipe( |
| switchMap(() => this.transform(this.extractGeographicPositionFromBounds(bounds))), |
| switchMap((geographicPositions) => { |
| const gisUrl = this.generateUrl(geographicPositions, user); |
| return this.http.get(gisUrl, {responseType: "text"}).pipe(ignoreError()); |
| }), |
| ignoreElements(), |
| catchErrorTo(setErrorAction({error: EErrorCode.UNEXPECTED})) |
| ); |
| } |
| |
| /** |
| * Extract all required geographic positions from the given Leaflet bounds. |
| */ |
| public extractGeographicPositionFromBounds(bounds: ILeafletBounds): IAPIGeographicPositions { |
| const geographicPositions: IAPIGeographicPositions = {}; |
| this.coordinateKeys.forEach((key) => { |
| const value = bounds[key]; |
| if (typeof value !== "object") { |
| return; |
| } |
| const tokens = [`{${key}X}`, `{${key}Y}`]; |
| if (tokens.some((token) => this.gisUrlTemplate.indexOf(token) > -1)) { |
| geographicPositions[key] = { |
| x: value.lng, |
| y: value.lat |
| }; |
| } |
| }); |
| return geographicPositions; |
| } |
| |
| /** |
| * Transforms a set of geographic positions via an API back end call. |
| */ |
| public transform(geographicPositions: IAPIGeographicPositions): Observable<IAPIGeographicPositions> { |
| return Object.keys(geographicPositions).length > 0 ? |
| this.geoApiService.transform(geographicPositions, this.projectionFrom, this.projectionTo) : |
| of(geographicPositions); |
| } |
| |
| /** |
| * Generate the URL to the GIS with a set of given geographic positions. |
| */ |
| public generateUrl(geographicPositions: IAPIGeographicPositions, user: string) { |
| let result = this.gisUrlTemplate; |
| Object.entries(geographicPositions).forEach(([key, value]) => { |
| result = result.replace(new RegExp(`{${key}X}`, "g"), "" + value.x); |
| result = result.replace(new RegExp(`{${key}Y}`, "g"), "" + value.y); |
| }); |
| result = result.replace(new RegExp(`{user}`, "g"), user); |
| return result; |
| } |
| |
| } |