diff --git a/Docs/ServerConfig/cache/Caddyfile b/Docs/ServerConfig/cache/Caddyfile index b818fae82..e54c42d99 100644 --- a/Docs/ServerConfig/cache/Caddyfile +++ b/Docs/ServerConfig/cache/Caddyfile @@ -1,14 +1,4 @@ cache.mapcomplete.org { - reverse_proxy /summary/* { - to http://127.0.0.1:2345 - } - - reverse_proxy /extractgraph { - to http://127.0.0.1:2346 - } - - reverse_proxy /* { - to http://127.0.0.1:7800 - } - + reverse_proxy /summary/* 127.0.0.1:2345 + reverse_proxy /* 127.0.0.1:7800 } diff --git a/Docs/ServerConfig/cache/cache.txt b/Docs/ServerConfig/cache/cache.md similarity index 89% rename from Docs/ServerConfig/cache/cache.txt rename to Docs/ServerConfig/cache/cache.md index ddda8f29a..df11db46d 100644 --- a/Docs/ServerConfig/cache/cache.txt +++ b/Docs/ServerConfig/cache/cache.md @@ -10,6 +10,6 @@ https://dynamicdns.park-your-domain.com/update?host=cache&domain=mapcomplete.org ## Setup -See SettingUpPSQL.md +See [SettingUpPSQL.md](../SettingUpPSQL.md) diff --git a/Docs/ServerConfig/hetzner/Caddyfile b/Docs/ServerConfig/hetzner/Caddyfile index 7888c8f7b..b0beb86e1 100644 --- a/Docs/ServerConfig/hetzner/Caddyfile +++ b/Docs/ServerConfig/hetzner/Caddyfile @@ -3,7 +3,6 @@ hosted.mapcomplete.org { file_server header { +Permissions-Policy "interest-cohort=()" - +Report-To `\{"group":"csp-endpoint", "max_age": 86400,"endpoints": [\{"url": "https://report.mapcomplete.org/csp"}], "include_subdomains": true}` } } @@ -11,12 +10,11 @@ countrycoder.mapcomplete.org { root * tiles/ file_server header { - +Permissions-Policy "interest-cohort=()" - +Access-Control-Allow-Origin https://hosted.mapcomplete.org https://dev.mapcomplete.org https://mapcomplete.org - } + +Permissions-Policy "interest-cohort=()" + +Access-Control-Allow-Origin https://hosted.mapcomplete.org https://dev.mapcomplete.org https://mapcomplete.org + } } - report.mapcomplete.org { reverse_proxy { to http://127.0.0.1:2600 @@ -30,25 +28,7 @@ studio.mapcomplete.org { } lod.mapcomplete.org { - reverse_proxy /extractgraph { - to http://127.0.0.1:2346 - } -} - -proxy.mapcomplete.org { - reverse_proxy { - to http://127.0.0.1:1237 - } -} - -bounce.mapcomplete.org { - reverse_proxy { - to http://127.0.0.1:1236 - } -} - -cache.mapcomplete.org { - reverse_proxy /summary/* { - to http://127.0.0.1:2345 - } + reverse_proxy /extractgraph { + to http://127.0.0.1:2346 + } } diff --git a/Docs/SettingUpPSQL.md b/Docs/SettingUpPSQL.md index 7b19dccad..b615129bb 100644 --- a/Docs/SettingUpPSQL.md +++ b/Docs/SettingUpPSQL.md @@ -59,11 +59,13 @@ HP ProLiant DL360 G7 (1U): 2Rx4 DDR3-memory (PC3) ## Deploying a tile server -pg_tileserv kan hier gedownload worden: https://github.com/CrunchyData/pg_tileserv +pg_tileserv can be downloaded here: https://github.com/CrunchyData/pg_tileserv + +In the directory where it is downloaded (e.g. `~/data`), run ```` export DATABASE_URL=postgresql://user:password@localhost:5444/osm-poi -nohup ./pg_tileserv & +nohup ./pg_tileserv > pg_tileserv.log & ```` Tiles are available at: @@ -74,6 +76,10 @@ map.addSource("drinking_water", { }) ```` +# Starting the summary server + +`npm run summary-server` in the git repo + # Rebooting: -> Restart the docker container diff --git a/assets/layers/icons/icons.json b/assets/layers/icons/icons.json index 8b290c036..11553fe28 100644 --- a/assets/layers/icons/icons.json +++ b/assets/layers/icons/icons.json @@ -201,7 +201,7 @@ }, { "#": "ignore-image-in-then", - "if": "context:website~*", + "if": "contact:website~*", "then": "website" } ] diff --git a/assets/layers/playground_equipment/playground_equipment.json b/assets/layers/playground_equipment/playground_equipment.json index 67b06456c..da7ad93eb 100644 --- a/assets/layers/playground_equipment/playground_equipment.json +++ b/assets/layers/playground_equipment/playground_equipment.json @@ -364,5 +364,8 @@ } } ], - "allowMove": true + "allowMove": true, + "deletion": { + "neededChangesets": 0 + } } diff --git a/assets/layers/shops/shops.json b/assets/layers/shops/shops.json index a621c2bb1..892004764 100644 --- a/assets/layers/shops/shops.json +++ b/assets/layers/shops/shops.json @@ -426,6 +426,36 @@ } ] }, + { + "id": "copyshop-binding", + "condition": { + "or": [ + "shop~.*copyshop.*", + "shop~.*stationery.*", + "service:print=yes" + ] + }, + "question": { + "en": "Does this shop offer a binding service?" + }, + "questionHint": { + "en": "Does this shop bind a bundle of pages into a small book, e.g. with a comb, a spiral, wire or by gluing?" + }, + "mappings": [ + { + "if": "service:binding=yes", + "then": { + "en": "This shop binds papers into a booklet" + } + }, + { + "if": "service:binding=no", + "then": { + "en": "This shop does bind books" + } + } + ] + }, { "id": "key_cutter", "question": { diff --git a/package-lock.json b/package-lock.json index ada348b2b..ffad3919f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mapcomplete", - "version": "0.42.6", + "version": "0.43.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mapcomplete", - "version": "0.42.6", + "version": "0.43.1", "license": "GPL-3.0-or-later", "dependencies": { "@comunica/core": "^3.0.1", @@ -7682,10 +7682,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "license": "MIT", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -9756,8 +9757,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "license": "MIT", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -10770,6 +10772,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "dev": true, @@ -17710,7 +17720,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dependencies": { "is-number": "^7.0.0" }, @@ -17718,13 +17729,6 @@ "node": ">=8.0" } }, - "node_modules/to-regex-range/node_modules/is-number": { - "version": "7.0.0", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/topojson-client": { "version": "3.1.0", "license": "ISC", @@ -24931,9 +24935,11 @@ } }, "braces": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "brorand": { @@ -26246,7 +26252,9 @@ } }, "fill-range": { - "version": "7.0.1", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } @@ -26866,6 +26874,11 @@ "define-properties": "^1.1.3" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, "is-path-inside": { "version": "3.0.3", "dev": true @@ -31326,13 +31339,10 @@ }, "to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { "is-number": "^7.0.0" - }, - "dependencies": { - "is-number": { - "version": "7.0.0" - } } }, "topojson-client": { diff --git a/package.json b/package.json index b5020986c..9ef566671 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,8 @@ "url": "https://www.openstreetmap.org" }, "mvt_layer_server": "https://cache.mapcomplete.org/public.{type}_{layer}/{z}/{x}/{y}.pbf", + "#summary_server": "Should be the endpoint; appending status.json should work", + "summary_server": "https://cache.mapcomplete.org/", "disabled:oauth_credentials": { "##": "DEV", "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/", diff --git a/scripts/GenerateSeries.ts b/scripts/GenerateSeries.ts index 12727606b..a505c84a0 100644 --- a/scripts/GenerateSeries.ts +++ b/scripts/GenerateSeries.ts @@ -5,6 +5,7 @@ import Script from "./Script" import { GeoOperations } from "../src/Logic/GeoOperations" import { Feature, Polygon } from "geojson" import { Tiles } from "../src/Models/TileRange" +import { BBox } from "../src/Logic/BBox" class StatsDownloader { private readonly urlTemplate = @@ -123,7 +124,7 @@ class StatsDownloader { Referer: "https://osmcha.org/?filters=%7B%22date__gte%22%3A%5B%7B%22label%22%3A%222020-07-05%22%2C%22value%22%3A%222020-07-05%22%7D%5D%2C%22editor%22%3A%5B%7B%22label%22%3A%22mapcomplete%22%2C%22value%22%3A%22mapcomplete%22%7D%5D%7D", "Content-Type": "application/json", - Authorization: "Token 6e422e2afedb79ef66573982012000281f03dc91", + Authorization: "Token 9cc11ad2868778272eadbb1a423ebb507184bc04", DNT: "1", Connection: "keep-alive", TE: "Trailers", @@ -135,7 +136,7 @@ class StatsDownloader { ScriptUtils.erasableLog( `Downloading stats for ${year}-${month}-${day}, page ${page} ${url}` ) - const result = await Utils.downloadJson(url, headers) + const result = await Utils.downloadJson<{features: [], next: string}>(url, headers) page++ allFeatures.push(...result.features) if (result.features === undefined) { @@ -201,11 +202,11 @@ class GenerateSeries extends Script { const targetDir = args[0] ?? "../../git/MapComplete-data" await this.downloadStatistics(targetDir + "/changeset-metadata") - await this.generateCenterPoints( + this.generateCenterPoints( targetDir + "/changeset-metadata", targetDir + "/mapcomplete-changes/", { - zoomlevel: 8, + zoomlevel: 8 } ) } @@ -248,10 +249,8 @@ class GenerateSeries extends Script { const allPaths = readdirSync(sourceDir).filter( (p) => p.startsWith("stats.") && p.endsWith(".json") ) - let allFeatures: ChangeSetData[] = [].concat( - ...allPaths.map( + let allFeatures: ChangeSetData[] = allPaths.flatMap( (path) => JSON.parse(readFileSync(sourceDir + "/" + path, "utf-8")).features - ) ) allFeatures = allFeatures.filter( (f) => @@ -270,8 +269,24 @@ class GenerateSeries extends Script { f.properties.editor.toLowerCase().startsWith("mapcomplete")) ) - allFeatures = allFeatures.filter((f) => f.properties.metadata?.theme !== "EMPTY CS") - const centerpoints = allFeatures.map((f) => GeoOperations.centerpoint(f)) + allFeatures = allFeatures.filter((f) => f.properties.metadata?.theme !== "EMPTY CS" && f.geometry.coordinates.length > 0) + const centerpointsAll = allFeatures.map((f) => { + const centerpoint = GeoOperations.centerpoint(f) + const c = centerpoint.geometry.coordinates + // OsmCha doesn't adhere to the Geojson standard and uses `lat` `lon` as coordinates instead of `lon`, `lat` + centerpoint.geometry.coordinates = [c[1], c[0]] + return centerpoint + }) + const centerpoints = centerpointsAll.filter(p => { + const bbox= BBox.get(p) + if(bbox.minLat === -90 && bbox.maxLat === -90){ + // Due to some bug somewhere, those invalid bboxes might appear if the latitude is < 90 + // This crashes the 'spreadIntoBBoxes + // As workaround, we simply ignore them for now + return false + } + return true + }) console.log("Found", centerpoints.length, " changesets in total") const perBbox = GeoOperations.spreadIntoBboxes(centerpoints, options.zoomlevel) diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index f7e2aca01..709ffa0fc 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -392,6 +392,8 @@ class GenerateLayouts extends Script { } } + hosts.add("http://www.schema.org") // Schema.org is _not_ encrypted and thus needs an exception + if (hosts.has("*")) { throw "* is not allowed as connect-src" } diff --git a/scripts/velopark/compare.ts b/scripts/velopark/compare.ts index 947e9b580..cea83eb63 100644 --- a/scripts/velopark/compare.ts +++ b/scripts/velopark/compare.ts @@ -65,6 +65,10 @@ class Compare extends Script { async main(args: string[]): Promise { let [velopark, osm, key] = args + if(velopark === undefined || osm === undefined){ + console.log("Needed argument: velopark.geojson osm.geojson [key]\nThe key is optional and will be `ref:velopark` by default\nUse overpass to get a geojson with ref:velopark") + return + } key ??= "ref:velopark" const veloparkData: FeatureCollection = JSON.parse(fs.readFileSync(velopark, "utf-8")) const osmData: FeatureCollection = JSON.parse(fs.readFileSync(osm, "utf-8")) @@ -82,6 +86,7 @@ class Compare extends Script { console.error("No velopark entry found for", veloId) continue } + console.log("Veloparking is", veloparking) diffs.push(this.compare(veloId, parking, veloparking)) } console.log( diff --git a/scripts/velopark/diffToCsv.ts b/scripts/velopark/diffToCsv.ts new file mode 100644 index 000000000..d0031ae8f --- /dev/null +++ b/scripts/velopark/diffToCsv.ts @@ -0,0 +1,63 @@ +import Script from "../Script" +import { readFileSync, writeFileSync } from "fs" +import { OsmId } from "../../src/Models/OsmFeature" +import { Utils } from "../../src/Utils" + +interface DiffItem { + /** + * Velopark-id + */ + "ref": string, + "osmid": OsmId, + "distance": number, + "diffs": { + key: string, + /** + * The value in OpenStreetMap + * Might be undefined if OSM doesn't have an appropriate value + */ + osm?: string, + velopark: string | number } [] +} + +export class DiffToCsv extends Script { + constructor() { + super("Converts a 'report.diff' to a CSV file for people who prefer LibreOffice Calc (or other Spreadsheet Software)") + } + + async main(args: string[]): Promise { + const file = args[0] ?? "report_diff.json" + const json = <{diffs:DiffItem[], distanceBinds: number[]}> JSON.parse(readFileSync(file, "utf8")) + const diffs = json.diffs + const allKeys = Utils.Dedup(diffs.flatMap(item => item.diffs.map(d => d.key))) + allKeys.sort() + + const header = ["osm_id","velopark_id", "distance",...allKeys.flatMap(k => ["osm:"+k, "velopark:"+k])] + const lines = [header] + for (const diffItem of diffs) { + const line = [] + lines.push(line) + line.push(diffItem.osmid) + line.push(diffItem.ref) + line.push(diffItem.distance) + + const d = diffItem.diffs + for (const k of allKeys) { + const found = d.find(i => i.key === k) + if(!found){ + line.push("","") + continue + } + line.push(found.osm, found.velopark) + } + + } + const path = "report_diff.csv" + writeFileSync(path, + lines.map(l => l.join(",")).join("\n") + ,"utf8") + console.log("Written", path) + } +} + +new DiffToCsv().run() diff --git a/scripts/velopark/veloParkToGeojson.ts b/scripts/velopark/veloParkToGeojson.ts index acbc6d0eb..839155079 100644 --- a/scripts/velopark/veloParkToGeojson.ts +++ b/scripts/velopark/veloParkToGeojson.ts @@ -23,9 +23,9 @@ class VeloParkToGeojson extends Script { JSON.stringify( extension === ".geojson" ? { - type: "FeatureCollection", - features, - } + type: "FeatureCollection", + features + } : features, null, " " @@ -34,34 +34,14 @@ class VeloParkToGeojson extends Script { console.log("Written", file, "(" + features.length, " features)") } - public static sumProperties(data: object, addTo: Record>) { - delete data["@context"] - for (const k in data) { - if (k === "@graph") { - for (const obj of data["@graph"]) { - this.sumProperties(obj, addTo) - } - continue - } - if (addTo[k] === undefined) { - addTo[k] = new Set() - } - addTo[k].add(data[k]) - } - } - private static async downloadDataFor( - url: string, - allProperties: Record> + url: string ): Promise { - const cachePath = "/home/pietervdvn/data/velopark_cache/" + url.replace(/[/:.]/g, "_") - if (!fs.existsSync(cachePath)) { - const data = await Utils.downloadJson(url) - fs.writeFileSync(cachePath, JSON.stringify(data), "utf-8") - console.log("Saved a backup to", cachePath) + const cachePath = "/home/pietervdvn/data/velopark_cache_refined/" + url.replace(/[/:.]/g, "_") + if (fs.existsSync(cachePath)) { + return JSON.parse(fs.readFileSync(cachePath, "utf8")) } - - this.sumProperties(JSON.parse(fs.readFileSync(cachePath, "utf-8")), allProperties) + console.log("Fetching data for", url) const linkedData = await LinkedDataLoader.fetchVeloparkEntry(url) const allVelopark: Feature[] = [] @@ -70,9 +50,12 @@ class VeloParkToGeojson extends Script { if (Object.keys(sectionInfo).length === 0) { console.warn("No result for", url) } - sectionInfo["ref:velopark"] = [sectionId ?? url] + if(!sectionInfo.geometry?.coordinates){ + throw "Invalid properties!" + } allVelopark.push(sectionInfo) } + fs.writeFileSync(cachePath, JSON.stringify(allVelopark), "utf8") return allVelopark } @@ -85,20 +68,24 @@ class VeloParkToGeojson extends Script { let failed = 0 console.log("Got", allVeloparkRaw.length, "items") const allVelopark: Feature[] = [] - const allProperties = {} - for (let i = 0; i < allVeloparkRaw.length; i++) { - const f = allVeloparkRaw[i] - console.log("Handling", i + "/" + allVeloparkRaw.length) - try { - const sections: Feature[] = await VeloParkToGeojson.downloadDataFor( - f.url, - allProperties - ) - allVelopark.push(...sections) - } catch (e) { - console.error("Loading ", f.url, " failed due to", e) - failed++ - } + const batchSize = 50 + for (let i = 0; i < allVeloparkRaw.length; i += batchSize) { + await Promise.all(Utils.TimesT(batchSize, j => j).map( + async j => { + const f = allVeloparkRaw[i + j] + if (!f) { + return + } + try { + const sections: Feature[] = await VeloParkToGeojson.downloadDataFor(f.url) + allVelopark.push(...sections) + } catch (e) { + console.error("Loading ", f.url, " failed due to", e) + failed++ + } + } + )) + } console.log( "Fetching data done, got ", @@ -107,11 +94,6 @@ class VeloParkToGeojson extends Script { failed ) VeloParkToGeojson.exportGeojsonTo("velopark_all", allVelopark) - for (const k in allProperties) { - allProperties[k] = Array.from(allProperties[k]) - } - - fs.writeFileSync("all_properties_mashup.json", JSON.stringify(allProperties, null, " ")) return allVelopark } @@ -158,7 +140,7 @@ class VeloParkToGeojson extends Script { private static async createDiff(allVelopark: Feature[]) { const bboxBelgium = new BBox([ [2.51357303225, 49.5294835476], - [6.15665815596, 51.4750237087], + [6.15665815596, 51.4750237087] ]) const alreadyLinkedQuery = new Overpass( @@ -201,7 +183,7 @@ class VeloParkToGeojson extends Script { VeloParkToGeojson.exportExtraAmenities(allVelopark) await VeloParkToGeojson.createDiff(allVelopark) console.log( - "Use vite-node script/velopark/compare to compare the results and generate a diff file" + "Use vite-node scripts/velopark/compare.ts to compare the results and generate a diff file" ) } } diff --git a/src/Logic/BBox.ts b/src/Logic/BBox.ts index fd5ef5e5b..b54928418 100644 --- a/src/Logic/BBox.ts +++ b/src/Logic/BBox.ts @@ -16,6 +16,18 @@ export class BBox { /*** * Coordinates should be [[lon, lat],[lon, lat]] * @param coordinates + * + * const bb = new BBox([[5,6]]) + * bb.minLat // => 6 + * bb.minLon // => 5 + * bb.maxLat // => 6 + * bb.maxLon // => 5 + * + * const bb = new BBox([[-100,-100]]) + * bb.minLat // => -90 + * bb.minLon // => -100 + * bb.maxLat // => -90 + * bb.maxLon // => -100 */ constructor(coordinates: [number, number][]) { this.maxLat = -90 @@ -45,13 +57,24 @@ export class BBox { ]) } + /** + * Gets the bbox from a feature and caches it (by monkeypatching) the relevant feature + * + * + * const f = {type:"Feature",properties: {}, geometry: {type: "Point", coordinates: [-100,45]}} + * const bb = BBox.get(f) + * bb.minLat // => 45 + * bb.minLon // => -100 + * + */ static get(feature: Feature): BBox { const f = feature if (f.bbox?.overlapsWith === undefined) { - const turfBbox: number[] = turf.bbox(feature) + const [minX, minY, maxX, maxY]: number[] = turf.bbox(feature) + // Note: x is longitude f["bbox"] = new BBox([ - [turfBbox[0], turfBbox[1]], - [turfBbox[2], turfBbox[3]], + [minX, minY], + [maxX, maxY], ]) } return f["bbox"] diff --git a/src/Logic/FeatureSource/Sources/LayoutSource.ts b/src/Logic/FeatureSource/Sources/LayoutSource.ts index 3eee84959..601c75253 100644 --- a/src/Logic/FeatureSource/Sources/LayoutSource.ts +++ b/src/Logic/FeatureSource/Sources/LayoutSource.ts @@ -26,7 +26,6 @@ export default class LayoutSource extends FeatureSourceMerger { private readonly supportsForceDownload: UpdatableFeatureSource[] - private readonly fromCache: Map public static readonly fromCacheZoomLevel = 15 constructor( layers: LayerConfig[], diff --git a/src/Logic/GeoOperations.ts b/src/Logic/GeoOperations.ts index 74ee7aaa4..7c3dabb6c 100644 --- a/src/Logic/GeoOperations.ts +++ b/src/Logic/GeoOperations.ts @@ -734,7 +734,6 @@ export class GeoOperations { const splitted: Feature[] = [].concat(...lines) const kept: Feature[] = [] for (const f of splitted) { - console.log("Checking", f) if (!GeoOperations.inside(GeoOperations.centerpointCoordinates(f), boundary)) { continue } diff --git a/src/Logic/Web/LinkedDataLoader.ts b/src/Logic/Web/LinkedDataLoader.ts index 7bf03953e..97636ec3b 100644 --- a/src/Logic/Web/LinkedDataLoader.ts +++ b/src/Logic/Web/LinkedDataLoader.ts @@ -316,14 +316,16 @@ export default class LinkedDataLoader { input: Record> ): Record { const output: Record = {} - console.log("Input for patchVelopark:", input) for (const k in input) { output[k] = Array.from(input[k]) } - if (output["type"][0] === "https://data.velopark.be/openvelopark/terms#BicycleLocker") { + if (output["type"]?.[0] === "https://data.velopark.be/openvelopark/terms#BicycleLocker") { output["bicycle_parking"] = ["lockers"] } + if(output["type"] === undefined){ + console.error("No type given for", output) + } delete output["type"] function on(key: string, applyF: (s: string) => string) { @@ -506,7 +508,6 @@ export default class LinkedDataLoader { " ?parking a ", "?parking " + property + " " + (variable ?? "") ) - console.log("Fetching a velopark property gave", property, results) return results } diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index d13b6f75d..4f9894c40 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -164,6 +164,7 @@ export default class Constants { */ public static VectorTileServer: string | undefined = Constants.config.mvt_layer_server public static readonly maptilerApiKey = "GvoVAJgu46I5rZapJuAy" + public static readonly SummaryServer: string = Constants.config.summary_server private static isRetina(): boolean { if (Utils.runningFromConsole) { diff --git a/src/Models/RasterLayers.ts b/src/Models/RasterLayers.ts index 850a87967..da0cdfc3f 100644 --- a/src/Models/RasterLayers.ts +++ b/src/Models/RasterLayers.ts @@ -80,11 +80,14 @@ export class AvailableRasterLayers { return GeoOperations.inside(lonlat, eliPolygon) }) matching.unshift(AvailableRasterLayers.osmCarto) - matching.push(AvailableRasterLayers.defaultBackgroundLayer) + if (enableBing?.data) { matching.push(AvailableRasterLayers.bing) } matching.push(...AvailableRasterLayers.globalLayers) + if(!matching.some(l => l.id === AvailableRasterLayers.defaultBackgroundLayer.properties.id)){ + matching.push(AvailableRasterLayers.defaultBackgroundLayer) + } return matching }, [enableBing] diff --git a/src/Models/ThemeViewState.ts b/src/Models/ThemeViewState.ts index 9ae12e26c..d76c84318 100644 --- a/src/Models/ThemeViewState.ts +++ b/src/Models/ThemeViewState.ts @@ -690,9 +690,8 @@ export default class ThemeViewState implements SpecialVisualizationState { l.source.geojsonSource === undefined && l.doCount ) - const url = new URL(Constants.VectorTileServer) const summaryTileSource = new SummaryTileSource( - url.protocol + "//" + url.host + "/summary", + Constants.SummaryServer, layers.map((l) => l.id), this.mapProperties.zoom.map((z) => Math.max(Math.floor(z), 0)), this.mapProperties, diff --git a/src/StylesheetTestGui.ts b/src/StylesheetTestGui.ts index 6f6fe84c4..de0b9b1d2 100644 --- a/src/StylesheetTestGui.ts +++ b/src/StylesheetTestGui.ts @@ -1,4 +1,5 @@ -import SvelteUIElement from "./UI/Base/SvelteUIElement" import StylesheetTestGui from "./UI/StylesheetTestGui.svelte" -new SvelteUIElement(StylesheetTestGui, {}).AttachTo("main") +new StylesheetTestGui({ + target: document.getElementById("maindiv") +}) diff --git a/src/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte index dfbe08bf2..b14c80e81 100644 --- a/src/UI/AllThemesGui.svelte +++ b/src/UI/AllThemesGui.svelte @@ -65,6 +65,7 @@ } +
+
diff --git a/src/UI/Base/LoginToggle.svelte b/src/UI/Base/LoginToggle.svelte index 12d0e4ea9..65b07b81d 100644 --- a/src/UI/Base/LoginToggle.svelte +++ b/src/UI/Base/LoginToggle.svelte @@ -16,6 +16,10 @@ * If set, 'loading' will act as if we are already logged in. */ export let ignoreLoading: boolean = false + /** + * Only show the 'successful' state, don't show loading or error messages + */ + export let silentFail : boolean = false let loadingStatus = state?.osmConnection?.loadingStatus ?? new ImmutableStore("logged-in") let badge = state?.featureSwitches?.featureSwitchEnableLogin ?? new ImmutableStore(true) const t = Translations.t.general @@ -30,11 +34,11 @@ {#if $badge} - {#if !ignoreLoading && $loadingStatus === "loading"} + {#if !ignoreLoading && !silentFail && $loadingStatus === "loading"} - {:else if $loadingStatus === "error"} + {:else if !silentFail && $loadingStatus === "error"}
@@ -43,7 +47,7 @@ {:else if $loadingStatus === "logged-in"} - {:else if $loadingStatus === "not-attempted"} + {:else if !silentFail && $loadingStatus === "not-attempted"} {/if} {/if} diff --git a/src/UI/Image/LinkableImage.svelte b/src/UI/Image/LinkableImage.svelte index 12f488308..287c9866a 100644 --- a/src/UI/Image/LinkableImage.svelte +++ b/src/UI/Image/LinkableImage.svelte @@ -13,6 +13,7 @@ import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" import AttributedImage from "./AttributedImage.svelte" import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte" + import LoginToggle from "../Base/LoginToggle.svelte" export let tags: UIEventSource export let state: SpecialVisualizationState @@ -68,10 +69,12 @@ previewedImage={state.previewedImage} />
+ {#if linkable} {/if} + diff --git a/src/UI/Image/NearbyImages.svelte b/src/UI/Image/NearbyImages.svelte index 11e5c4d0c..c28e004d6 100644 --- a/src/UI/Image/NearbyImages.svelte +++ b/src/UI/Image/NearbyImages.svelte @@ -30,7 +30,7 @@ lon, lat, allowSpherical: new UIEventSource(false), - blacklist: AllImageProviders.LoadImagesFor(tags), + blacklist: AllImageProviders.LoadImagesFor(tags) }, state.indexedFeatures ) @@ -39,26 +39,24 @@ let allDone = imagesProvider.allDone - -
-
-

- -

- -
- {#if !$allDone} - - {:else if $images.length === 0} - - {:else} -
- {#each $images as image (image.pictureUrl)} +
+
+

+ +

+ +
+ {#if !$allDone} + + {:else if $images.length === 0} + + {:else} +
+ {#each $images as image (image.pictureUrl)} - {/each} -
- {/if} -
- + {/each} +
+ {/if} +
diff --git a/src/UI/Image/NearbyImagesCollapsed.svelte b/src/UI/Image/NearbyImagesCollapsed.svelte index 4129fbcc1..6cbc37bd9 100644 --- a/src/UI/Image/NearbyImagesCollapsed.svelte +++ b/src/UI/Image/NearbyImagesCollapsed.svelte @@ -25,7 +25,6 @@ let expanded = false -
{#if expanded} @@ -54,4 +53,3 @@ {/if}
-
diff --git a/src/UI/Leaderboard.svelte b/src/UI/Leaderboard.svelte index 4b6ffd21e..daf788383 100644 --- a/src/UI/Leaderboard.svelte +++ b/src/UI/Leaderboard.svelte @@ -30,7 +30,7 @@ } > = UIEventSource.FromPromise(Utils.downloadJsonCached(source)) - +

Contributed images with MapComplete: leaderboard

{#if $data} @@ -67,3 +67,4 @@
Logged in as {$loggedInContributor}
+
diff --git a/src/UI/NotFound.svelte b/src/UI/NotFound.svelte index d7e0534cf..ee7e9889b 100644 --- a/src/UI/NotFound.svelte +++ b/src/UI/NotFound.svelte @@ -5,6 +5,7 @@ console.log("???") +
+
diff --git a/src/UI/Popup/TagRendering/SpecialTranslation.svelte b/src/UI/Popup/TagRendering/SpecialTranslation.svelte index 12765bc37..3149a721f 100644 --- a/src/UI/Popup/TagRendering/SpecialTranslation.svelte +++ b/src/UI/Popup/TagRendering/SpecialTranslation.svelte @@ -63,7 +63,7 @@ } - +{#if lang === "*"} {#each specs as specpart} {#if typeof specpart === "string"} @@ -74,4 +74,17 @@ createVisualisation(specpart)} /> {/if} {/each} - +{:else} + + {#each specs as specpart} + {#if typeof specpart === "string"} + + {@html Utils.purify(Utils.SubstituteKeys(specpart, $tags)) } + + + {:else if $tags !== undefined} + createVisualisation(specpart)} /> + {/if} + {/each} + +{/if} diff --git a/src/UI/PrivacyGui.svelte b/src/UI/PrivacyGui.svelte index 1afdef92d..d92ca15c8 100644 --- a/src/UI/PrivacyGui.svelte +++ b/src/UI/PrivacyGui.svelte @@ -16,7 +16,7 @@ userRelatedState: new UserRelatedState(osmConnection) } - +

@@ -33,3 +33,4 @@

+
diff --git a/src/UI/StylesheetTestGui.svelte b/src/UI/StylesheetTestGui.svelte index 27aa90772..755b0b6c0 100644 --- a/src/UI/StylesheetTestGui.svelte +++ b/src/UI/StylesheetTestGui.svelte @@ -6,6 +6,7 @@ import { UIEventSource } from "../Logic/UIEventSource" +

Stylesheet testing grounds

@@ -167,3 +168,4 @@
+
diff --git a/src/UI/Test.svelte b/src/UI/Test.svelte index 4475d846c..df2281134 100644 --- a/src/UI/Test.svelte +++ b/src/UI/Test.svelte @@ -1,16 +1,5 @@ - -

Svelte native

- -

ToSvelte

- +
+
diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index 48220206b..41d4a5984 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -203,6 +203,7 @@ +
@@ -688,3 +689,4 @@ sl !== undefined && sl?.properties?.id === LastClickFeatureSource.newPointElementId)} moveTo={openNewElementButton} debug="newElement"/> +
diff --git a/src/all_themes_index.ts b/src/all_themes_index.ts index 864457e3c..6cc03b2c6 100644 --- a/src/all_themes_index.ts +++ b/src/all_themes_index.ts @@ -28,4 +28,6 @@ if (layout !== "") { ) } -new SvelteUIElement(AllThemesGui, {}).AttachTo("main") +new AllThemesGui({ + target: document.getElementById("main") +}) diff --git a/src/index.ts b/src/index.ts index 2d5a1a03a..1cebb856f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,7 +28,7 @@ async function timeout(timeMS: number): Promise<{ layers: string[] }> { async function getAvailableLayers(): Promise> { try { - const host = new URL(Constants.VectorTileServer).host + const host = new URL(Constants.SummaryServer).host const status: { layers: string[] } = await Promise.any([ Utils.downloadJson<{layers}>("https://" + host + "/summary/status.json"), timeout(2500), @@ -52,8 +52,10 @@ async function main() { ]) console.log("The available layers on server are", Array.from(availableLayers)) const state = new ThemeViewState(layout, availableLayers) - const main = new SvelteUIElement(ThemeViewGUI, { state }) - main.AttachTo("maindiv") + new ThemeViewGUI({ + target: document.getElementById("maindiv"), + props: {state} + }) Array.from(document.getElementsByClassName("delete-on-load")).forEach((el) => { el.parentElement.removeChild(el) }) diff --git a/src/index_theme.ts.template b/src/index_theme.ts.template index 6092f8453..048a54e12 100644 --- a/src/index_theme.ts.template +++ b/src/index_theme.ts.template @@ -1,5 +1,4 @@ import ThemeViewState from "./src/Models/ThemeViewState" -import SvelteUIElement from "./src/UI/Base/SvelteUIElement" import ThemeViewGUI from "./src/UI/ThemeViewGUI.svelte" import LayoutConfig from "./src/Models/ThemeConfig/LayoutConfig"; import MetaTagging from "./src/Logic/MetaTagging"; @@ -47,8 +46,10 @@ async function main() { MetaTagging.setThemeMetatagging(new ThemeMetaTagging()) // LAYOUT.ADD_LAYERS const state = new ThemeViewState(new LayoutConfig( layout), availableLayers) - const main = new SvelteUIElement(ThemeViewGUI, { state }) - main.AttachTo("maindiv") + new ThemeViewGUI({ + target: document.getElementById("maindiv"), + props: {state} + }) Array.from(document.getElementsByClassName("delete-on-load")).forEach(el => { el.parentElement.removeChild(el) }) diff --git a/src/leaderboard.ts b/src/leaderboard.ts index 3a15cf261..1d974d77e 100644 --- a/src/leaderboard.ts +++ b/src/leaderboard.ts @@ -1,4 +1,5 @@ -import SvelteUIElement from "./UI/Base/SvelteUIElement" import Leaderboard from "./UI/Leaderboard.svelte" -new SvelteUIElement(Leaderboard, {}).AttachTo("main") +new Leaderboard({ + target: document.getElementById("main") +}) diff --git a/src/notfound.ts b/src/notfound.ts index da596ea9d..1cb23811e 100644 --- a/src/notfound.ts +++ b/src/notfound.ts @@ -1,4 +1,5 @@ -import SvelteUIElement from "./UI/Base/SvelteUIElement" import NotFound from "./UI/NotFound.svelte" -new SvelteUIElement(NotFound, {}).AttachTo("maindiv") +new NotFound({ + target: document.getElementById("maindiv") +}) diff --git a/src/privacy_index.ts b/src/privacy_index.ts index c8da1465e..68587dfc4 100644 --- a/src/privacy_index.ts +++ b/src/privacy_index.ts @@ -1,3 +1,4 @@ -import SvelteUIElement from "./UI/Base/SvelteUIElement" import PrivacyGui from "./UI/PrivacyGui.svelte" -new SvelteUIElement(PrivacyGui, {}).AttachTo("main") +new PrivacyGui({ + target: document.getElementById("main") +}) diff --git a/src/test.ts b/src/test.ts index 52729071c..248e34073 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,4 +1,6 @@ import SvelteUIElement from "./UI/Base/SvelteUIElement" import Test from "./UI/Test.svelte" -new SvelteUIElement(Test).AttachTo("maindiv") +new Test({ + target: document.getElementById("maindiv") +})