forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
423618847b
334 changed files with 9307 additions and 6025 deletions
|
@ -55,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),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -82,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" +
|
||||
"|-"
|
||||
|
||||
|
@ -140,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(
|
||||
|
@ -166,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",
|
||||
|
@ -174,29 +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",
|
||||
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
|
||||
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"
|
||||
|
||||
]
|
||||
),
|
||||
].join("\n\n"),
|
||||
["./public/assets/data/editor-layer-index.json"]
|
||||
)
|
||||
|
||||
new WikiPageGenerator().generate()
|
||||
|
@ -244,7 +246,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")
|
||||
|
@ -253,7 +255,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",
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -287,7 +289,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`,
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -468,7 +470,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_",
|
||||
|
@ -488,7 +490,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",
|
||||
|
@ -568,10 +570,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",
|
||||
])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ class LayerOverviewUtils extends Script {
|
|||
return
|
||||
}
|
||||
|
||||
word = Utils.SubstituteKeys(word, {}).trim()
|
||||
word = Utils.SubstituteKeys(word, {})?.trim()
|
||||
if(!word){
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,17 +7,15 @@ export class GenerateSunnyUnlabeled extends Script {
|
|||
super("Generates 'sunny-unlabeled.json' based on sunny.json")
|
||||
}
|
||||
|
||||
|
||||
generateUnlabeled() {
|
||||
const unlabeled = { "#": "AUTOMATICALLY GENERATED! Do not edit.", ...sunny }
|
||||
unlabeled.name = unlabeled.name + "-unlabeled"
|
||||
unlabeled.layers = sunny.layers.filter(
|
||||
(l) => l.type !== "symbol" || !l.layout["text-field"],
|
||||
(l) => l.type !== "symbol" || !l.layout["text-field"]
|
||||
)
|
||||
writeFileSync("public/assets/sunny-unlabeled.json", JSON.stringify(unlabeled, null, " "))
|
||||
}
|
||||
|
||||
|
||||
async main(args: string[]): Promise<void> {
|
||||
this.generateUnlabeled()
|
||||
}
|
||||
|
|
|
@ -52,10 +52,10 @@ class TranslationPart {
|
|||
if (typeof v != "string") {
|
||||
console.error(
|
||||
`Non-string object at ${context} in translation while trying to add the translation ` +
|
||||
JSON.stringify(v) +
|
||||
` to '` +
|
||||
translationsKey +
|
||||
"'. The offending object which _should_ be a translation is: ",
|
||||
JSON.stringify(v) +
|
||||
` to '` +
|
||||
translationsKey +
|
||||
"'. The offending object which _should_ be a translation is: ",
|
||||
v,
|
||||
"\n\nThe current object is (only showing en):",
|
||||
this.toJson(),
|
||||
|
@ -94,9 +94,9 @@ class TranslationPart {
|
|||
if (noTranslate !== undefined) {
|
||||
console.log(
|
||||
"Ignoring some translations for " +
|
||||
context +
|
||||
": " +
|
||||
dontTranslateKeys.join(", ")
|
||||
context +
|
||||
": " +
|
||||
dontTranslateKeys.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class TranslationPart {
|
|||
this.contents.set(key, new TranslationPart())
|
||||
}
|
||||
|
||||
(this.contents.get(key) as TranslationPart).recursiveAdd(v, context + "." + key)
|
||||
;(this.contents.get(key) as TranslationPart).recursiveAdd(v, context + "." + key)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ class TranslationPart {
|
|||
let value = this.contents.get(key)
|
||||
|
||||
if (typeof value === "string") {
|
||||
value = value.replace(/"/g, "\\\"").replace(/\n/g, "\\n")
|
||||
value = value.replace(/"/g, '\\"').replace(/\n/g, "\\n")
|
||||
if (neededLanguage === undefined) {
|
||||
parts.push(`"${key}": "${value}"`)
|
||||
} else if (key === neededLanguage) {
|
||||
|
@ -229,7 +229,7 @@ class TranslationPart {
|
|||
} else if (!isLeaf) {
|
||||
errors.push({
|
||||
error: "Mixed node: non-leaf node has translation strings",
|
||||
path: path
|
||||
path: path,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ class TranslationPart {
|
|||
value +
|
||||
"\n" +
|
||||
fixLink,
|
||||
path: path
|
||||
path: path,
|
||||
})
|
||||
}
|
||||
return
|
||||
|
@ -292,7 +292,7 @@ class TranslationPart {
|
|||
error: `The translation for ${key} does not have the required subpart ${part} (in ${usedByLanguage}).
|
||||
\tThe full translation is ${value}
|
||||
\t${fixLink}`,
|
||||
path: path
|
||||
path: path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,6 @@ class TranslationPart {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a translation object into something that can be added to the 'generated translations'.
|
||||
*
|
||||
|
@ -373,9 +372,7 @@ function transformTranslation(
|
|||
)}.${key}\n\tThe translations in other languages are ${JSON.stringify(value)}`
|
||||
}
|
||||
const subParts: string[] = value["en"].match(/{[^}]*}/g)
|
||||
let expr = `new Translation(${JSON.stringify(value)}, "core:${path.join(
|
||||
"."
|
||||
)}.${key}")`
|
||||
let expr = `new Translation(${JSON.stringify(value)}, "core:${path.join(".")}.${key}")`
|
||||
if (subParts !== null) {
|
||||
// convert '{to_substitute}' into 'to_substitute'
|
||||
const types = Utils.Dedup(subParts.map((tp) => tp.substring(1, tp.length - 1)))
|
||||
|
@ -393,7 +390,6 @@ function transformTranslation(
|
|||
}
|
||||
if (shortNotation) {
|
||||
values.push(`${spaces} ${key}: ${expr}`)
|
||||
|
||||
} else {
|
||||
values.push(`${spaces}get ${key}() { return ${expr} }`)
|
||||
}
|
||||
|
@ -423,26 +419,29 @@ function stringifySorted(o: object, space: string = undefined, depth = 0): strin
|
|||
const keys = Object.keys(o)
|
||||
let obj = "{"
|
||||
|
||||
obj += keys.sort().map(key => {
|
||||
const v = o[key]
|
||||
let r = ""
|
||||
if (space !== undefined) {
|
||||
r += "\n"
|
||||
for (let i = 0; i <= depth; i++) {
|
||||
r += space
|
||||
obj += keys
|
||||
.sort()
|
||||
.map((key) => {
|
||||
const v = o[key]
|
||||
let r = ""
|
||||
if (space !== undefined) {
|
||||
r += "\n"
|
||||
for (let i = 0; i <= depth; i++) {
|
||||
r += space
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r += JSON.stringify("" + key) + ": "
|
||||
if (typeof v === "object") {
|
||||
r += stringifySorted(v, space, depth + 1)
|
||||
} else if (Array.isArray(v)) {
|
||||
r += "[" + v.map(v_ => stringifySorted(v_, space, depth + 1)).join(",") + "]"
|
||||
} else {
|
||||
r += JSON.stringify(v)
|
||||
}
|
||||
return r
|
||||
}).join(",")
|
||||
r += JSON.stringify("" + key) + ": "
|
||||
if (typeof v === "object") {
|
||||
r += stringifySorted(v, space, depth + 1)
|
||||
} else if (Array.isArray(v)) {
|
||||
r += "[" + v.map((v_) => stringifySorted(v_, space, depth + 1)).join(",") + "]"
|
||||
} else {
|
||||
r += JSON.stringify(v)
|
||||
}
|
||||
return r
|
||||
})
|
||||
.join(",")
|
||||
if (space !== undefined) {
|
||||
obj += "\n"
|
||||
for (let i = 0; i < depth; i++) {
|
||||
|
@ -477,7 +476,6 @@ function formatFile(path) {
|
|||
writeFileSync(path, contents)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads 'lang/*.json', writes them into to 'assets/generated/translations.json'.
|
||||
* This is only for the core translations
|
||||
|
@ -662,7 +660,9 @@ function removeNonEnglishTranslations(object: any) {
|
|||
leaf["en"] = en
|
||||
},
|
||||
(possibleLeaf) =>
|
||||
possibleLeaf !== null && typeof possibleLeaf === "object" && GenerateTranslations.isTranslation(possibleLeaf)
|
||||
possibleLeaf !== null &&
|
||||
typeof possibleLeaf === "object" &&
|
||||
GenerateTranslations.isTranslation(possibleLeaf)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -738,7 +738,6 @@ class GenerateTranslations extends Script {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the big compiledTranslations file based on 'translations.json'
|
||||
*/
|
||||
|
@ -749,7 +748,12 @@ class GenerateTranslations extends Script {
|
|||
const translations = JSON.parse(
|
||||
fs.readFileSync("./src/assets/generated/translations.json", "utf-8")
|
||||
)
|
||||
const transformed = transformTranslation(translations, undefined, englishOnly ? ["en"] : undefined, englishOnly)
|
||||
const transformed = transformTranslation(
|
||||
translations,
|
||||
undefined,
|
||||
englishOnly ? ["en"] : undefined,
|
||||
englishOnly
|
||||
)
|
||||
|
||||
let module = `import {Translation, TypedTranslation} from "../../UI/i18n/Translation"\n\nexport default class CompiledTranslations {\n\n`
|
||||
module += " public static t = " + transformed
|
||||
|
|
|
@ -31,12 +31,18 @@ class HandleErrors extends Script {
|
|||
|
||||
private readonly ignoreUsers = new Set<string>([])
|
||||
|
||||
private async handleError(parsed: ErrorMessage, changesObj: Changes, downloader: OsmObjectDownloader, createdChangesets: Set<string>, refusedFiles: 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,
|
||||
parsed.date
|
||||
)
|
||||
|
||||
const e = parsed.message
|
||||
|
@ -48,12 +54,11 @@ class HandleErrors extends Script {
|
|||
}>(
|
||||
neededIds.map(async (id) => {
|
||||
try {
|
||||
|
||||
const osmObj = await downloader.DownloadObjectAsync(id)
|
||||
return ({
|
||||
return {
|
||||
id,
|
||||
osmObj,
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("COULD NOT DOWNLOAD OBJECT", id)
|
||||
return {
|
||||
|
@ -61,7 +66,7 @@ class HandleErrors extends Script {
|
|||
osmObj: "deleted",
|
||||
}
|
||||
}
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
const objects = osmObjects
|
||||
|
@ -77,8 +82,7 @@ class HandleErrors extends Script {
|
|||
} = changesObj.CreateChangesetObjects(toUpload, objects, true)
|
||||
|
||||
const changeset = Changes.buildChangesetXML("", changes)
|
||||
const path =
|
||||
"error_changeset_" + parsed.index + "_" + e.layout + "_" + e.username + ".osc"
|
||||
const path = "error_changeset_" + parsed.index + "_" + e.layout + "_" + e.username + ".osc"
|
||||
if (
|
||||
changeset ===
|
||||
`<osmChange version='0.6' generator='Mapcomplete ${Constants.vNumber}'></osmChange>`
|
||||
|
@ -130,7 +134,7 @@ ${changeset}`
|
|||
osmConnection,
|
||||
},
|
||||
false,
|
||||
(err) => console.error(err),
|
||||
(err) => console.error(err)
|
||||
)
|
||||
|
||||
const all: ErrorMessage[] = []
|
||||
|
@ -152,7 +156,7 @@ ${changeset}`
|
|||
console.log(
|
||||
"\t https://osm.org/" + pendingChange.type + "/" + pendingChange.id,
|
||||
pendingChange.meta.changeType,
|
||||
pendingChange.doDelete ? "DELETE" : "",
|
||||
pendingChange.doDelete ? "DELETE" : ""
|
||||
)
|
||||
}
|
||||
all.push(parsed)
|
||||
|
@ -163,10 +167,20 @@ ${changeset}`
|
|||
|
||||
for (const parsed of all) {
|
||||
try {
|
||||
await this.handleError(parsed, changesObj, downloader, createdChangesets, refusedFiles)
|
||||
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")
|
||||
writeFileSync(
|
||||
"ERRORS." + parsed.index,
|
||||
"ERROR: due to " + e + ": could not handle\n" + JSON.stringify(parsed),
|
||||
"utf8"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ import { OsmPoiDatabase } from "./osmPoiDatabase"
|
|||
|
||||
class CreateNewDatabase extends Script {
|
||||
constructor() {
|
||||
super("Creates a new version of the database. Usage: `createNewDatabase -- YYYY-MM-DD` which will create database `osm-poi.YYYY-MM-DD`")
|
||||
super(
|
||||
"Creates a new version of the database. Usage: `createNewDatabase -- YYYY-MM-DD` which will create database `osm-poi.YYYY-MM-DD`"
|
||||
)
|
||||
}
|
||||
|
||||
async main(args: string[]): Promise<void> {
|
||||
|
@ -12,5 +14,4 @@ class CreateNewDatabase extends Script {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
new CreateNewDatabase().run()
|
||||
|
|
|
@ -12,5 +12,4 @@ class DeleteOldDbs extends Script {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
new DeleteOldDbs().run()
|
||||
|
|
|
@ -68,7 +68,6 @@ export class OsmPoiDatabase {
|
|||
const metaclient = this.getMetaClient()
|
||||
await metaclient.connect()
|
||||
try {
|
||||
|
||||
const meta = await metaclient.query("SELECT datname FROM pg_database")
|
||||
let latest: string = undefined
|
||||
let latestDate: Date = new Date(0)
|
||||
|
@ -104,7 +103,7 @@ export class OsmPoiDatabase {
|
|||
}
|
||||
|
||||
console.log("Latest database is:", latest)
|
||||
return "osm-poi."+latest
|
||||
return "osm-poi." + latest
|
||||
}
|
||||
|
||||
async createNew(date: string) {
|
||||
|
@ -113,7 +112,6 @@ export class OsmPoiDatabase {
|
|||
const metaclient = this.getMetaClient()
|
||||
await metaclient.connect()
|
||||
try {
|
||||
|
||||
await metaclient.query(`CREATE DATABASE "${dbname}"`)
|
||||
console.log("Database created - installing extensions")
|
||||
const client = new Client(this._connectionString + "/" + dbname)
|
||||
|
@ -129,7 +127,7 @@ export class OsmPoiDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
async deleteAllButLatest(){
|
||||
async deleteAllButLatest() {
|
||||
const dbs = await this.findSuitableDatabases()
|
||||
for (let i = 0; i < dbs.length - 1; i++) {
|
||||
await this.deleteDatabase(dbs[i])
|
||||
|
@ -152,7 +150,6 @@ export class OsmPoiDatabase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
async connectToLatest() {
|
||||
const latest = await this.searchLatest()
|
||||
this._client = new Client(this._connectionString + "/" + latest)
|
||||
|
@ -161,7 +158,7 @@ export class OsmPoiDatabase {
|
|||
|
||||
async getCount(
|
||||
layer: string,
|
||||
bbox: [[number, number], [number, number]] = undefined,
|
||||
bbox: [[number, number], [number, number]] = undefined
|
||||
): Promise<{ count: number; lat: number; lon: number }> {
|
||||
await this.connectIfNeeded()
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Server } from "../server"
|
|||
import Script from "../Script"
|
||||
import { OsmPoiDatabase } from "./osmPoiDatabase"
|
||||
|
||||
|
||||
class CachedSqlCount {
|
||||
private readonly _cache: Record<
|
||||
string,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue