Further stabilization of UK-addresses: add minzoom requirement to import button, fix eternal loading message

This commit is contained in:
Pieter Vander Vennet 2021-10-08 15:11:20 +02:00
parent 561b21d2fe
commit d8fa054a34
8 changed files with 71 additions and 40 deletions

View file

@ -29,8 +29,12 @@ export default class SaveTileToLocalStorageActor {
public static MarkVisited(layerId: string, tileId: number, freshness: Date){ public static MarkVisited(layerId: string, tileId: number, freshness: Date){
const key = `${SaveTileToLocalStorageActor.storageKey}-${layerId}-${tileId}` const key = `${SaveTileToLocalStorageActor.storageKey}-${layerId}-${tileId}`
localStorage.setItem(key + "-time", JSON.stringify(freshness.getTime())) try{
localStorage.setItem(key + "-format", SaveTileToLocalStorageActor.formatVersion) localStorage.setItem(key + "-time", JSON.stringify(freshness.getTime()))
localStorage.setItem(key + "-format", SaveTileToLocalStorageActor.formatVersion)
}catch(e){
console.error("Could not mark tile ", key, "as visited")
}
} }
} }

View file

@ -206,7 +206,9 @@ export default class FeaturePipeline {
maxZoomLevel: state.layoutToUse.clustering.maxZoom, maxZoomLevel: state.layoutToUse.clustering.maxZoom,
registerTile: (tile) => { registerTile: (tile) => {
// We save the tile data for the given layer to local storage // We save the tile data for the given layer to local storage
new SaveTileToLocalStorageActor(tile, tile.tileIndex) if(source.layer.layerDef.source.geojsonSource === undefined || source.layer.layerDef.source.isOsmCacheLayer == true){
new SaveTileToLocalStorageActor(tile, tile.tileIndex)
}
perLayerHierarchy.get(source.layer.layerDef.id).registerTile(new RememberingSource(tile)) perLayerHierarchy.get(source.layer.layerDef.id).registerTile(new RememberingSource(tile))
tile.features.addCallbackAndRunD(_ => self.newDataLoadedSignal.setData(tile)) tile.features.addCallbackAndRunD(_ => self.newDataLoadedSignal.setData(tile))
@ -239,7 +241,11 @@ export default class FeaturePipeline {
this.runningQuery = updater.runningQuery.map( this.runningQuery = updater.runningQuery.map(
overpass => overpass || osmFeatureSource.isRunning.data, [osmFeatureSource.isRunning] overpass => {
console.log("FeaturePipeline: runningQuery state changed. Overpass", overpass ? "is querying," : "is idle,",
"osmFeatureSource is", osmFeatureSource.isRunning ? "is running ("+ +")" : "is idle")
return overpass || osmFeatureSource.isRunning.data;
}, [osmFeatureSource.isRunning]
) )

View file

@ -58,21 +58,25 @@ export default class OsmFeatureSource {
for (const neededTile of neededTiles) { for (const neededTile of neededTiles) {
if (self.downloadedTiles.has(neededTile)) { if (self.downloadedTiles.has(neededTile)) {
return; continue;
} }
console.log("Tile download", Tiles.tile_from_index(neededTile).join("/"), "started")
self.downloadedTiles.add(neededTile) self.downloadedTiles.add(neededTile)
Promise.resolve(self.LoadTile(...Tiles.tile_from_index(neededTile)).then(_ => { self.LoadTile(...Tiles.tile_from_index(neededTile)).then(_ => {
})) console.log("Tile ", Tiles.tile_from_index(neededTile).join("/"), "loaded")
})
} }
} catch (e) { } catch (e) {
console.error(e) console.error(e)
}finally {
console.log("Done")
self.isRunning.setData(false)
} }
self.isRunning.setData(false)
}) })
const neededLayers = options.state.layoutToUse.layers const neededLayers = options.state.layoutToUse.layers
.filter( layer => !layer.doNotDownload ) .filter(layer => !layer.doNotDownload)
.filter(layer => layer.source.geojsonSource === undefined || layer.source.isOsmCacheLayer) .filter(layer => layer.source.geojsonSource === undefined || layer.source.isOsmCacheLayer)
this.allowedTags = new Or(neededLayers.map(l => l.source.osmTags)) this.allowedTags = new Or(neededLayers.map(l => l.source.osmTags))
} }
@ -96,22 +100,22 @@ export default class OsmFeatureSource {
{ {
flatProperties: true flatProperties: true
}); });
// The geojson contains _all_ features at the given location // The geojson contains _all_ features at the given location
// We only keep what is needed // We only keep what is needed
geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties)) geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties))
console.log("Tile geojson:", z, x, y, "is", geojson) console.log("Tile geojson:", z, x, y, "is", geojson)
const index = Tiles.tile_index(z, x, y); const index = Tiles.tile_index(z, x, y);
new PerLayerFeatureSourceSplitter(this.filteredLayers, new PerLayerFeatureSourceSplitter(this.filteredLayers,
this.handleTile, this.handleTile,
new StaticFeatureSource(geojson.features, false), new StaticFeatureSource(geojson.features, false),
{ {
tileIndex:index tileIndex: index
} }
); );
if(this.options.markTileVisited){ if (this.options.markTileVisited) {
this.options.markTileVisited(index) this.options.markTileVisited(index)
} }
} catch (e) { } catch (e) {

View file

@ -9,11 +9,17 @@ import Constants from "../../Models/Constants";
import Toggle from "../Input/Toggle"; import Toggle from "../Input/Toggle";
import CreateNewNodeAction from "../../Logic/Osm/Actions/CreateNewNodeAction"; import CreateNewNodeAction from "../../Logic/Osm/Actions/CreateNewNodeAction";
import {Tag} from "../../Logic/Tags/Tag"; import {Tag} from "../../Logic/Tags/Tag";
import Loading from "../Base/Loading";
export default class ImportButton extends Toggle { export default class ImportButton extends Toggle {
constructor(imageUrl: string | BaseUIElement, message: string | BaseUIElement, constructor(imageUrl: string | BaseUIElement, message: string | BaseUIElement,
originalTags: UIEventSource<any>, originalTags: UIEventSource<any>,
newTags: UIEventSource<Tag[]>, lat: number, lon: number) { newTags: UIEventSource<Tag[]>,
lat: number, lon: number,
minZoom: number,
state: {
locationControl: UIEventSource<{ zoom: number }>
}) {
const t = Translations.t.general.add; const t = Translations.t.general.add;
const isImported = originalTags.map(tags => tags._imported === "yes") const isImported = originalTags.map(tags => tags._imported === "yes")
const appliedTags = new Toggle( const appliedTags = new Toggle(
@ -30,6 +36,7 @@ export default class ImportButton extends Toggle {
) )
const button = new SubtleButton(imageUrl, message) const button = new SubtleButton(imageUrl, message)
minZoom = Math.max(16, minZoom ?? 19)
button.onClick(async () => { button.onClick(async () => {
if (isImported.data) { if (isImported.data) {
@ -49,11 +56,13 @@ export default class ImportButton extends Toggle {
}) })
const withLoadingCheck = new Toggle( const withLoadingCheck = new Toggle(new Toggle(
t.stillLoading, new Loading(t.stillLoading.Clone()),
new Combine([button, appliedTags]).SetClass("flex flex-col"), new Combine([button, appliedTags]).SetClass("flex flex-col"),
State.state.featurePipeline.runningQuery State.state.featurePipeline.runningQuery
) ),t.zoomInFurther.Clone(),
state.locationControl.map(l => l.zoom >= minZoom)
)
const importButton = new Toggle(t.hasBeenImported, withLoadingCheck, isImported) const importButton = new Toggle(t.hasBeenImported, withLoadingCheck, isImported)
const pleaseLoginButton = const pleaseLoginButton =

View file

@ -396,7 +396,10 @@ export default class SpecialVisualizations {
name: "icon", name: "icon",
doc: "A nice icon to show in the button", doc: "A nice icon to show in the button",
defaultValue: "./assets/svg/addSmall.svg" defaultValue: "./assets/svg/addSmall.svg"
}], },
{name:"minzoom",
doc: "How far the contributor must zoom in before being able to import the point",
defaultValue: "18"}],
docs: `This button will copy the data from an external dataset into OpenStreetMap. It is only functional in official themes but can be tested in unofficial themes. docs: `This button will copy the data from an external dataset into OpenStreetMap. It is only functional in official themes but can be tested in unofficial themes.
If you want to import a dataset, make sure that: If you want to import a dataset, make sure that:
@ -439,13 +442,13 @@ There are also some technicalities in your theme to keep in mind:
return newTags return newTags
}) })
const id = tagSource.data.id; const id = tagSource.data.id;
const feature = State.state.allElements.ContainingFeatures.get(id) const feature = state.allElements.ContainingFeatures.get(id)
if (feature.geometry.type !== "Point") { if (feature.geometry.type !== "Point") {
return new FixedUiElement("Error: can only import point objects").SetClass("alert") return new FixedUiElement("Error: can only import point objects").SetClass("alert")
} }
const [lon, lat] = feature.geometry.coordinates; const [lon, lat] = feature.geometry.coordinates;
return new ImportButton( return new ImportButton(
args[2], args[1], tagSource, rewrittenTags, lat, lon args[2], args[1], tagSource, rewrittenTags, lat, lon, Number(args[3]), state
) )
} }
} }

View file

@ -37,24 +37,29 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1043" inkscape:window-height="1003"
id="namedview14" id="namedview14"
showgrid="false" showgrid="false"
inkscape:zoom="7.375" inkscape:zoom="7.375"
inkscape:cx="-1.3561062" inkscape:cx="-1.3561062"
inkscape:cy="19.621117" inkscape:cy="41.316032"
inkscape:window-x="0" inkscape:window-x="862"
inkscape:window-y="0" inkscape:window-y="1080"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="svg12" /> inkscape:current-layer="svg12" />
<path <path
d="m 42.372766,41.559418 h 3.247468 c 0.421762,0 0.76133,0.339541 0.76133,0.761329 v 3.241506 c 0,0.421761 -0.339541,0.761329 -0.76133,0.761329 h -3.247468 c -0.421762,0 -0.76133,-0.339541 -0.76133,-0.761329 v -3.241506 c 0,-0.421761 0.339541,-0.761329 0.76133,-0.761329 z" d="m 27.122405,19.186537 h 33.74819 c 4.383014,0 7.911859,3.528561 7.911859,7.911848 v 33.68623 c 0,4.383006 -3.528563,7.911848 -7.911859,7.911848 h -33.74819 c -4.383014,0 -7.911859,-3.528561 -7.911859,-7.911848 v -33.68623 c 0,-4.383006 3.528563,-7.911848 7.911859,-7.911848 z"
style="fill:#495aad;stroke-width:0.0542103;paint-order:normal" style="fill:#495aad;stroke-width:0.56336182;paint-order:normal"
id="path6" id="path6"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
d="m 42.085614,42.793949 v 2.289464 c 0.381581,0 0.763173,0.381581 0.763173,0.763173 h 2.289463 c 0,-0.381581 0.381581,-0.763173 0.763173,-0.763173 v -2.289464 c -0.381581,0 -0.763173,-0.381581 -0.763173,-0.763172 h -2.289463 c 0,0.38158 -0.381581,0.763172 -0.763173,0.763172 z" d="m 24.138277,32.015973 v 23.792462 c 3.965449,0 7.931011,3.965449 7.931011,7.931014 h 23.792453 c 0,-3.965449 3.965449,-7.931014 7.931014,-7.931014 V 32.015973 c -3.965449,0 -7.931014,-3.965449 -7.931014,-7.931002 H 32.069288 c 0,3.965439 -3.965449,7.931002 -7.931011,7.931002 z"
id="path8" id="path8"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="fill:none;stroke:#ffffff;stroke-width:0.27187553" /> style="fill:none;stroke:#ffffff;stroke-width:2.8253727" />
<path
id="path3711"
d="m 44.16217,30.966164 c -7.526249,0 -13.627102,6.101307 -13.627102,13.627103 0,7.525795 6.101307,13.627102 13.627102,13.627102 7.525796,0 13.627103,-6.101307 13.627103,-13.627102 0,-7.525796 -6.101307,-13.627103 -13.627103,-13.627103 z m -3.168302,21.803364 -0.0091,-0.0091 -0.0077,0.0091 -6.353865,-6.541009 3.192832,-3.254153 3.16921,3.263237 9.53897,-9.820144 3.176933,3.269596 z"
inkscape:connector-curvature="0"
style="fill:#fdd835;stroke-width:0.45423675" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -39,14 +39,14 @@
{ {
"id": "to_import", "id": "to_import",
"source": { "source": {
"#geoJson": "http://127.0.0.1:8080/islington_small_piece.geojson", "#geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/assets/themes/uk_addresses/islington_small_piece.geojson",
"geoJson": "https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/assets/themes/uk_addresses/islington_small_piece.geojson", "geoJson": "https://osm-uk-addresses.russss.dev/addresses/{z}/{x}/{y}.json",
"##geoJson": "https://raw.githubusercontent.com/russss/osm-uk-addresses/main/output/islington.geojson",
"osmTags": "inspireid~*", "osmTags": "inspireid~*",
"geoJsonZoomLevel": 16,
"isOsmCache": false "isOsmCache": false
}, },
"name": "Addresses to check", "name": "Addresses to check",
"minzoom": 12, "minzoom": 14,
"wayHandling": 1, "wayHandling": 1,
"icon": { "icon": {
"render": "./assets/themes/uk_addresses/housenumber_unknown.svg", "render": "./assets/themes/uk_addresses/housenumber_unknown.svg",
@ -122,7 +122,7 @@
} }
}, },
"calculatedTags": [ "calculatedTags": [
"_closest_3_street_names=feat.closestn('named_streets',3, 'name').map(f => ({name: f.feat.properties.name, distance: Math.round(1000*f.distance), id: f.id}))", "_closest_3_street_names=feat.properties['addr:street'] === undefined ? feat.closestn('named_streets',3, 'name').map(f => ({name: f.feat.properties.name, distance: Math.round(1000*f.distance), id: f.id})) : []",
"_closest_street:0:name=JSON.parse(feat.properties._closest_3_street_names)[0]?.name", "_closest_street:0:name=JSON.parse(feat.properties._closest_3_street_names)[0]?.name",
"_closest_street:1:name=JSON.parse(feat.properties._closest_3_street_names)[1]?.name", "_closest_street:1:name=JSON.parse(feat.properties._closest_3_street_names)[1]?.name",
"_closest_street:2:name=JSON.parse(feat.properties._closest_3_street_names)[2]?.name", "_closest_street:2:name=JSON.parse(feat.properties._closest_3_street_names)[2]?.name",

View file

@ -13,8 +13,7 @@
"uploadDone": "<span class='thanks'>Your picture has been added. Thanks for helping out!</span>", "uploadDone": "<span class='thanks'>Your picture has been added. Thanks for helping out!</span>",
"dontDelete": "Cancel", "dontDelete": "Cancel",
"doDelete": "Remove image", "doDelete": "Remove image",
"isDeleted": "Deleted", "isDeleted": "Deleted"
"hasBeenImported": "This feature has been imported"
}, },
"centerMessage": { "centerMessage": {
"loadingData": "Loading data…", "loadingData": "Loading data…",
@ -103,7 +102,8 @@
"confirmButton": "Add a {category} here.<br/><div class='alert'>Your addition is visible for everyone</div>", "confirmButton": "Add a {category} here.<br/><div class='alert'>Your addition is visible for everyone</div>",
"openLayerControl": "Open the layer control box", "openLayerControl": "Open the layer control box",
"layerNotEnabled": "The layer {layer} is not enabled. Enable this layer to add a point", "layerNotEnabled": "The layer {layer} is not enabled. Enable this layer to add a point",
"hasBeenImported": "This point has already been imported" "hasBeenImported": "This point has already been imported",
"zoomInMore": "Zoom in more to import this feature"
}, },
"pickLanguage": "Choose a language: ", "pickLanguage": "Choose a language: ",
"about": "Easily edit and add OpenStreetMap for a certain theme", "about": "Easily edit and add OpenStreetMap for a certain theme",