terriajs
Version:
Geospatial data visualization platform.
217 lines • 9.71 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import i18next from "i18next";
import { makeObservable, override, runInAction } from "mobx";
import Rectangle from "terriajs-cesium/Source/Core/Rectangle";
import Resource from "terriajs-cesium/Source/Core/Resource";
import { Category, SearchAction } from "../../Core/AnalyticEvents/analyticEvents";
import isDefined from "../../Core/isDefined";
import loadJson from "../../Core/loadJson";
import { applyTranslationIfExists } from "../../Language/languageHelpers";
import prettifyCoordinates from "../../Map/Vector/prettifyCoordinates";
import LocationSearchProviderMixin, { getMapCenter } from "../../ModelMixins/SearchProviders/LocationSearchProviderMixin";
import MapboxSearchProviderTraits from "../../Traits/SearchProviders/MapboxSearchProviderTraits";
import CommonStrata from "../Definition/CommonStrata";
import CreateModel from "../Definition/CreateModel";
import SearchResult from "./SearchResult";
var MapboxGeocodeDirection;
(function (MapboxGeocodeDirection) {
MapboxGeocodeDirection["Forward"] = "forward";
MapboxGeocodeDirection["Reverse"] = "reverse";
})(MapboxGeocodeDirection || (MapboxGeocodeDirection = {}));
export default class MapboxSearchProvider extends LocationSearchProviderMixin(CreateModel(MapboxSearchProviderTraits)) {
static type = "mapbox-search-provider";
get type() {
return MapboxSearchProvider.type;
}
constructor(uniqueId, terria) {
super(uniqueId, terria);
makeObservable(this);
}
showWarning() {
if (!this.accessToken || this.accessToken === "") {
console.warn(`The ${applyTranslationIfExists(this.name, i18next)}(${this.type}) geocoder will always return no results because a Mapbox token has not been provided. Please get a token from mapbox.com and add it to parameters.mapboxSearchProviderAccessToken in config.json.`);
}
}
logEvent(searchText) {
this.terria.analytics?.logEvent(Category.search, SearchAction.mapbox, searchText);
}
doSearch(searchText, searchResults) {
searchResults.results.length = 0;
searchResults.message = undefined;
const isCoordinate = RegExp(/^-?([0-9]{1,2}|1[0-7][0-9]|180)(\.[0-9]{1,17})$/);
const isCSCoordinatePair = RegExp(/([+-]?\d+\.?\d+)\s*,\s*([+-]?\d+\.?\d+)/);
let searchDirection = isCSCoordinatePair.test(searchText)
? MapboxGeocodeDirection.Reverse
: MapboxGeocodeDirection.Forward;
let queryParams = {
access_token: this.accessToken,
autocomplete: this.partialMatch,
language: this.language
};
//check if geocoder should be reverse and set up.
if (searchDirection === MapboxGeocodeDirection.Reverse) {
let lonLat = searchText.split(/\s+/).join("").split(",");
if (lonLat.length === 2 &&
isCoordinate.test(lonLat[0]) &&
isCoordinate.test(lonLat[1])) {
// need to reverse the coord order if true.
if (this.latLonSearchOrder) {
lonLat = lonLat.reverse();
}
const [lonf, latf] = lonLat.map(parseFloat);
if (this.showCoordinatesInReverseGeocodeResult) {
const prettyCoords = prettifyCoordinates(lonf, latf);
searchResults.results.push(new SearchResult({
name: `${prettyCoords.latitude}, ${prettyCoords.longitude}`,
clickAction: createZoomToFunction(this, {
geometry: {
coordinates: [lonf, latf]
},
properties: {}
}),
location: {
longitude: lonf,
latitude: latf
}
}));
}
queryParams = {
...queryParams,
...{
longitude: lonLat[0],
latitude: lonLat[1],
limit: 1 //limit for reverse geocoder is per type
}
};
}
else {
//if lonLat fails to parse, then assume is forward geocode
searchDirection = MapboxGeocodeDirection.Forward;
}
}
const searchQuery = new Resource({
url: new URL(searchDirection, this.url).toString(),
queryParameters: queryParams
});
if (searchDirection === MapboxGeocodeDirection.Forward) {
searchQuery.appendQueryParameters({
q: searchText,
limit: this.limit
});
}
if (searchDirection === MapboxGeocodeDirection.Forward && this.mapCenter) {
const mapCenter = getMapCenter(this.terria);
searchQuery.appendQueryParameters({
proximity: `${mapCenter.longitude}, ${mapCenter.latitude}`
});
}
if (searchDirection === MapboxGeocodeDirection.Forward &&
this.terria.searchBarModel.boundingBoxLimit) {
const bbox = this.terria.searchBarModel.boundingBoxLimit;
if (isDefined(bbox.west) &&
isDefined(bbox.north) &&
isDefined(bbox.east) &&
isDefined(bbox.south)) {
searchQuery.appendQueryParameters({
bbox: [bbox.west, bbox.north, bbox.east, bbox.south].join(",")
});
}
}
if (this.country) {
searchQuery.appendQueryParameters({
country: this.country
});
}
if (this.types) {
searchQuery.appendQueryParameters({
types: this.types
});
}
if (this.worldview) {
searchQuery.appendQueryParameters({
worldview: this.worldview
});
}
const promise = loadJson(searchQuery);
return promise
.then((result) => {
if (searchResults.isCanceled) {
// A new search has superseded this one, so ignore the result.
return;
}
if ((result.features.length === 0 &&
searchDirection === MapboxGeocodeDirection.Forward) ||
//in the case where coordinate result is true, list is
//not empty.
(result.features.length === 0 &&
searchDirection === MapboxGeocodeDirection.Reverse &&
this.showCoordinatesInReverseGeocodeResult === false)) {
searchResults.message = {
content: "translate#viewModels.searchNoLocations"
};
return;
}
const locations = result.features
.filter((feat) => feat.properties && feat.geometry && feat.properties.full_address)
.map((feat) => {
return new SearchResult({
name: feat.properties.full_address,
clickAction: createZoomToFunction(this, feat),
location: {
latitude: feat.geometry.coordinates[1],
longitude: feat.geometry.coordinates[0]
}
});
});
runInAction(() => {
searchResults.results.push(...locations);
});
if (searchResults.results.length === 0) {
searchResults.message = {
content: "translate#viewModels.searchNoLocations"
};
}
const attribution = result.attribution;
if (attribution) {
runInAction(() => {
this.setTrait(CommonStrata.underride, "attributions", [
attribution
]);
});
}
})
.catch(() => {
if (searchResults.isCanceled) {
// A new search has superseded this one, so ignore the result.
return;
}
searchResults.message = {
content: "translate#viewModels.searchErrorOccurred"
};
});
}
}
__decorate([
override
], MapboxSearchProvider.prototype, "showWarning", null);
function createZoomToFunction(model, resource) {
// mapbox doesn't return a bbox for street names etc, so we
// need to create it ourselves.
const [west, north, east, south] = resource.properties.bbox ?? [
resource.geometry.coordinates[0] - 0.01,
resource.geometry.coordinates[1] - 0.01,
resource.geometry.coordinates[0] + 0.01,
resource.geometry.coordinates[1] + 0.01
];
const rectangle = Rectangle.fromDegrees(west, south, east, north);
return function () {
const terria = model.terria;
terria.currentViewer.zoomTo(rectangle, model.flightDurationSeconds);
};
}
//# sourceMappingURL=MapboxSearchProvider.js.map