diff --git a/Docs/ServerConfig/cache/Caddyfile b/Docs/ServerConfig/cache/Caddyfile new file mode 100644 index 000000000..61d4b6211 --- /dev/null +++ b/Docs/ServerConfig/cache/Caddyfile @@ -0,0 +1,9 @@ +cache.mapcomplete.org { + reverse_proxy /mvt { + to http://127.0.0.1:7800 + } + + reverse_proxy /summary { + to http://127.0.0.1:2345 + } +} diff --git a/Docs/ServerConfig/cache/cache.txt b/Docs/ServerConfig/cache/cache.txt new file mode 100644 index 000000000..ddda8f29a --- /dev/null +++ b/Docs/ServerConfig/cache/cache.txt @@ -0,0 +1,15 @@ +# Cache.mapComplete.org server config + +The "cache"-server is hosted at nerdlab. + +It has a full OSM-copy on disk, and has a Postgis/Postgres database with a table for every layer for quick access. It should run the tileserver and the summaryserver + +## Dyndns + +https://dynamicdns.park-your-domain.com/update?host=cache&domain=mapcomplete.org&password=[ddns_password] + +## Setup + +See SettingUpPSQL.md + + diff --git a/scripts/hetzner/config/Caddyfile b/Docs/ServerConfig/hetzner/Caddyfile similarity index 100% rename from scripts/hetzner/config/Caddyfile rename to Docs/ServerConfig/hetzner/Caddyfile diff --git a/scripts/hetzner/config/csp-logger-config.json b/Docs/ServerConfig/hetzner/csp-logger-config.json similarity index 100% rename from scripts/hetzner/config/csp-logger-config.json rename to Docs/ServerConfig/hetzner/csp-logger-config.json diff --git a/Docs/ServerConfig/hetzner/hetzner.txt b/Docs/ServerConfig/hetzner/hetzner.txt new file mode 100644 index 000000000..0dae8e283 --- /dev/null +++ b/Docs/ServerConfig/hetzner/hetzner.txt @@ -0,0 +1,5 @@ +# Hetzner + +This server hosts the studio files and is used for expermintal builds. + +For used hosts, see the Caddyfile diff --git a/Docs/SettingUpPSQL.md b/Docs/SettingUpPSQL.md index 1b7ed9aa9..05aa3e54b 100644 --- a/Docs/SettingUpPSQL.md +++ b/Docs/SettingUpPSQL.md @@ -54,7 +54,7 @@ pg_tileserv kan hier gedownload worden: https://github.com/CrunchyData/pg_tilese ```` export DATABASE_URL=postgresql://user:password@localhost:5444/osm-poi -./pg_tileserv +nohup ./pg_tileserv & ```` Tiles are available at: @@ -64,3 +64,8 @@ map.addSource("drinking_water", { "tiles": ["http://127.0.0.2:7800/public.drinking_water/{z}/{x}/{y}.pbf"] // http://127.0.0.2:7800/public.drinking_water.json", }) ```` + +# Rebooting: + +-> Restart the docker container +-> diff --git a/assets/png/twoway.png.license b/assets/png/twoway.png.license index 2452bee1e..ed0288300 100644 --- a/assets/png/twoway.png.license +++ b/assets/png/twoway.png.license @@ -1,2 +1,2 @@ SPDX-FileCopyrightText: Pieter Vander Vennet -SPDX-License-Identifier: CC0 \ No newline at end of file +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/png/twoway.svg.license b/assets/png/twoway.svg.license index 2452bee1e..ed0288300 100644 --- a/assets/png/twoway.svg.license +++ b/assets/png/twoway.svg.license @@ -1,2 +1,2 @@ SPDX-FileCopyrightText: Pieter Vander Vennet -SPDX-License-Identifier: CC0 \ No newline at end of file +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/themes/shops/shops.json b/assets/themes/shops/shops.json index 8b7abf172..db96e8941 100644 --- a/assets/themes/shops/shops.json +++ b/assets/themes/shops/shops.json @@ -59,4 +59,3 @@ "minzoom": 16 } } -} diff --git a/package.json b/package.json index 652937d24..2232bfd4a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg", "url": "https://www.openstreetmap.org" }, - "mvt_layer_server": "http://127.0.0.1:7800/public.{type}_{layer}/{z}/{x}/{y}.pbf", + "mvt_layer_server": "http://cache.mapcomplete.org/mvt/public.{type}_{layer}/{z}/{x}/{y}.pbf", "disabled:oauth_credentials": { "##": "DEV", "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/", diff --git a/scripts/osm2pgsql/tilecountServer.ts b/scripts/osm2pgsql/tilecountServer.ts index 8980e9939..385fbc825 100644 --- a/scripts/osm2pgsql/tilecountServer.ts +++ b/scripts/osm2pgsql/tilecountServer.ts @@ -28,7 +28,7 @@ class OsmPoiDatabase { private static readonly prefixes: ReadonlyArray = ["pois", "lines", "polygons"] private readonly _client: Client private isConnected = false - private supportedLayers: string[] = undefined + private supportedLayers: Set = undefined private metaCache: PoiDatabaseMeta = undefined private metaCacheDate: Date = undefined @@ -64,7 +64,7 @@ class OsmPoiDatabase { this._client.end() } - async getLayers(): Promise { + async getLayers(): Promise> { if (this.supportedLayers !== undefined) { return this.supportedLayers } @@ -74,8 +74,8 @@ class OsmPoiDatabase { "WHERE table_schema = 'public' AND table_name LIKE 'lines_%';" ) const layers = result.rows.map((r) => r.table_name.substring("lines_".length)) - this.supportedLayers = layers - return layers + this.supportedLayers = new Set(layers) + return this.supportedLayers } async getMeta(): Promise { @@ -218,7 +218,12 @@ const server = new Server(2345, [ let sum = 0 let properties: Record = {} + const availableLayers = await tcs.getLayers() for (const layer of layers.split("+")) { + console.log("Getting layer", layer) + if (!availableLayers.has(layer)) { + continue + } const count = await tcs.getCount( layer, Tiles.tile_bounds_lon_lat(Number(z), Number(x), Number(y)) diff --git a/src/Logic/FeatureSource/Sources/LayoutSource.ts b/src/Logic/FeatureSource/Sources/LayoutSource.ts index 181daa3c1..ff5b5fda8 100644 --- a/src/Logic/FeatureSource/Sources/LayoutSource.ts +++ b/src/Logic/FeatureSource/Sources/LayoutSource.ts @@ -11,9 +11,7 @@ import DynamicGeoJsonTileSource from "../TiledFeatureSource/DynamicGeoJsonTileSo import { BBox } from "../../BBox" import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeatureSource" import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource" -import { Features } from "@rgossiaux/svelte-headlessui/types" import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource" -import { layouts } from "chart.js" /** * This source will fetch the needed data from various sources for the given layout. @@ -21,17 +19,18 @@ import { layouts } from "chart.js" * Note that special layers (with `source=null` will be ignored) */ export default class LayoutSource extends FeatureSourceMerger { - private readonly _isLoading: UIEventSource = new UIEventSource(false) /** * Indicates if a data source is loading something */ - public readonly isLoading: Store = this._isLoading + public readonly isLoading: Store + constructor( layers: LayerConfig[], featureSwitches: FeatureSwitchState, mapProperties: { bounds: Store; zoom: Store }, backend: string, isDisplayed: (id: string) => Store, + mvtAvailableLayers: Set, fullNodeDatabaseSource?: FullNodeDatabaseSource ) { const { bounds, zoom } = mapProperties @@ -47,47 +46,60 @@ export default class LayoutSource extends FeatureSourceMerger { maxAge: l.maxAgeOfCache, }) ) - console.log(mapProperties) - const mvtSources: FeatureSource[] = osmLayers.map(l => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id))) + const mvtSources: FeatureSource[] = osmLayers + .filter((f) => mvtAvailableLayers.has(f.id)) + .map((l) => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id))) + const nonMvtSources = [] + const nonMvtLayers = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id)) + const isLoading = new UIEventSource(false) + if (nonMvtLayers.length > 0) { + console.log( + "Layers ", + nonMvtLayers.map((l) => l.id), + " cannot be fetched from the cache server, defaulting to overpass/OSM-api" + ) + const overpassSource = LayoutSource.setupOverpass( + osmLayers, + bounds, + zoom, + featureSwitches + ) + const osmApiSource = LayoutSource.setupOsmApiSource( + osmLayers, + bounds, + zoom, + backend, + featureSwitches, + fullNodeDatabaseSource + ) + nonMvtSources.push(overpassSource, osmApiSource) - /* - const overpassSource = LayoutSource.setupOverpass( - osmLayers, - bounds, - zoom, - featureSwitches - )//*/ -/* - const osmApiSource = LayoutSource.setupOsmApiSource( - osmLayers, - bounds, - zoom, - backend, - featureSwitches, - fullNodeDatabaseSource - )*/ + function setIsLoading() { + const loading = overpassSource?.runningQuery?.data || osmApiSource?.isRunning?.data + isLoading.setData(loading) + } + overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading()) + osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading()) + } const geojsonSources: FeatureSource[] = geojsonlayers.map((l) => LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) ) + super(...geojsonSources, ...fromCache, ...mvtSources, ...nonMvtSources) - super(...geojsonSources, ...fromCache, ...mvtSources) - - const self = this - function setIsLoading() { - // const loading = overpassSource?.runningQuery?.data || osmApiSource?.isRunning?.data - // self._isLoading.setData(loading) - } - - // overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading()) - // osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading()) + this.isLoading = isLoading } - private static setupMvtSource(layer: LayerConfig, mapProperties: { zoom: Store; bounds: Store }, isActive?: Store): FeatureSource{ + private static setupMvtSource( + layer: LayerConfig, + mapProperties: { zoom: Store; bounds: Store }, + isActive?: Store + ): FeatureSource { return new DynamicMvtileSource(layer, mapProperties, { isActive }) } + private static setupGeojsonSource( layer: LayerConfig, mapProperties: { zoom: Store; bounds: Store }, diff --git a/src/index.ts b/src/index.ts index 3d2e6cd3a..e0df3ec27 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import Combine from "./UI/Base/Combine" import { SubtleButton } from "./UI/Base/SubtleButton" import { Utils } from "./Utils" import Download from "./assets/svg/Download.svelte" +import Constants from "./Models/Constants" function webgl_support() { try { @@ -19,38 +20,41 @@ function webgl_support() { return false } } +async function availableLayers(): Promise> { + const status = await Utils.downloadJson(Constants.VectorTileServer + "/status.json") + return new Set(status.layers) +} +async function main() { + // @ts-ignore + try { + if (!webgl_support()) { + throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this." + } + const [layout, availableLayers] = await Promise.all([ + DetermineLayout.GetLayout(), + await availableLayers(), + ]) + const state = new ThemeViewState(layout) + const main = new SvelteUIElement(ThemeViewGUI, { state }) + main.AttachTo("maindiv") + } catch (err) { + console.error("Error while initializing: ", err, err.stack) + const customDefinition = DetermineLayout.getCustomDefinition() + new Combine([ + new FixedUiElement(err).SetClass("block alert"), -// @ts-ignore -try { - if (!webgl_support()) { - throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this." - } - DetermineLayout.GetLayout() - .then((layout) => { - const state = new ThemeViewState(layout) - const main = new SvelteUIElement(ThemeViewGUI, { state }) - main.AttachTo("maindiv") - }) - .catch((err) => { - console.error("Error while initializing: ", err, err.stack) - const customDefinition = DetermineLayout.getCustomDefinition() - new Combine([ - new FixedUiElement(err).SetClass("block alert"), - - customDefinition?.length > 0 - ? new SubtleButton( - new SvelteUIElement(Download), - "Download the raw file" - ).onClick(() => + customDefinition?.length > 0 + ? new SubtleButton(new SvelteUIElement(Download), "Download the raw file").onClick( + () => Utils.offerContentsAsDownloadableFile( DetermineLayout.getCustomDefinition(), "mapcomplete-theme.json", { mimetype: "application/json" } ) - ) - : undefined, - ]).AttachTo("maindiv") - }) -} catch (err) { - new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv") + ) + : undefined, + ]).AttachTo("maindiv") + } } + +main().then((_) => {})