terriajs
Version:
Geospatial data visualization platform.
231 lines • 9.48 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 { featureCollection } from "@turf/helpers";
import i18next from "i18next";
import { computed, makeObservable, observable, runInAction } from "mobx";
import RequestErrorEvent from "terriajs-cesium/Source/Core/RequestErrorEvent";
import URI from "urijs";
import { toFeatureCollection } from "../../../Core/GeoJson";
import { isJsonNumber, isJsonObject, isJsonString, isJsonStringArray } from "../../../Core/Json";
import loadJson from "../../../Core/loadJson";
import Result from "../../../Core/Result";
import TerriaError, { networkRequestError } from "../../../Core/TerriaError";
import GeoJsonMixin from "../../../ModelMixins/GeojsonMixin";
import CartoMapV3CatalogItemTraits from "../../../Traits/TraitsClasses/CartoMapV3CatalogItemTraits";
import { GeoJsonTraits } from "../../../Traits/TraitsClasses/GeoJsonTraits";
import TableStyleTraits from "../../../Traits/TraitsClasses/Table/StyleTraits";
import CreateModel from "../../Definition/CreateModel";
import createStratumInstance from "../../Definition/createStratumInstance";
import LoadableStratum from "../../Definition/LoadableStratum";
import StratumOrder from "../../Definition/StratumOrder";
class CartoMapV3Stratum extends LoadableStratum(GeoJsonTraits) {
catalogItem;
static stratumName = "cartoMapV3Stratum";
constructor(catalogItem) {
super();
this.catalogItem = catalogItem;
makeObservable(this);
}
static load(item) {
return new CartoMapV3Stratum(item);
}
duplicateLoadableStratum(newModel) {
return new CartoMapV3Stratum(newModel);
}
// Hide "cartodb_id" style
get styles() {
return [
createStratumInstance(TableStyleTraits, {
id: "cartodb_id",
hidden: true
})
];
}
}
__decorate([
computed
], CartoMapV3Stratum.prototype, "styles", null);
StratumOrder.addLoadStratum(CartoMapV3Stratum.stratumName);
export default class CartoMapV3CatalogItem extends GeoJsonMixin(CreateModel(CartoMapV3CatalogItemTraits)) {
static type = "carto-v3";
geoJsonUrls = [];
// Commented out as we don't support tileJSON yet
// @observable
// mvtTileJsonUrls: string[] = [];
geoJsonSize;
constructor(id, terria, sourceReference) {
super(id, terria, sourceReference);
makeObservable(this);
if (this.strata.get(CartoMapV3Stratum.stratumName) === undefined) {
runInAction(() => {
this.strata.set(CartoMapV3Stratum.stratumName, new CartoMapV3Stratum(this));
});
}
}
get type() {
return CartoMapV3CatalogItem.type;
}
get typeName() {
return i18next.t("models.carto-v3.name");
}
async forceLoadMetadata() {
let response;
// If cartoQuery is defined - use Query API (https://api-docs.carto.com/#8f2020d9-edf3-4b50-ae58-9edeaa34613c)
if (this.cartoQuery) {
const url = new URI(this.baseUrl)
.path("")
.path(`v3/maps/${this.connectionName}/query`);
response = (await callCartoApi(url.toString(), this.accessToken, {
q: this.cartoQuery,
geo_column: this.cartoGeoColumn
}))?.throwIfError();
}
// If cartoTableName is defined - use Table API (https://api-docs.carto.com/#6a05d4d7-c6a1-4635-a8de-c91fa5e77fda)
else if (this.cartoTableName) {
const url = new URI(this.baseUrl)
.path("")
.path(`v3/maps/${this.connectionName}/table`)
.query({
name: this.cartoTableName,
columns: this.cartoColumns?.join(","),
geo_column: this.cartoGeoColumn
});
response = (await callCartoApi(url.toString(), this.accessToken))?.throwIfError();
}
else {
throw new TerriaError({
title: "Invalid Carto V3 config",
message: "`cartoQuery` or `cartoTableName` must be defined"
});
}
let geoJsonUrls = [];
// Commented out as we don't support tileJSON yet
// let mvtTileJsonUrls: string[] = [];
if (response &&
isJsonObject(response.geojson) &&
isJsonStringArray(response.geojson.url)) {
geoJsonUrls = response.geojson.url;
}
// Commented out as we don't support tileJSON yet
// if (
// response &&
// isJsonObject(response.tilejson) &&
// isJsonStringArray(response.tilejson.url)
// ) {
// mvtTileJsonUrls = response.tilejson.url;
// }
if (geoJsonUrls.length === 0 /*&& mvtTileJsonUrls.length === 0*/) {
throw TerriaError.from("No GeoJSON found.");
}
runInAction(() => {
if (response && isJsonNumber(response?.size)) {
this.geoJsonSize = response.size;
}
this.geoJsonUrls = geoJsonUrls;
// Commented out as we don't support tileJSON yet
// this.mvtTileJsonUrls = mvtTileJsonUrls;
});
}
async forceLoadGeojsonData() {
if (this.geoJsonUrls.length === 0)
throw TerriaError.from("No GeoJSON URL found for Carto table");
let jsonData = undefined;
// Download all geoJson files
const geojsonResponses = await Promise.all(this.geoJsonUrls.map(async (url) => {
jsonData = (await callCartoApi(url, this.accessToken))?.throwIfError();
if (jsonData === undefined) {
throw new TerriaError({
title: "Failed to load GeoJSON",
message: `Failed to load GeoJSON URL ${url}`
});
}
if (isJsonObject(jsonData, false) &&
typeof jsonData.type === "string") {
// Actual geojson
const fc = toFeatureCollection(jsonData);
if (fc)
return fc;
}
throw new TerriaError({
title: "Failed to load GeoJSON",
message: `Invalid response from GeoJSON URL ${url}:\n\n
\`\`\`
${JSON.stringify(jsonData)}
\`\`\``
});
}));
// NOTE: Commented out until we add tileJson/mvt support
// Download all tileJson files
// const tilejsonResponses = await Promise.all(
// this.mvtTileJsonUrls.map(async (url) => {
// jsonData = await loadJson(url, {
// Authorization: `Bearer ${this.accessToken}`
// });
// if (jsonData === undefined) {
// throw new TerriaError({
// title: "Failed to load GeoJSON",
// message: `Failed to load GeoJSON URL ${url}`
// });
// }
// if (isJsonObject(jsonData, false)) {
// return jsonData;
// }
// throw new TerriaError({
// title: "Failed to load GeoJSON",
// message: `Invalid response from GeoJSON URL ${url}:\n\n
// \`\`\`
// ${JSON.stringify(jsonData)}
// \`\`\``
// });
// })
// );
// Merge all geojson responses into a combined feature collection
const combinedFeatureCollection = featureCollection([]);
geojsonResponses.forEach((fc) => {
for (let i = 0; i < fc.features.length; i++) {
combinedFeatureCollection.features.push(fc.features[i]);
}
});
return combinedFeatureCollection;
}
}
__decorate([
observable
], CartoMapV3CatalogItem.prototype, "geoJsonUrls", void 0);
__decorate([
observable
], CartoMapV3CatalogItem.prototype, "geoJsonSize", void 0);
/** Wrap loadJson calls to handle Carto API error messages */
async function callCartoApi(url, auth, body) {
try {
return new Result(await loadJson(url, auth
? {
Authorization: `Bearer ${auth}`
}
: {}, body));
}
catch (e) {
if (e instanceof RequestErrorEvent) {
try {
const jsonResponse = isJsonString(e.response)
? JSON.parse(e.response)
: e.response;
if (isJsonObject(jsonResponse) && isJsonString(jsonResponse.error)) {
const cartoError = jsonResponse;
return Result.error(networkRequestError(TerriaError.from(e, {
title: "Error from Carto API",
message: cartoError.message ?? cartoError.error,
importance: -1
})));
}
}
catch { }
}
return Result.error(e);
}
}
//# sourceMappingURL=CartoMapV3CatalogItem.js.map