diff options
Diffstat (limited to 'app/models.js')
| -rw-r--r-- | app/models.js | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/app/models.js b/app/models.js index 2d85df5..9a0e2ca 100644 --- a/app/models.js +++ b/app/models.js @@ -1,4 +1,4 @@ -import { Bounds, Collection, Feature, LineString, Point, Polygon } from "geom"; +import { Bounds, Collection, Feature, Geometry, LineString, Point, Polygon } from "geom"; /** @typedef {{ lat: number, lng: number }} GeoPointJson */ /** @typedef {{ date: string, price: number }} PriceUpdateJson */ @@ -160,10 +160,12 @@ export class Geospatial { export class District { /** * @param {string} name + * @param {string} municipality * @param {Polygon} polygon */ - constructor(name, polygon) { + constructor(name, municipality, polygon) { this.name = name; + this.municipality = municipality; this.polygon = polygon; } @@ -172,14 +174,20 @@ export class District { * @returns {District} */ static fromFeature(feature) { - const name = "nimi_fi" in feature.properties ? feature.properties.nimi_fi : ""; + const name = + "nimi" in feature.properties && typeof feature.properties.nimi === "string" + ? feature.properties.nimi + : ""; + const municipality = + "kunta" in feature.properties && typeof feature.properties.kunta === "string" + ? feature.properties.kunta + : ""; const geometry = feature.geometry; - - if (name === null || name === undefined || !(geometry instanceof Polygon)) { - throw new Error("Invalid district feature data"); + if (!(geometry instanceof Polygon)) { + throw new Error(`Invalid district feature data ${geometry}`); } - return new District(name, geometry); + return new District(name, municipality, geometry); } /** @@ -487,53 +495,77 @@ export class Filters { } export class DataProvider { + static couchBaseUrl = "https://couch.tammi.cc"; + static wfsDbName = "helsinki_wfs"; + static housesDbName = "asunnot"; + + /** + * Fetch all features for a layer as a GeoJSON FeatureCollection + * @param {string} layerName + * @returns {Promise<Collection>} + */ + static async getCollectionFromCouch(layerName) { + // Use CouchDB view to get all features for the layer + const viewUrl = `${DataProvider.couchBaseUrl}/${DataProvider.wfsDbName}/_design/layers/_view/by_layer`; + const params = new URLSearchParams({ + include_docs: "true", + key: JSON.stringify(layerName), + }); + + const response = await fetch(`${viewUrl}?${params}`, { + headers: new Headers({ accept: "application/json" }), + mode: "cors", + }); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + + const result = await response.json(); + const features = result.rows + .map((row) => { + return row.doc.geometry && "type" in row.doc.geometry + ? new Feature(Geometry.fromGeoJSON(row.doc.geometry), row.doc.properties, row.doc._id) + : null; + }) + .filter((x) => x !== null); + return new Collection(features); + } + /** @returns {Promise<Collection>} */ static async getCoastline() { - return await DataProvider.getCollection("data/Seutukartta_meren_rantaviiva.json"); + return await DataProvider.getCollectionFromCouch("Seutukartta_meren_rantaviiva"); } /** @returns {Promise<Collection>} */ static async getMainRoads() { - return await DataProvider.getCollection("data/Seutukartta_liikenne_paatiet.json"); + return await DataProvider.getCollectionFromCouch("Seutukartta_liikenne_paatiet"); } /** @returns {Promise<District[]>} */ static async getDistricts() { - const collection = await DataProvider.getCollection("data/Seutukartta_aluejako_pienalue.json"); - return District.fromCollection(collection); + const collection = await DataProvider.getCollectionFromCouch("Seutukartta_aluejako_pienalue"); + const districts = District.fromCollection(collection); + return districts; } /** @returns {Promise<TrainStation[]>} */ static async getTrainStations() { - const collection = await DataProvider.getCollection( - "data/Seutukartta_liikenne_juna_asema.json", - ); + const collection = await DataProvider.getCollectionFromCouch("Seutukartta_liikenne_juna_asema"); return TrainStation.fromCollection(collection); } /** @returns {Promise<TrainTracks[]>} */ static async getTrainTracks() { - const collection = await DataProvider.getCollection("data/Seutukartta_liikenne_juna_rata.json"); + const collection = await DataProvider.getCollectionFromCouch("Seutukartta_liikenne_juna_rata"); return TrainTracks.fromCollection(collection); } - /** - * Load any GeoJSON file as Feature Collection - * @param {string} url - * @returns {Promise<Collection>} - */ - static async getCollection(url) { - const response = await fetch(url); - if (!response.ok) throw new Error(`Failed to load GeoJSON from ${url}: ${response.status}`); - const geojson = await response.json(); - return Collection.fromGeoJSON(geojson); - } - /** @returns {Promise<House[]>} */ static async getHouses() { try { const response = await fetch( - new URL("/asunnot/_all_docs?include_docs=true", "https://couch.tammi.cc"), + `${DataProvider.couchBaseUrl}/${DataProvider.housesDbName}/_all_docs?include_docs=true`, { headers: new Headers({ accept: "application/json" }), mode: "cors", |
