Merge branch 'master' into develop

This commit is contained in:
Pieter Vander Vennet 2024-11-26 22:02:24 +01:00
commit 55741d7043
8 changed files with 134 additions and 32 deletions

View file

@ -106,6 +106,12 @@ If you want to deploy your fork:
2. Copy the entire `dist` folder to where you host your website. Visiting `index.html` gives you the landing page, 2. Copy the entire `dist` folder to where you host your website. Visiting `index.html` gives you the landing page,
visiting `yourwebsite/<theme>` should bring you to the appropriate theme. visiting `yourwebsite/<theme>` should bring you to the appropriate theme.
### Getting your own API-keys
Some services are bound to `https://mapcomplete.org`. In `package.json/config`, search for "#fork" and read the instructions.
Weird errors Weird errors
------------ ------------

View file

@ -44,7 +44,7 @@
"title": "een spandoek" "title": "een spandoek"
}, },
"12": { "12": {
"title": "een totem" "title": "eem reclamezuil"
}, },
"13": { "13": {
"description": "Gebruikt voor reclameborden, neonborden, logo's & toegangsborden voor instellingen", "description": "Gebruikt voor reclameborden, neonborden, logo's & toegangsborden voor instellingen",
@ -212,6 +212,9 @@
}, },
"7": { "7": {
"then": "Dit is een teken" "then": "Dit is een teken"
},
"9": {
"then": "Dit is een reclamezuil"
} }
}, },
"render": "Dit is een {advertising}" "render": "Dit is een {advertising}"
@ -238,7 +241,7 @@
"then": "Spandoek" "then": "Spandoek"
}, },
"9": { "9": {
"then": "Aanplakzuil" "then": "Reclamezuil"
} }
} }
} }

View file

@ -306,7 +306,12 @@
"logout": "Afmelden", "logout": "Afmelden",
"menu": { "menu": {
"aboutMapComplete": "Over MapComplete", "aboutMapComplete": "Over MapComplete",
"filter": "Filter data" "filter": "Filter data",
"aboutCurrentThemeTitle": "Over deze kaart",
"moreUtilsTitle": "Ontdek meer",
"openHereDifferentApp": "Open de huidige locatie in andere toepassingen",
"showIntroduction": "Toon introductie",
"title": "Menu"
}, },
"morescreen": { "morescreen": {
"createYourOwnTheme": "Maak je eigen MapComplete-kaart", "createYourOwnTheme": "Maak je eigen MapComplete-kaart",
@ -402,7 +407,9 @@
"recents": "Recent bekeken plaatsen", "recents": "Recent bekeken plaatsen",
"search": "Zoek naar een locatie, filter of kaart", "search": "Zoek naar een locatie, filter of kaart",
"searchShort": "Zoek…", "searchShort": "Zoek…",
"searching": "Aan het zoeken…" "searching": "Aan het zoeken…",
"nMoreFilters": "{n} meer",
"nothingFor": "Geen resultaten gevonden voor {term}"
}, },
"share": "Deel deze locatie", "share": "Deel deze locatie",
"sharescreen": { "sharescreen": {
@ -412,7 +419,15 @@
"fsWelcomeMessage": "Toon het welkomstbericht en de bijhorende tabbladen", "fsWelcomeMessage": "Toon het welkomstbericht en de bijhorende tabbladen",
"intro": "Kopieer onderstaande link om deze kaart naar vrienden en familie door te sturen:", "intro": "Kopieer onderstaande link om deze kaart naar vrienden en familie door te sturen:",
"thanksForSharing": "Bedankt om te delen!", "thanksForSharing": "Bedankt om te delen!",
"title": "Deel deze kaart" "title": "Deel deze kaart",
"fsBackground": "Wisselende achtergronden inschakelen",
"fsFilter": "De mogelijkheid inschakelen om te wisselen tussen lagen en filters",
"fsGeolocation": "Geolocatie inschakelen",
"openInOtherApplications": "De huidige locatie openen met een andere kaarttoepassing",
"openLayers": "Open het menu met lagen en filters",
"options": "Opties voor delen",
"stateIsIncluded": "De huidige status van de lagen en filters is opgenomen in de gedeelde link en iframe.",
"documentation": "Voor meer informatie over beschikbare URL-parameters, <a href='https://github.com/pietervdvn/MapComplete/blob/develop/Docs/URL_Parameters.md' target='_blank'>raadpleeg de documentatie</a>"
}, },
"skip": "Sla deze vraag over", "skip": "Sla deze vraag over",
"testing": "Testmode - wijzigingen worden niet opgeslaan", "testing": "Testmode - wijzigingen worden niet opgeslaan",
@ -479,7 +494,9 @@
"unlocked": "Bewegen ontgrendeld", "unlocked": "Bewegen ontgrendeld",
"viewportCenterCloseToGps": "De kaart is gecentreerd op je huidige GPS-locatie.", "viewportCenterCloseToGps": "De kaart is gecentreerd op je huidige GPS-locatie.",
"viewportCenterDetails": "Het kaartbeeldcentrum is {distance} {bearing} vanaf je huidige locatie.", "viewportCenterDetails": "Het kaartbeeldcentrum is {distance} {bearing} vanaf je huidige locatie.",
"west": "Naar het westen" "west": "Naar het westen",
"fromGps": "{distance} {direction} van uw locatie",
"fromMapCenter": "{distance} {direction} van het midden van de kaart"
}, },
"waitingForLocation": "Je locatie wordt gezocht…", "waitingForLocation": "Je locatie wordt gezocht…",
"weekdays": { "weekdays": {
@ -522,7 +539,17 @@
"searchToShort": "Je zoekopdracht is te kort, vul een langere tekst in", "searchToShort": "Je zoekopdracht is te kort, vul een langere tekst in",
"searchWikidata": "Zoek op Wikidata", "searchWikidata": "Zoek op Wikidata",
"wikipediaboxTitle": "Wikipedia" "wikipediaboxTitle": "Wikipedia"
} },
"retry": "Opnieuw proberen",
"searchAnswer": "Zoek een optie…",
"seeIndex": "Zie het overzich van alle thematische kaarten",
"uploadError": "Fout tijdens het uploaden van wijzigingen: {error}",
"mappingsAreHidden": "Sommige opties zijn verborgen. Gebruik zoeken om meer opties te tonen.",
"poweredByMapComplete": "Powered by MapComplete - crowdsourced, thematische kaarten met OpenStreetMap",
"uploadPending": "{count} wijzigingen in behandeling",
"uploadPendingSingle": "Eén wijziging in behandeling",
"uploadingChanges": "Wijzigingen aan het uploaden…",
"waitingForGeopermission": "Aan het wachten op toestemming om geolocatie te gebruiken…"
}, },
"hotkeyDocumentation": { "hotkeyDocumentation": {
"action": "Actie", "action": "Actie",
@ -536,7 +563,15 @@
"selectMapnik": "Gebruik OpenStreetMap-carto als achtergrondlaag", "selectMapnik": "Gebruik OpenStreetMap-carto als achtergrondlaag",
"selectOsmbasedmap": "Gebruik een OpenStreetMap-gebaseerde achtergrondkaart (of schakel de achtergrond-rasterlaag uit)", "selectOsmbasedmap": "Gebruik een OpenStreetMap-gebaseerde achtergrondkaart (of schakel de achtergrond-rasterlaag uit)",
"selectSearch": "Selecteer de zoekbalk om locaties te zoeken", "selectSearch": "Selecteer de zoekbalk om locaties te zoeken",
"title": "Sneltoetsen" "title": "Sneltoetsen",
"queryCurrentLocation": "Toon het adres dichtst bij het midden van de kaart",
"selectFavourites": "Open de pagina met favorieten",
"selectItem2": "Selecteer het POI het op één na dichtst bij het midden van de kaart (crosshair). Alleen wanneer toetsenbordnavigatie wordt gebruikt",
"shakePhone": "Schudden met je telefoon",
"translationMode": "Vertaalmodus in- of uitschakelen",
"openFilterPanel": "Opent het POI-lagen- en filterpaneel",
"selectItem": "Selecteer het POI het dichtst bij het midden van de kaart (crosshair). Alleen wanneer toetsenbordnavigatie wordt gebruikt",
"selectItem3": "Selecteer het POI het op twee na dichtst bij het midden van de kaart (crosshair). Alleen wanneer toetsenbordnavigatie wordt gebruikt"
}, },
"image": { "image": {
"addPicture": "Voeg foto toe", "addPicture": "Voeg foto toe",
@ -547,7 +582,10 @@
"nearby": { "nearby": {
"link": "Deze afbeelding toont het object", "link": "Deze afbeelding toont het object",
"seeNearby": "Bekijk foto's in de buurt", "seeNearby": "Bekijk foto's in de buurt",
"title": "Straatafbeeldingen uit de buurt" "title": "Straatafbeeldingen uit de buurt",
"failed": "Afbeeldingen ophalen van {service} mislukt",
"close": "Paneel met nabije afbeeldingen samenvouwen",
"noNearbyImages": "Geen afbeeldingen in de buurt gevonden"
}, },
"pleaseLogin": "Gelieve je aan te melden om een foto toe te voegen", "pleaseLogin": "Gelieve je aan te melden om een foto toe te voegen",
"respectPrivacy": "Voeg geen Google Maps, Google Streetview of foto's met auteursrechten toe.", "respectPrivacy": "Voeg geen Google Maps, Google Streetview of foto's met auteursrechten toe.",
@ -556,7 +594,34 @@
"uploadFailed": "Afbeelding uploaden mislukt. Heb je internet? Gebruik je Brave of UMatrix? Dan moet je derde partijen toelaten.", "uploadFailed": "Afbeelding uploaden mislukt. Heb je internet? Gebruik je Brave of UMatrix? Dan moet je derde partijen toelaten.",
"uploadMultipleDone": "{count} afbeeldingen zijn toegevoegd. Bedankt voor je bijdrage!", "uploadMultipleDone": "{count} afbeeldingen zijn toegevoegd. Bedankt voor je bijdrage!",
"uploadingMultiple": "Bezig met {count} foto's te uploaden…", "uploadingMultiple": "Bezig met {count} foto's te uploaden…",
"uploadingPicture": "Bezig met een foto te uploaden…" "uploadingPicture": "Bezig met een foto te uploaden…",
"panoramax": {
"deletionRequested": "Het rapport is verzonden. Een moderator zal er binnenkort naar kijken",
"freeform": "Is er andere relevante informatie?",
"otherFreeform": "Waarom moet deze afbeelding worden verwijderd:",
"report": {
"blur_missing": "Op deze foto is een gezicht of nummerplaat niet geblurd",
"blur_excess": "Er is te geblurd, waardoor de foto onbruikbaar is",
"copyright": "De foto bevat auteursrechtelijk beschermde inhoud",
"mislocated": "De foto is van een andere locatie",
"other": "Een andere reden, specificeer",
"picture_low_quality": "De foto is van lage kwaliteit",
"privacy": "De foto toont een privé-eigendom",
"inappropriate": "Deze foto is ongepast (bevat naakt, roept op tot haat of is geen straatbeeld)"
},
"requestDeletion": "Verwijdering van foto aanvragen",
"title": "Waarom zou dit beeld permanent verwijderd moeten worden?",
"placeholder": "Leg uit waarom de foto verwijderd moet worden"
},
"processing": "De server is je beeld aan het verwerken",
"unlink": {
"button": "Link naar foto verwijderen",
"title": "Link naar deze afbeelding verwijderen?",
"explanation": "Door de link naar deze afbeelding te verwijderen, wordt deze niet meer getoond bij dit object. De afbeelding zal nog steeds verschijnen bij nabije afbeeldingen en mogelijk ook andere objecten."
},
"upload": {
"failReasons": "Mogelijk heb je geen verbinding meer met het internet"
}
}, },
"importInspector": { "importInspector": {
"title": "Inspecteer en beheer importeer-notas" "title": "Inspecteer en beheer importeer-notas"
@ -781,4 +846,4 @@
"description": "Een Wikidata-code" "description": "Een Wikidata-code"
} }
} }
} }

View file

@ -17,6 +17,7 @@
], ],
"oauth_credentials": { "oauth_credentials": {
"#": "This client-id is registered by 'MapComplete' on OpenStreetMap.org", "#": "This client-id is registered by 'MapComplete' on OpenStreetMap.org",
"#fork": "For a fork, you will need to register your own key at https://www.openstreetmap.org/oauth2/applications ; redirect url is `https://<your-domain>/land.html`, permissions: `read_user_preferences`, `modify preferences`, `modify the map`. For GPS-traces: both, `modify-notes` if you want the notes-theme to work.",
"oauth_client_id": "K93H1d8ve7p-tVLE1ZwsQ4lAFLQk8INx5vfTLMu5DWk", "oauth_client_id": "K93H1d8ve7p-tVLE1ZwsQ4lAFLQk8INx5vfTLMu5DWk",
"oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg", "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg",
"url": "https://www.openstreetmap.org", "url": "https://www.openstreetmap.org",
@ -37,10 +38,12 @@
"error_server": "https://report.mapcomplete.org/report", "error_server": "https://report.mapcomplete.org/report",
"api_keys": { "api_keys": {
"#": "Various API-keys for various services. Feel free to reuse those in another MapComplete-hosted version", "#": "Various API-keys for various services. Feel free to reuse those in another MapComplete-hosted version",
"#fork": "Not bound to a domain; can be reused",
"imgur": "7070e7167f0a25a", "imgur": "7070e7167f0a25a",
"mapillary_v4": "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" "mapillary_v4": "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85"
}, },
"panoramax": { "panoramax": {
"#fork": "Not bound to a domain; can be reused",
"url": "https://panoramax.mapcomplete.org", "url": "https://panoramax.mapcomplete.org",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnZW92aXNpbyIsInN1YiI6IjU5ZjgzOGI0LTM4ZjAtNDdjYi04OWYyLTM3NDQ3MWMxNTUxOCJ9.0rBioZS_48NTjnkIyN9497c3fQdTqtGgH1HDqlz1bWs", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnZW92aXNpbyIsInN1YiI6IjU5ZjgzOGI0LTM4ZjAtNDdjYi04OWYyLTM3NDQ3MWMxNTUxOCJ9.0rBioZS_48NTjnkIyN9497c3fQdTqtGgH1HDqlz1bWs",
"sequence": "6e702976-580b-419c-8fb3-cf7bd364e6f8", "sequence": "6e702976-580b-419c-8fb3-cf7bd364e6f8",
@ -61,6 +64,7 @@
"photonEndpoint": "https://photon.komoot.io/", "photonEndpoint": "https://photon.komoot.io/",
"jsonld-proxy": "https://lod.mapcomplete.org/extractgraph?url={url}", "jsonld-proxy": "https://lod.mapcomplete.org/extractgraph?url={url}",
"protomaps": { "protomaps": {
"#fork": "Bound to https://mapcomplete.org; get your own at https://protomaps.com/",
"api-key": "2af8b969a9e8b692", "api-key": "2af8b969a9e8b692",
"endpoint": "https://api.protomaps.com/tiles/", "endpoint": "https://api.protomaps.com/tiles/",
"styles": [ "styles": [
@ -73,7 +77,7 @@
} }
}, },
"scripts": { "scripts": {
"init": "npm ci && npm run prep:layeroverview && npm run generate && npm run download:editor-layer-index && npm run generate:layouts && npm run clean && npm run weblate:add-upstream", "init": "npm ci && npm run prep:layeroverview && npm run generate && npm run download:editor-layer-index && npm run generate:layouts && npm run clean",
"start": "npm run generate:layeroverview && npm run strt", "start": "npm run generate:layeroverview && npm run strt",
"strt": "vite --host | sed 's/localhost:/127.0.0.1:/g'", "strt": "vite --host | sed 's/localhost:/127.0.0.1:/g'",
"build": "./scripts/build.sh", "build": "./scripts/build.sh",
@ -114,6 +118,8 @@
"download:editor-layer-index": "vite-node scripts/downloadEli.ts", "download:editor-layer-index": "vite-node scripts/downloadEli.ts",
"download:stats": "vite-node scripts/GenerateSeries.ts", "download:stats": "vite-node scripts/GenerateSeries.ts",
"download:images": "vite-node scripts/generateImageAnalysis.ts -- ~/data/imgur-image-backup/", "download:images": "vite-node scripts/generateImageAnalysis.ts -- ~/data/imgur-image-backup/",
"weblate:add-upstream": "git remote add weblate https://translate.mapcomplete.org/git/mapcomplete/core/ ; git remote update weblate",
"weblate:fix": "npm run weblate:add-upstream && git merge weblate/master && git rebase origin/master && git push origin master",
"lint": "npm run lint:prettier && npm run lint:eslint && npm run lint:themes", "lint": "npm run lint:prettier && npm run lint:eslint && npm run lint:themes",
"lint:eslint": "eslint ./src", "lint:eslint": "eslint ./src",
"lint:prettier": "prettier --check '**/*.ts' '**/*.svelte'", "lint:prettier": "prettier --check '**/*.ts' '**/*.svelte'",

View file

@ -13,60 +13,74 @@ export default class FilteringFeatureSource implements FeatureSource {
private readonly _is_dirty = new UIEventSource(false) private readonly _is_dirty = new UIEventSource(false)
private readonly _layer: FilteredLayer private readonly _layer: FilteredLayer
private previousFeatureSet: Set<any> = undefined private previousFeatureSet: Set<any> = undefined
private readonly _zoomlevel: Store<number>
private readonly _selectedElement: Store<Feature>
constructor( constructor(
layer: FilteredLayer, layer: FilteredLayer,
upstream: FeatureSource, upstream: FeatureSource,
fetchStore?: (id: string) => Store<Record<string, string>>, fetchStore?: (id: string) => Store<Record<string, string>>,
globalFilters?: Store<GlobalFilter[]>, globalFilters?: Store<GlobalFilter[]>,
metataggingUpdated?: Store<any> metataggingUpdated?: Store<any>,
zoomlevel?: Store<number>,
selectedElement?: Store<Feature>
) { ) {
this.upstream = upstream this.upstream = upstream
this._fetchStore = fetchStore this._fetchStore = fetchStore
this._layer = layer this._layer = layer
this._globalFilters = globalFilters this._globalFilters = globalFilters
this._zoomlevel = zoomlevel
this._selectedElement = selectedElement
const self = this
upstream.features.addCallback(() => { upstream.features.addCallback(() => {
self.update() this.update()
}) })
layer.isDisplayed.addCallback(() => { layer.isDisplayed.addCallback(() => {
self.update() this.update()
}) })
layer.appliedFilters.forEach((value) => layer.appliedFilters.forEach((value) =>
value.addCallback((_) => { value.addCallback((_) => {
self.update() this.update()
}) })
) )
this._is_dirty.stabilized(1000).addCallbackAndRunD((dirty) => { this._is_dirty.stabilized(1000).addCallbackAndRunD((dirty) => {
if (dirty) { if (dirty) {
self.update() this.update()
} }
}) })
metataggingUpdated?.addCallback((_) => { metataggingUpdated?.addCallback(() => {
self._is_dirty.setData(true) this._is_dirty.setData(true)
}) })
globalFilters?.addCallback((_) => { globalFilters?.addCallback(() => {
self.update() this.update()
}) })
selectedElement?.addCallback(() => this.update())
zoomlevel?.mapD(z => Math.floor(z)).addCallback(() => this.update())
this.update() this.update()
} }
private update() { private update() {
const self = this
const layer = this._layer const layer = this._layer
const features: Feature[] = this.upstream.features.data ?? [] const features: Feature[] = this.upstream.features.data ?? []
const includedFeatureIds = new Set<string>() const includedFeatureIds = new Set<string>()
const globalFilters = self._globalFilters?.data?.map((f) => f) const globalFilters = this._globalFilters?.data?.map((f) => f)
const zoomlevel = this._zoomlevel?.data
const selectedElement = this._selectedElement?.data?.properties?.id
const newFeatures = (features ?? []).filter((f) => { const newFeatures = (features ?? []).filter((f) => {
self.registerCallback(f.properties.id) this.registerCallback(f.properties.id)
if (!layer.isShown(f.properties, globalFilters)) { if(selectedElement === f.properties.id){
return true
}
if (!layer.isShown(f.properties, globalFilters, zoomlevel)) {
return false return false
} }

View file

@ -210,7 +210,7 @@ export default class FilteredLayer {
* - the specified 'global filters' * - the specified 'global filters'
* - the 'isShown'-filter set by the layer * - the 'isShown'-filter set by the layer
*/ */
public isShown(properties: Record<string, string>, globalFilters?: GlobalFilter[]): boolean { public isShown(properties: Record<string, string>, globalFilters?: GlobalFilter[], zoomlevel?: number): boolean {
if (properties._deleted === "yes") { if (properties._deleted === "yes") {
return false return false
} }
@ -219,9 +219,10 @@ export default class FilteredLayer {
if (neededTags !== undefined) { if (neededTags !== undefined) {
const doesMatch = neededTags.matchesProperties(properties) const doesMatch = neededTags.matchesProperties(properties)
if (globalFilter.forceShowOnMatch) { if (globalFilter.forceShowOnMatch) {
return doesMatch || this.isDisplayed.data if(doesMatch){
} return true
if (!doesMatch) { }
} else if (!doesMatch) {
return false return false
} }
} }
@ -240,6 +241,10 @@ export default class FilteredLayer {
} }
} }
if(zoomlevel !== undefined && (this.layerDef.minzoom > zoomlevel || this.layerDef.minzoomVisible < zoomlevel)){
return false
}
return true return true
} }

View file

@ -159,7 +159,7 @@ export default class LayerConfig extends WithContextLoader {
if (json["minZoom"] !== undefined) { if (json["minZoom"] !== undefined) {
throw "At " + context + ": minzoom is written all lowercase" throw "At " + context + ": minzoom is written all lowercase"
} }
this.minzoomVisible = json.minzoomVisible ?? this.minzoom this.minzoomVisible = json.minzoomVisible ?? 100
this.shownByDefault = json.shownByDefault ?? true this.shownByDefault = json.shownByDefault ?? true
this.doCount = json.isCounted ?? this.shownByDefault ?? true this.doCount = json.isCounted ?? this.shownByDefault ?? true
this.forceLoad = json.forceLoad ?? false this.forceLoad = json.forceLoad ?? false

View file

@ -473,7 +473,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
fs.layer, fs.layer,
fs, fs,
(id) => this.featureProperties.getStore(id), (id) => this.featureProperties.getStore(id),
this.layerState.globalFilters this.layerState.globalFilters,
undefined,
this.mapProperties.zoom,
this.selectedElement
) )
filteringFeatureSource.set(layerName, filtered) filteringFeatureSource.set(layerName, filtered)