forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
1378c1a779
372 changed files with 26005 additions and 20082 deletions
|
@ -29,6 +29,7 @@ import { Changes } from "../src/Logic/Osm/Changes"
|
|||
import TableOfContents from "../src/UI/Base/TableOfContents"
|
||||
import MarkdownUtils from "../src/Utils/MarkdownUtils"
|
||||
import { parse as parse_html } from "node-html-parser"
|
||||
import { AvailableRasterLayers } from "../src/Models/RasterLayers"
|
||||
|
||||
/**
|
||||
* Converts a markdown-file into a .json file, which a walkthrough/slideshow element can use
|
||||
|
@ -54,15 +55,15 @@ class ToSlideshowJson {
|
|||
sections.push(currentSection)
|
||||
currentSection = []
|
||||
}
|
||||
line = line.replace('src="../../public/', 'src="./')
|
||||
line = line.replace('src="../../', 'src="./')
|
||||
line = line.replace("src=\"../../public/", "src=\"./")
|
||||
line = line.replace("src=\"../../", "src=\"./")
|
||||
currentSection.push(line)
|
||||
}
|
||||
sections.push(currentSection)
|
||||
writeFileSync(
|
||||
this._target,
|
||||
JSON.stringify({
|
||||
sections: sections.map((s) => s.join("\n")).filter((s) => s.length > 0),
|
||||
sections: sections.map((s) => s.join("\n")).filter((s) => s.length > 0)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -81,7 +82,7 @@ class WikiPageGenerator {
|
|||
|
||||
generate() {
|
||||
let wikiPage =
|
||||
'{|class="wikitable sortable"\n' +
|
||||
"{|class=\"wikitable sortable\"\n" +
|
||||
"! Name, link !! Genre !! Covered region !! Language !! Description !! Free materials !! Image\n" +
|
||||
"|-"
|
||||
|
||||
|
@ -139,7 +140,7 @@ export class GenerateDocs extends Script {
|
|||
}
|
||||
|
||||
this.WriteMarkdownFile("./Docs/Tags_format.md", TagUtils.generateDocs(), [
|
||||
"src/Logic/Tags/TagUtils.ts",
|
||||
"src/Logic/Tags/TagUtils.ts"
|
||||
])
|
||||
|
||||
new ToSlideshowJson(
|
||||
|
@ -165,7 +166,7 @@ export class GenerateDocs extends Script {
|
|||
})
|
||||
|
||||
this.WriteMarkdownFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), [
|
||||
"src/UI/SpecialVisualizations.ts",
|
||||
"src/UI/SpecialVisualizations.ts"
|
||||
])
|
||||
this.WriteMarkdownFile(
|
||||
"./Docs/CalculatedTags.md",
|
||||
|
@ -173,13 +174,31 @@ export class GenerateDocs extends Script {
|
|||
["src/Logic/SimpleMetaTagger.ts", "src/Logic/ExtraFunctions.ts"]
|
||||
)
|
||||
this.WriteMarkdownFile("./Docs/SpecialInputElements.md", Validators.HelpText(), [
|
||||
"src/UI/InputElement/Validators.ts",
|
||||
"src/UI/InputElement/Validators.ts"
|
||||
])
|
||||
|
||||
this.WriteMarkdownFile("./Docs/ChangesetMeta.md", Changes.getDocs(), [
|
||||
"src/Logic/Osm/Changes.ts",
|
||||
"src/Logic/Osm/ChangesetHandler.ts",
|
||||
"src/Logic/Osm/ChangesetHandler.ts"
|
||||
])
|
||||
const eli = await AvailableRasterLayers.editorLayerIndex()
|
||||
this.WriteMarkdownFile("./Docs/ELI-overview.md",
|
||||
[
|
||||
"# Layers in the Editor Layer Index",
|
||||
"This table gives a summary of ids, names and other metainformation. [See the online, interactive map here](https://osmlab.github.io/editor-layer-index/) or [visit the repository](https://github.com/osmlab/editor-layer-index)",
|
||||
MarkdownUtils.table(
|
||||
["id", "name", "category", "Best", "attribution"],
|
||||
eli.map(f => [f.properties.id, f.properties.name, f.properties.category, f.properties.best ? "⭐" : "",
|
||||
f.properties.attribution?.html ?? f.properties.attribution?.text
|
||||
])
|
||||
)
|
||||
|
||||
].join("\n\n"), [
|
||||
"./public/assets/data/editor-layer-index.json"
|
||||
|
||||
]
|
||||
)
|
||||
|
||||
new WikiPageGenerator().generate()
|
||||
|
||||
console.log("Generated docs")
|
||||
|
@ -212,7 +231,7 @@ export class GenerateDocs extends Script {
|
|||
md = TableOfContents.insertTocIntoMd(md)
|
||||
}
|
||||
|
||||
md.replace(/\n\n\n+/g, "\n\n")
|
||||
md = md.replace(/\n\n\n+/g, "\n\n")
|
||||
|
||||
if (!md.endsWith("\n")) {
|
||||
md += "\n"
|
||||
|
@ -225,7 +244,7 @@ export class GenerateDocs extends Script {
|
|||
"This document is autogenerated from",
|
||||
autogenSource
|
||||
.map((s) => `[${s}](https://github.com/pietervdvn/MapComplete/blob/develop/${s})`)
|
||||
.join(", "),
|
||||
.join(", ")
|
||||
].join(" ")
|
||||
|
||||
writeFileSync(filename, warnAutomated + md + "\n\n" + generatedFrom + "\n")
|
||||
|
@ -234,7 +253,7 @@ export class GenerateDocs extends Script {
|
|||
private generateHotkeyDocs() {
|
||||
new ThemeViewState(new LayoutConfig(<any>bookcases), new Set())
|
||||
this.WriteMarkdownFile("./Docs/Hotkeys.md", Hotkeys.generateDocumentation(), [
|
||||
"src/UI/Base/Hotkeys.ts",
|
||||
"src/UI/Base/Hotkeys.ts"
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -268,7 +287,7 @@ export class GenerateDocs extends Script {
|
|||
}
|
||||
|
||||
this.WriteMarkdownFile("./Docs/builtin_units.md", ["# Units", ...els].join("\n\n"), [
|
||||
`assets/layers/unit/unit.json`,
|
||||
`assets/layers/unit/unit.json`
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -449,7 +468,7 @@ export class GenerateDocs extends Script {
|
|||
theme.title,
|
||||
"(",
|
||||
`[${theme.id}](https://mapcomplete.org/${theme.id})`,
|
||||
")",
|
||||
")"
|
||||
].join(" "),
|
||||
|
||||
"_This document details some technical information about this MapComplete theme, mostly about the attributes used in the theme. Various links point toward more information about the attributes, e.g. to the OpenStreetMap-wiki, to TagInfo or tools creating statistics_",
|
||||
|
@ -469,7 +488,7 @@ export class GenerateDocs extends Script {
|
|||
MarkdownUtils.list(theme.language.filter((ln) => ln !== "_context")),
|
||||
"# Layers defined in this theme configuration file",
|
||||
"These layers can not be reused in different themes.",
|
||||
...layersToInline.map((l) => l.GenerateDocumentation(null)),
|
||||
...layersToInline.map((l) => l.GenerateDocumentation(null))
|
||||
].join("\n")
|
||||
this.WriteMarkdownFile(
|
||||
"./Docs/Themes/" + theme.id + ".md",
|
||||
|
@ -549,10 +568,10 @@ export class GenerateDocs extends Script {
|
|||
Array.from(AllSharedLayers.sharedLayers.keys()).map(
|
||||
(id) => `[${id}](./Layers/${id}.md)`
|
||||
)
|
||||
),
|
||||
)
|
||||
].join("\n\n")
|
||||
this.WriteMarkdownFile("./Docs/BuiltinLayers.md", el, [
|
||||
"src/Customizations/AllKnownLayouts.ts",
|
||||
"src/Customizations/AllKnownLayouts.ts"
|
||||
])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,11 @@ class ParseLayer extends Conversion<
|
|||
const fixed = this._prepareLayer.convert(parsed, context.inOperation("PrepareLayer"))
|
||||
|
||||
if (!fixed.source && fixed.presets?.length < 1) {
|
||||
context.enter("source").err("No source is configured. (Tags might be automatically derived if presets are given)")
|
||||
context
|
||||
.enter("source")
|
||||
.err(
|
||||
"No source is configured. (Tags might be automatically derived if presets are given)"
|
||||
)
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Script from "./Script"
|
||||
import { readFileSync, writeFileSync } from "fs"
|
||||
import { appendFileSync, readFileSync, writeFile, writeFileSync } from "fs"
|
||||
import { ChangeDescription } from "../src/Logic/Osm/Actions/ChangeDescription"
|
||||
import { Changes } from "../src/Logic/Osm/Changes"
|
||||
import { OsmObject } from "../src/Logic/Osm/OsmObject"
|
||||
|
@ -28,6 +28,91 @@ class HandleErrors extends Script {
|
|||
constructor() {
|
||||
super("Inspects the errors made on a given day. Argument: path to errors")
|
||||
}
|
||||
|
||||
private readonly ignoreUsers = new Set<string>([])
|
||||
|
||||
private async handleError(parsed: ErrorMessage, changesObj: Changes, downloader: OsmObjectDownloader, createdChangesets: Set<string>, refusedFiles: Set<string>) {
|
||||
console.log(
|
||||
parsed.message.username,
|
||||
parsed.message.layout,
|
||||
parsed.message.message,
|
||||
parsed.date,
|
||||
)
|
||||
|
||||
const e = parsed.message
|
||||
const neededIds = Changes.GetNeededIds(e.pendingChanges)
|
||||
// We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes
|
||||
const osmObjects: { id: string; osmObj: OsmObject | "deleted" }[] = await Promise.all<{
|
||||
id: string
|
||||
osmObj: OsmObject | "deleted"
|
||||
}>(
|
||||
neededIds.map(async (id) => {
|
||||
try {
|
||||
|
||||
const osmObj = await downloader.DownloadObjectAsync(id)
|
||||
return ({
|
||||
id,
|
||||
osmObj,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("COULD NOT DOWNLOAD OBJECT", id)
|
||||
return {
|
||||
id,
|
||||
osmObj: "deleted",
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
const objects = osmObjects
|
||||
.filter((obj) => obj.osmObj !== "deleted")
|
||||
.map((obj) => <OsmObject>obj.osmObj)
|
||||
|
||||
const { toUpload, refused } = changesObj.fragmentChanges(e.pendingChanges, objects)
|
||||
|
||||
const changes: {
|
||||
newObjects: OsmObject[]
|
||||
modifiedObjects: OsmObject[]
|
||||
deletedObjects: OsmObject[]
|
||||
} = changesObj.CreateChangesetObjects(toUpload, objects, true)
|
||||
|
||||
const changeset = Changes.buildChangesetXML("", changes)
|
||||
const path =
|
||||
"error_changeset_" + parsed.index + "_" + e.layout + "_" + e.username + ".osc"
|
||||
if (
|
||||
changeset ===
|
||||
`<osmChange version='0.6' generator='Mapcomplete ${Constants.vNumber}'></osmChange>`
|
||||
) {
|
||||
/*console.log(
|
||||
"Changes for " + parsed.index + ": empty changeset, not creating a file for it"
|
||||
)*/
|
||||
} else if (createdChangesets.has(changeset)) {
|
||||
/* console.log(
|
||||
"Changeset " +
|
||||
parsed.index +
|
||||
" is identical to previously seen changeset, not writing to file"
|
||||
)*/
|
||||
} else {
|
||||
const changesetWithMsg = `<!-- User: ${parsed.message.username} (${parsed.message.userid}) ${parsed.message.layout}; Version ${parsed.message.version}; Not uploaded due to ${parsed.message.message} -->
|
||||
${changeset}`
|
||||
writeFileSync(path, changesetWithMsg, "utf8")
|
||||
createdChangesets.add(changeset)
|
||||
console.log("Written", path, "with " + e.pendingChanges.length + " changes")
|
||||
}
|
||||
const refusedContent = JSON.stringify(refused)
|
||||
if (refusedFiles.has(refusedContent)) {
|
||||
/* console.log(
|
||||
"Refused changes for " +
|
||||
parsed.index +
|
||||
" is identical to previously seen changeset, not writing to file"
|
||||
)*/
|
||||
} else {
|
||||
writeFileSync(path + ".refused.json", refusedContent, "utf8")
|
||||
refusedFiles.add(refusedContent)
|
||||
console.log("Written refused", path)
|
||||
}
|
||||
}
|
||||
|
||||
async main(args: string[]): Promise<void> {
|
||||
const osmConnection = new OsmConnection()
|
||||
const downloader = new OsmObjectDownloader(osmConnection.Backend(), undefined)
|
||||
|
@ -45,7 +130,7 @@ class HandleErrors extends Script {
|
|||
osmConnection,
|
||||
},
|
||||
false,
|
||||
(err) => console.error(err)
|
||||
(err) => console.error(err),
|
||||
)
|
||||
|
||||
const all: ErrorMessage[] = []
|
||||
|
@ -60,11 +145,14 @@ class HandleErrors extends Script {
|
|||
console.log("Skipping GRB ")
|
||||
continue
|
||||
}
|
||||
if (this.ignoreUsers.has(e.username)) {
|
||||
continue
|
||||
}
|
||||
for (const pendingChange of e.pendingChanges) {
|
||||
console.log(
|
||||
"\t https://osm.org/" + pendingChange.type + "/" + pendingChange.id,
|
||||
pendingChange.meta.changeType,
|
||||
pendingChange.doDelete ? "DELETE" : ""
|
||||
pendingChange.doDelete ? "DELETE" : "",
|
||||
)
|
||||
}
|
||||
all.push(parsed)
|
||||
|
@ -74,72 +162,11 @@ class HandleErrors extends Script {
|
|||
}
|
||||
|
||||
for (const parsed of all) {
|
||||
console.log(
|
||||
parsed.message.username,
|
||||
parsed.message.layout,
|
||||
parsed.message.message,
|
||||
parsed.date
|
||||
)
|
||||
|
||||
const e = parsed.message
|
||||
const neededIds = Changes.GetNeededIds(e.pendingChanges)
|
||||
// We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes
|
||||
const osmObjects: { id: string; osmObj: OsmObject | "deleted" }[] = await Promise.all<{
|
||||
id: string
|
||||
osmObj: OsmObject | "deleted"
|
||||
}>(
|
||||
neededIds.map(async (id) => ({
|
||||
id,
|
||||
osmObj: await downloader.DownloadObjectAsync(id),
|
||||
}))
|
||||
)
|
||||
|
||||
const objects = osmObjects
|
||||
.filter((obj) => obj.osmObj !== "deleted")
|
||||
.map((obj) => <OsmObject>obj.osmObj)
|
||||
|
||||
const { toUpload, refused } = changesObj.fragmentChanges(e.pendingChanges, objects)
|
||||
|
||||
const changes: {
|
||||
newObjects: OsmObject[]
|
||||
modifiedObjects: OsmObject[]
|
||||
deletedObjects: OsmObject[]
|
||||
} = changesObj.CreateChangesetObjects(toUpload, objects)
|
||||
|
||||
const changeset = Changes.createChangesetFor("", changes)
|
||||
const path =
|
||||
"error_changeset_" + parsed.index + "_" + e.layout + "_" + e.username + ".osc"
|
||||
if (
|
||||
changeset ===
|
||||
`<osmChange version='0.6' generator='Mapcomplete ${Constants.vNumber}'></osmChange>`
|
||||
) {
|
||||
/*console.log(
|
||||
"Changes for " + parsed.index + ": empty changeset, not creating a file for it"
|
||||
)*/
|
||||
} else if (createdChangesets.has(changeset)) {
|
||||
/* console.log(
|
||||
"Changeset " +
|
||||
parsed.index +
|
||||
" is identical to previously seen changeset, not writing to file"
|
||||
)*/
|
||||
} else {
|
||||
const changesetWithMsg = `<!-- User: ${parsed.message.username} (${parsed.message.userid}) ${parsed.message.layout}; Version ${parsed.message.version}; Not uploaded due to ${parsed.message.message} -->
|
||||
${changeset}`
|
||||
writeFileSync(path, changesetWithMsg, "utf8")
|
||||
createdChangesets.add(changeset)
|
||||
console.log("Written", path, "with " + e.pendingChanges.length + " changes")
|
||||
}
|
||||
const refusedContent = JSON.stringify(refused)
|
||||
if (refusedFiles.has(refusedContent)) {
|
||||
/* console.log(
|
||||
"Refused changes for " +
|
||||
parsed.index +
|
||||
" is identical to previously seen changeset, not writing to file"
|
||||
)*/
|
||||
} else {
|
||||
writeFileSync(path + ".refused.json", refusedContent, "utf8")
|
||||
refusedFiles.add(refusedContent)
|
||||
console.log("Written refused", path)
|
||||
try {
|
||||
await this.handleError(parsed, changesObj, downloader, createdChangesets, refusedFiles)
|
||||
} catch (e) {
|
||||
console.error("ERROR: could not handle ", parsed, " due to", e)
|
||||
writeFileSync("ERRORS."+parsed.index, "ERROR: due to " + e + ": could not handle\n" + JSON.stringify(parsed), "utf8")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,7 +313,7 @@ export default class CleanRepair extends Script {
|
|||
|
||||
const changedObjects = changes.CreateChangesetObjects(changesToMake, objects)
|
||||
|
||||
const osc = Changes.createChangesetFor("", changedObjects)
|
||||
const osc = Changes.buildChangesetXML("", changedObjects)
|
||||
|
||||
writeFileSync("Cleanup.osc", osc, "utf8")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue