terriajs
Version:
Geospatial data visualization platform.
261 lines • 13.5 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 { action, computed, runInAction, makeObservable } from "mobx";
import URI from "urijs";
import isDefined from "../../../Core/isDefined";
import loadJson from "../../../Core/loadJson";
import runLater from "../../../Core/runLater";
import TerriaError, { networkRequestError } from "../../../Core/TerriaError";
import CatalogMemberMixin from "../../../ModelMixins/CatalogMemberMixin";
import GroupMixin from "../../../ModelMixins/GroupMixin";
import UrlMixin from "../../../ModelMixins/UrlMixin";
import { InfoSectionTraits, MetadataUrlTraits } from "../../../Traits/TraitsClasses/CatalogMemberTraits";
import SocrataCatalogGroupTraits, { FacetFilterTraits } from "../../../Traits/TraitsClasses/SocrataCatalogGroupTraits";
import CommonStrata from "../../Definition/CommonStrata";
import CreateModel from "../../Definition/CreateModel";
import createStratumInstance from "../../Definition/createStratumInstance";
import LoadableStratum from "../../Definition/LoadableStratum";
import StratumOrder from "../../Definition/StratumOrder";
import CatalogGroup from "../CatalogGroup";
import CsvCatalogItem from "../CatalogItems/CsvCatalogItem";
import GeoJsonCatalogItem from "../CatalogItems/GeoJsonCatalogItem";
import SocrataMapViewCatalogItem from "../CatalogItems/SocrataMapViewCatalogItem";
import proxyCatalogItemUrl from "../proxyCatalogItemUrl";
export class SocrataCatalogStratum extends LoadableStratum(SocrataCatalogGroupTraits) {
catalogGroup;
facets;
results;
static stratumName = "socrataCatalog";
static async load(catalogGroup) {
if (!catalogGroup.url)
throw "`url` must be set";
const filterQuery = Object.assign({}, catalogGroup.filterQuery, {
only: "dataset,map"
});
const domain = URI(catalogGroup.url).hostname();
let facets = [];
let results = [];
// If not facet filters have been set - get facets
if (!isDefined(catalogGroup.facetFilters) ||
catalogGroup.facetFilters.length === 0) {
const facetsToUse = catalogGroup.facetGroups;
const facetUri = URI(`${catalogGroup.url}/api/catalog/v1/domains/${domain}/facets`).addQuery(filterQuery);
const facetResponse = await loadJson(proxyCatalogItemUrl(catalogGroup, facetUri.toString()));
if (facetResponse.error) {
throw facetResponse.message ?? facetResponse.error;
}
facets = facetResponse;
if (!Array.isArray(facets))
throw `Could not fetch facets for domain ${domain}`;
facets = facets.filter((f) => facetsToUse.includes(f.facet));
if (facets.length === 0)
throw `Could not find any facets for domain ${domain}`;
}
// If facetFilter is set, use it to search for datasets (aka resources)
else {
const resultsUri = URI(`${catalogGroup.url}/api/catalog/v1?search_context=${domain}`).addQuery(filterQuery);
catalogGroup.facetFilters.forEach(({ name, value }) => name && isDefined(value) ? resultsUri.addQuery(name, value) : null);
const resultsResponse = await loadJson(proxyCatalogItemUrl(catalogGroup, resultsUri.toString()));
if (resultsResponse.error) {
throw resultsResponse.message ?? resultsResponse.error;
}
results = resultsResponse.results;
if (!Array.isArray(results) || results.length === 0)
throw `Could not find any results for domain ${domain} and facets: ${catalogGroup.facetFilters
.map(({ name, value }) => `${name} = ${value}`)
.join(", ")}`;
}
return new SocrataCatalogStratum(catalogGroup, facets, results);
}
duplicateLoadableStratum(model) {
return new SocrataCatalogStratum(model, this.facets, this.results);
}
constructor(catalogGroup, facets, results) {
super();
this.catalogGroup = catalogGroup;
this.facets = facets;
this.results = results;
makeObservable(this);
}
get members() {
// If we only have one facet, return it's children instead of a single facet group
if (this.facets.length === 1)
return this.facets[0].values.map((facetValue) => `${this.getFacetId(this.facets[0])}/${facetValue.value}`);
return [
...this.facets.map((f) => this.getFacetId(f)),
...this.results.map((r) => this.getResultId(r))
];
}
createMembers() {
this.facets.forEach((facet) => this.createGroupFromFacet(facet));
this.results.forEach((result) => this.createItemFromResult(result));
}
/** Turn facet into SocrataCatalogGroup */
createGroupFromFacet(facet) {
const facetGroupId = this.getFacetId(facet);
// Create group for Facet
let facetGroup = this.catalogGroup.terria.getModelById(CatalogGroup, facetGroupId);
if (facetGroup === undefined) {
facetGroup = new CatalogGroup(facetGroupId, this.catalogGroup.terria, undefined);
this.catalogGroup.terria.addModel(facetGroup);
}
// Replace the stratum inherited from the parent group.
facetGroup.strata.delete(CommonStrata.definition);
facetGroup.setTrait(CommonStrata.definition, "name", facet.facet);
// Create child groups for Facet values
facet.values.forEach((facetValue) => {
const facetValueId = `${facetGroupId}/${facetValue.value}`;
let facetValueGroup = this.catalogGroup.terria.getModelById(SocrataCatalogGroup, facetValueId);
if (facetValueGroup === undefined) {
facetValueGroup = new SocrataCatalogGroup(facetValueId, this.catalogGroup.terria, undefined);
this.catalogGroup.terria.addModel(facetValueGroup);
}
// Replace the stratum inherited from the parent group.
facetValueGroup.strata.delete(CommonStrata.definition);
facetValueGroup.setTrait(CommonStrata.definition, "name", `${facetValue.value}${facetValue.count ? ` (${facetValue.count ?? 0})` : ""}`);
facetValueGroup.setTrait(CommonStrata.definition, "url", this.catalogGroup.url);
facetValueGroup.setTrait(CommonStrata.definition, "facetFilters", [
createStratumInstance(FacetFilterTraits, {
name: facet.facet,
value: facetValue.value
})
]);
facetGroup.add(CommonStrata.definition, facetValueGroup);
});
}
/** Turn Result into catalog item
* If type is 'dataset':
* - If has geometery -> create GeoJSONCatalogItem
* - Otherwise -> create CsvCatalogItem
* If type is 'map' -> SocrataMapViewCatalogItem
* - Then the Socrata `views` API will be used to fetch data (this mimics how Socrata portal map visualisation works - it isn't an official API)
*/
createItemFromResult(result) {
const resultId = this.getResultId(result);
// Add share key for old ID which included parents ID
this.catalogGroup.terria.addShareKey(resultId, `${this.catalogGroup.uniqueId}/${result.resource.id}`);
let resultModel;
// If dataset resource
// - If has geometry - create GeoJSONCatalogItem
// - Otherwise - create CsvCatalogItem
if (result.resource.type === "dataset") {
if (result.resource.columns_datatype.find((type) => [
"Point",
"Line",
"Polygon",
"MultiLine",
"MultiPoint",
"MultiPolygon",
"Location"
].includes(type))) {
resultModel = this.catalogGroup.terria.getModelById(GeoJsonCatalogItem, resultId);
if (resultModel === undefined) {
resultModel = new GeoJsonCatalogItem(resultId, this.catalogGroup.terria, undefined);
this.catalogGroup.terria.addModel(resultModel);
}
// Replace the stratum inherited from the parent group.
resultModel.strata.delete(CommonStrata.definition);
resultModel.setTrait(CommonStrata.definition, "url", `${this.catalogGroup.url}/resource/${result.resource.id}.geojson?$limit=10000`);
}
else {
resultModel = this.catalogGroup.terria.getModelById(CsvCatalogItem, resultId);
if (resultModel === undefined) {
resultModel = new CsvCatalogItem(resultId, this.catalogGroup.terria, undefined);
this.catalogGroup.terria.addModel(resultModel);
}
// Replace the stratum inherited from the parent group.
resultModel.strata.delete(CommonStrata.definition);
resultModel.setTrait(CommonStrata.definition, "url", `${this.catalogGroup.url}/resource/${result.resource.id}.csv?$limit=10000`);
}
// If type is 'map' -> SocrataMapViewCatalogItem
}
else if (result.resource.type === "map") {
resultModel = this.catalogGroup.terria.getModelById(SocrataMapViewCatalogItem, resultId);
if (resultModel === undefined) {
resultModel = new SocrataMapViewCatalogItem(resultId, this.catalogGroup.terria, undefined);
this.catalogGroup.terria.addModel(resultModel);
}
// Replace the stratum inherited from the parent group.
resultModel.strata.delete(CommonStrata.definition);
resultModel.setTrait(CommonStrata.definition, "url", this.catalogGroup.url);
resultModel.setTrait(CommonStrata.definition, "resourceId", result.resource.id);
}
if (resultModel) {
resultModel.setTrait(CommonStrata.definition, "name", result.resource.name);
resultModel.setTrait(CommonStrata.definition, "description", result.resource.description);
resultModel.setTrait(CommonStrata.definition, "attribution", result.resource.attribution);
resultModel.setTrait(CommonStrata.definition, "info", [
createStratumInstance(InfoSectionTraits, {
name: i18next.t("models.socrataServer.licence"),
content: result.metadata.license
}),
createStratumInstance(InfoSectionTraits, {
name: i18next.t("models.socrataServer.tags"),
content: result.classification.tags.join(", ")
}),
createStratumInstance(InfoSectionTraits, {
name: i18next.t("models.socrataServer.attributes"),
content: result.resource.columns_name.join(", ")
})
]);
resultModel.setTrait(CommonStrata.definition, "metadataUrls", [
createStratumInstance(MetadataUrlTraits, {
title: i18next.t("models.openDataSoft.viewDatasetPage"),
url: result.permalink
})
]);
}
}
getFacetId(facet) {
return `${this.catalogGroup.uniqueId}/${facet.facet}`;
}
getResultId(result) {
// Use Socrata server hostname for datasets, so we don't create multiple across facets
return `${this.catalogGroup.url
? URI(this.catalogGroup.url ?? "").hostname()
: this.catalogGroup.uniqueId}/${result.resource.id}`;
}
}
__decorate([
computed
], SocrataCatalogStratum.prototype, "members", null);
__decorate([
action
], SocrataCatalogStratum.prototype, "createGroupFromFacet", null);
__decorate([
action
], SocrataCatalogStratum.prototype, "createItemFromResult", null);
StratumOrder.addLoadStratum(SocrataCatalogStratum.stratumName);
export default class SocrataCatalogGroup extends UrlMixin(GroupMixin(CatalogMemberMixin(CreateModel(SocrataCatalogGroupTraits)))) {
static type = "socrata-group";
get type() {
return SocrataCatalogGroup.type;
}
async forceLoadMetadata() {
try {
if (!this.strata.has(SocrataCatalogStratum.stratumName)) {
const stratum = await SocrataCatalogStratum.load(this);
runInAction(() => {
this.strata.set(SocrataCatalogStratum.stratumName, stratum);
});
}
}
catch (e) {
networkRequestError(TerriaError.from(e, {
message: { key: "models.socrataServer.retrieveErrorMessage" }
}));
}
}
async forceLoadMembers() {
const socrataServerStratum = this.strata.get(SocrataCatalogStratum.stratumName);
if (socrataServerStratum) {
await runLater(() => socrataServerStratum.createMembers());
}
}
}
//# sourceMappingURL=SocrataCatalogGroup.js.map