forked from MapComplete/MapComplete
Formatting, comments, use injected download functionality
This commit is contained in:
parent
7b774b2aa3
commit
dc5c3461f8
7 changed files with 47 additions and 98 deletions
|
@ -44,7 +44,7 @@ export default class PerLayerFeatureSourceSplitter {
|
||||||
for (const layer of layers.data) {
|
for (const layer of layers.data) {
|
||||||
if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) {
|
if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) {
|
||||||
// We have found our matching layer!
|
// We have found our matching layer!
|
||||||
featuresPerLayer.set(layer.layerDef.id, [f])
|
featuresPerLayer.get(layer.layerDef.id).push(f)
|
||||||
if (!layer.layerDef.passAllFeatures) {
|
if (!layer.layerDef.passAllFeatures) {
|
||||||
// If not 'passAllFeatures', we are done for this feature
|
// If not 'passAllFeatures', we are done for this feature
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -374,9 +374,15 @@ export class Changes {
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
const id = change.type + "/" + change.id
|
const id = change.type + "/" + change.id
|
||||||
if (!objects.has(id)) {
|
if (!objects.has(id)) {
|
||||||
|
// The object hasn't been seen before, so it doesn't exist yet and is newly created by its very definition
|
||||||
if (change.id >= 0) {
|
if (change.id >= 0) {
|
||||||
|
// Might be a failed fetch for simply this object
|
||||||
throw "Did not get an object that should be known: " + id
|
throw "Did not get an object that should be known: " + id
|
||||||
}
|
}
|
||||||
|
if(change.changes === undefined){
|
||||||
|
// This object is a change to a newly created object. However, we have not seen the creation changedescription yet!
|
||||||
|
throw "Not a creation of the object"
|
||||||
|
}
|
||||||
// This is a new object that should be created
|
// This is a new object that should be created
|
||||||
states.set(id, "created")
|
states.set(id, "created")
|
||||||
console.log("Creating object for changeDescription", change)
|
console.log("Creating object for changeDescription", change)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Title from "../UI/Base/Title";
|
||||||
import {FixedUiElement} from "../UI/Base/FixedUiElement";
|
import {FixedUiElement} from "../UI/Base/FixedUiElement";
|
||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
|
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
|
||||||
import {CountryCoder} from "latlon2country"
|
import {CountryCoder} from "latlon2country"
|
||||||
|
import ScriptUtils from "../scripts/ScriptUtils";
|
||||||
|
|
||||||
|
|
||||||
export class SimpleMetaTagger {
|
export class SimpleMetaTagger {
|
||||||
|
@ -40,8 +41,7 @@ export class SimpleMetaTagger {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CountryTagger extends SimpleMetaTagger {
|
export class CountryTagger extends SimpleMetaTagger {
|
||||||
private static readonly coder = new CountryCoder("https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country/");
|
private static readonly coder = new CountryCoder("https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country", ScriptUtils.DownloadJSON);
|
||||||
|
|
||||||
public runningTasks: Set<any>;
|
public runningTasks: Set<any>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -36,7 +36,7 @@ export default class UserRelatedState extends ElementsState {
|
||||||
public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>;
|
public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>;
|
||||||
|
|
||||||
|
|
||||||
constructor(layoutToUse: LayoutConfig, options:{attemptLogin : true | boolean}) {
|
constructor(layoutToUse: LayoutConfig, options?:{attemptLogin : true | boolean}) {
|
||||||
super(layoutToUse);
|
super(layoutToUse);
|
||||||
|
|
||||||
this.osmConnection = new OsmConnection({
|
this.osmConnection = new OsmConnection({
|
||||||
|
|
|
@ -39,7 +39,8 @@ class AutomationPanel extends Combine{
|
||||||
if (indices === undefined) {
|
if (indices === undefined) {
|
||||||
throw ("No tiles loaded - can not automate")
|
throw ("No tiles loaded - can not automate")
|
||||||
}
|
}
|
||||||
|
const openChangeset = new UIEventSource<string>(undefined);
|
||||||
|
openChangeset.addCallbackAndRun(cs => console.log("Sync current open changeset to:", cs))
|
||||||
|
|
||||||
const nextTileToHandle = tileState.map(handledTiles => {
|
const nextTileToHandle = tileState.map(handledTiles => {
|
||||||
for (const index of indices) {
|
for (const index of indices) {
|
||||||
|
@ -60,7 +61,9 @@ class AutomationPanel extends Combine{
|
||||||
}
|
}
|
||||||
console.warn("Triggered map on nextTileToHandle",tileIndex)
|
console.warn("Triggered map on nextTileToHandle",tileIndex)
|
||||||
const start = new Date()
|
const start = new Date()
|
||||||
return AutomationPanel.TileHandler(layoutToUse, tileIndex, layerId, tagRenderingToAutomate.tagRendering, extraCommentText,(result, logMessage) => {
|
return AutomationPanel.TileHandler(layoutToUse, tileIndex, layerId, tagRenderingToAutomate.tagRendering, extraCommentText,
|
||||||
|
openChangeset,
|
||||||
|
(result, logMessage) => {
|
||||||
const end = new Date()
|
const end = new Date()
|
||||||
const timeNeeded = (end.getTime() - start.getTime()) / 1000;
|
const timeNeeded = (end.getTime() - start.getTime()) / 1000;
|
||||||
neededTimes.data.push(timeNeeded)
|
neededTimes.data.push(timeNeeded)
|
||||||
|
@ -92,15 +95,28 @@ class AutomationPanel extends Combine{
|
||||||
|
|
||||||
return new Combine(["Handled " + total + "/" + indices.length + " tiles: ",
|
return new Combine(["Handled " + total + "/" + indices.length + " tiles: ",
|
||||||
new List(Array.from(perResult.keys()).map(key => key + ": " + perResult.get(key))),
|
new List(Array.from(perResult.keys()).map(key => key + ": " + perResult.get(key))),
|
||||||
"Handling one tile needs " + (Math.floor(timePerTile * 100) / 100) + "s on average. Estimated time left: " + Math.floor((indices.length - total) * timePerTile) + "s"
|
"Handling one tile needs " + (Math.floor(timePerTile * 100) / 100) + "s on average. Estimated time left: " + Utils.toHumanTime((indices.length - total) * timePerTile)
|
||||||
]).SetClass("flex flex-col")
|
]).SetClass("flex flex-col")
|
||||||
}))
|
}))
|
||||||
|
|
||||||
super([statistics, automaton, new VariableUiElement(logMessages.map(logMessages => new List(logMessages)))])
|
super([statistics, automaton,
|
||||||
|
new SubtleButton(undefined, "Clear fixed").onClick(() => {
|
||||||
|
const st = tileState.data
|
||||||
|
for (const tileIndex in st) {
|
||||||
|
if(st[tileIndex] === "fixed"){
|
||||||
|
delete st[tileIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tileState.ping();
|
||||||
|
}),
|
||||||
|
new VariableUiElement(logMessages.map(logMessages => new List(logMessages)))])
|
||||||
this.SetClass("flex flex-col")
|
this.SetClass("flex flex-col")
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TileHandler(layoutToUse: LayoutConfig, tileIndex: number, targetLayer: string, targetAction: TagRenderingConfig, extraCommentText: UIEventSource<string>, whenDone: ((result: string, logMessage?: string) => void)): BaseUIElement {
|
private static TileHandler(layoutToUse: LayoutConfig, tileIndex: number, targetLayer: string, targetAction: TagRenderingConfig, extraCommentText: UIEventSource<string>,
|
||||||
|
openChangeset: UIEventSource<string>,
|
||||||
|
whenDone: ((result: string, logMessage?: string) => void)): BaseUIElement {
|
||||||
|
|
||||||
const state = new MapState(layoutToUse, {attemptLogin: false})
|
const state = new MapState(layoutToUse, {attemptLogin: false})
|
||||||
extraCommentText.syncWith( state.changes.extraComment)
|
extraCommentText.syncWith( state.changes.extraComment)
|
||||||
|
@ -186,6 +202,13 @@ class AutomationPanel extends Combine{
|
||||||
if (handled === 0) {
|
if (handled === 0) {
|
||||||
whenDone("no-action","Inspected "+inspected+" elements: "+log.join("; "))
|
whenDone("no-action","Inspected "+inspected+" elements: "+log.join("; "))
|
||||||
}else{
|
}else{
|
||||||
|
state.osmConnection.AttemptLogin()
|
||||||
|
const openCS = state.osmConnection.GetPreference("current-open-changeset-"+layoutToUse.id)
|
||||||
|
openCS.addCallbackAndRun(cs => {
|
||||||
|
console.log("Current open Changeset is now: ", cs)
|
||||||
|
openChangeset.setData(cs)
|
||||||
|
})
|
||||||
|
openCS.setData(openChangeset.data)
|
||||||
state.changes.flushChanges("handled tile automatically, time to flush!")
|
state.changes.flushChanges("handled tile automatically, time to flush!")
|
||||||
whenDone("fixed", "Updated " + handled+" elements, inspected "+inspected+": "+log.join("; "))
|
whenDone("fixed", "Updated " + handled+" elements, inspected "+inspected+": "+log.join("; "))
|
||||||
}
|
}
|
||||||
|
@ -198,8 +221,6 @@ class AutomationPanel extends Combine{
|
||||||
new VariableUiElement(stateToShow)]).SetClass("flex flex-col")
|
new VariableUiElement(stateToShow)]).SetClass("flex flex-col")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,10 +255,10 @@ class AutomatonGui {
|
||||||
private static GenerateMainPanel(): BaseUIElement {
|
private static GenerateMainPanel(): BaseUIElement {
|
||||||
|
|
||||||
const themeSelect = new DropDown<string>("Select a theme",
|
const themeSelect = new DropDown<string>("Select a theme",
|
||||||
AllKnownLayouts.layoutsList.map(l => ({value: l.id, shown: l.id}))
|
AllKnownLayouts.layoutsList.map(l => ({value: l.id, shown: l.id}))
|
||||||
)
|
)
|
||||||
|
|
||||||
LocalStorageSource.Get("automation-theme-id").syncWith(themeSelect.GetValue())
|
LocalStorageSource.Get("automation-theme-id", "missing_streets").syncWith(themeSelect.GetValue())
|
||||||
|
|
||||||
|
|
||||||
const tilepath = ValidatedTextField.InputForType("url", {
|
const tilepath = ValidatedTextField.InputForType("url", {
|
||||||
|
@ -299,7 +320,7 @@ class AutomatonGui {
|
||||||
tilepath,
|
tilepath,
|
||||||
"Add an extra comment:",
|
"Add an extra comment:",
|
||||||
extraComment,
|
extraComment,
|
||||||
new VariableUiElement(extraComment.GetValue().map(c => "Your comment is "+c.length+"/200 characters long")).SetClass("subtle"),
|
new VariableUiElement(extraComment.GetValue().map(c => "Your comment is "+(c?.length??0)+"/200 characters long")).SetClass("subtle"),
|
||||||
new VariableUiElement(tilesToRunOver.map(t => {
|
new VariableUiElement(tilesToRunOver.map(t => {
|
||||||
if (t === undefined) {
|
if (t === undefined) {
|
||||||
return "No path given or still loading..."
|
return "No path given or still loading..."
|
||||||
|
|
|
@ -54,9 +54,9 @@ export class DropDown<T> extends InputElement<T> {
|
||||||
const select = document.createElement("select")
|
const select = document.createElement("select")
|
||||||
select.classList.add(...(options.select_class.split(" ") ?? []))
|
select.classList.add(...(options.select_class.split(" ") ?? []))
|
||||||
for (let i = 0; i < values.length; i++) {
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
|
||||||
const option = document.createElement("option")
|
const option = document.createElement("option")
|
||||||
option.value = "" + i
|
option.value = "" + i
|
||||||
|
console.log(values[i].shown)
|
||||||
option.appendChild(Translations.W(values[i].shown).ConstructElement())
|
option.appendChild(Translations.W(values[i].shown).ConstructElement())
|
||||||
select.appendChild(option)
|
select.appendChild(option)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,90 +24,10 @@
|
||||||
"clustering": false,
|
"clustering": false,
|
||||||
"overpassTimeout": 180,
|
"overpassTimeout": 180,
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
|
||||||
"id": "postal_code_boundary",
|
|
||||||
"name": {
|
|
||||||
"en": "postal codes"
|
|
||||||
},
|
|
||||||
"minzoom": 8,
|
|
||||||
"title": {
|
|
||||||
"render": {
|
|
||||||
"en": "Postal code {postal_code}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": {},
|
|
||||||
"tagRenderings": [
|
|
||||||
{
|
|
||||||
"id": "postal_code",
|
|
||||||
"render": {
|
|
||||||
"en": "The postal code is {postal_code}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": {
|
|
||||||
"osmTags": {
|
|
||||||
"or": [
|
|
||||||
"boundary=postal_code",
|
|
||||||
{
|
|
||||||
"and": [
|
|
||||||
"bounary=administrative",
|
|
||||||
"postal_code~*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mapRendering": [
|
|
||||||
{
|
|
||||||
"label": "<div class='text-xl bg-white rounded-full pl-2 pr-2 break-normal'>{postal_code}</div>",
|
|
||||||
"location": [
|
|
||||||
"point",
|
|
||||||
"centroid"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": {
|
|
||||||
"render": "#00f"
|
|
||||||
},
|
|
||||||
"width": {
|
|
||||||
"render": "4"
|
|
||||||
},
|
|
||||||
"fill": "no",
|
|
||||||
"dashArray": "8 8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isShown": {
|
|
||||||
"render": "yes",
|
|
||||||
"mappings": [
|
|
||||||
{
|
|
||||||
"if": "_country!=be",
|
|
||||||
"then": "no"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "wrong_postal_code",
|
|
||||||
"source": {
|
|
||||||
"osmTags": {
|
|
||||||
"and": [
|
|
||||||
"boundary~*",
|
|
||||||
"addr:postcode~*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"title": "Boundary relation with addr:postcode={addr:postcode}",
|
|
||||||
"mapRendering": [
|
|
||||||
{
|
|
||||||
"color": "#f00",
|
|
||||||
"width": 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "town_hall",
|
"id": "town_hall",
|
||||||
"name": {
|
"name": {
|
||||||
"en": "town halls"
|
"en": "town halls and churches"
|
||||||
},
|
},
|
||||||
"minzoom": 12,
|
"minzoom": 12,
|
||||||
"title": {
|
"title": {
|
||||||
|
@ -115,7 +35,7 @@
|
||||||
"en": "Town hall {name}"
|
"en": "Town hall {name}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"calculatedTags": [
|
"#calculatedTags": [
|
||||||
"_postal_code_properties=(() => { const f = feat.overlapWith('postal_code_boundary'); if(f.length===0){return {};}; const p = f[0]?.feat?.properties; return {id:p.id, postal_code: p.postal_code, _closest_town_hall: p._closest_town_hall}; })()",
|
"_postal_code_properties=(() => { const f = feat.overlapWith('postal_code_boundary'); if(f.length===0){return {};}; const p = f[0]?.feat?.properties; return {id:p.id, postal_code: p.postal_code, _closest_town_hall: p._closest_town_hall}; })()",
|
||||||
"_postal_code=feat.get('_postal_code_properties')?.postal_code",
|
"_postal_code=feat.get('_postal_code_properties')?.postal_code",
|
||||||
"_postal_code_center_distance=feat.distanceTo(feat.get('_postal_code_properties').id)"
|
"_postal_code_center_distance=feat.distanceTo(feat.get('_postal_code_properties').id)"
|
||||||
|
@ -124,7 +44,9 @@
|
||||||
"tagRenderings": [],
|
"tagRenderings": [],
|
||||||
"presets": [],
|
"presets": [],
|
||||||
"source": {
|
"source": {
|
||||||
"osmTags": "amenity=townhall"
|
"osmTags": {
|
||||||
|
"or": ["amenity=townhall","building=church"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"mapRendering": [
|
"mapRendering": [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue