Merge master

This commit is contained in:
Pieter Vander Vennet 2024-07-28 02:38:24 +02:00
commit 1b01f75905
186 changed files with 4169 additions and 2235 deletions

View file

@ -41,7 +41,7 @@ export abstract class Conversion<TIn, TOut> {
fixed = this.convert(json, context)
} catch (e) {
console.error(e)
context.err("ERROR WHILE RUNNING STEP " + this.name+": "+e)
context.err("ERROR WHILE RUNNING STEP " + this.name + ": " + e)
fixed = undefined
}
for (const msg of context.messages) {
@ -54,12 +54,11 @@ export abstract class Conversion<TIn, TOut> {
throw new Error(
[
"Detected one or more errors, stopping now:",
context.getAll("error").map((e) => e.context.path.join(".") + ": " + e.message)
context.getAll("error").map((e) => e.context.path.join(".") + ": " + e.message),
].join("\n\t")
)
}
return fixed
}
public andThenF<X>(f: (tout: TOut) => X): Conversion<TIn, X> {
@ -69,8 +68,7 @@ export abstract class Conversion<TIn, TOut> {
public abstract convert(json: TIn, context: ConversionContext): TOut
}
export abstract class DesugaringStep<T> extends Conversion<T, T> {
}
export abstract class DesugaringStep<T> extends Conversion<T, T> {}
export class Pipe<TIn, TInter, TOut> extends Conversion<TIn, TOut> {
private readonly _step0: Conversion<TIn, TInter>
@ -257,7 +255,7 @@ export class Cached<TIn, TOut> extends Conversion<TIn, TOut> {
const converted = this._step.convert(json, context)
Object.defineProperty(json, this.key, {
value: converted,
enumerable: false
enumerable: false,
})
return converted
}
@ -270,8 +268,8 @@ export class Fuse<T> extends DesugaringStep<T> {
constructor(doc: string, ...steps: DesugaringStep<T>[]) {
super(
(doc ?? "") +
"This fused pipeline of the following steps: " +
steps.map((s) => s.name).join(", "),
"This fused pipeline of the following steps: " +
steps.map((s) => s.name).join(", "),
Utils.Dedup([].concat(...steps.map((step) => step.modifiedAttributes))),
"Fuse(" + steps.map((s) => s.name).join(", ") + ")"
)

View file

@ -55,13 +55,12 @@ export class ExtractImages extends Conversion<
}
static isImageType(metapath: any): boolean {
if (metapath.hints.typehint === "icon" ||
metapath.hints.typehint === "image") {
if (metapath.hints.typehint === "icon" || metapath.hints.typehint === "image") {
return true
}
const types = metapath.hints.types?.split(";").map(x => x.trim())
if (types?.some(t => t === "icon" || t === "image")) {
const types = metapath.hints.types?.split(";").map((x) => x.trim())
if (types?.some((t) => t === "icon" || t === "image")) {
return true
}
@ -120,7 +119,7 @@ export class ExtractImages extends Conversion<
const allRenderedValuesAreImages = ExtractImages.isImageType(metapath)
const found = Utils.CollectPath(metapath.path, json)
if(found.length === 0){
if (found.length === 0) {
continue
}
@ -177,7 +176,7 @@ export class ExtractImages extends Conversion<
} else {
allFoundImages.push({
path: img.leaf,
context: context + "." + path
context: context + "." + path,
})
}
}
@ -191,7 +190,7 @@ export class ExtractImages extends Conversion<
.ExtractImages(false)
.map((path) => ({
path,
context: context + "." + path
context: context + "." + path,
}))
)
}
@ -211,7 +210,7 @@ export class ExtractImages extends Conversion<
}
allFoundImages.push({
context: context.path.join(".") + "." + foundElement.path.join("."),
path: foundElement.leaf
path: foundElement.leaf,
})
}
}

View file

@ -7,10 +7,13 @@ import {
FirstOf,
Fuse,
On,
SetDefault
SetDefault,
} from "./Conversion"
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { MinimalTagRenderingConfigJson, TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import {
MinimalTagRenderingConfigJson,
TagRenderingConfigJson,
} from "../Json/TagRenderingConfigJson"
import { Utils } from "../../../Utils"
import RewritableConfigJson from "../Json/RewritableConfigJson"
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
@ -63,24 +66,27 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
const newFilters: FilterConfigJson[] = []
const filters = <(FilterConfigJson | string)[]>json.filter
for (let i = 0; i < json.tagRenderings?.length; i++){
const tagRendering = <TagRenderingConfigJson> json.tagRenderings[i]
if(!tagRendering?.filter){
for (let i = 0; i < json.tagRenderings?.length; i++) {
const tagRendering = <TagRenderingConfigJson>json.tagRenderings[i]
if (!tagRendering?.filter) {
continue
}
for (const filterName of tagRendering.filter ?? []) {
if(typeof filterName !== "string"){
context.enters("tagRenderings",i,"filter").err("Not a string: "+ filterName)
if (typeof filterName !== "string") {
context.enters("tagRenderings", i, "filter").err("Not a string: " + filterName)
}
const exists = filters.some(existing => {
const id : string = existing["id"] ?? existing
return filterName === id || (filterName.startsWith("filters.") && filterName.endsWith("."+id))
const exists = filters.some((existing) => {
const id: string = existing["id"] ?? existing
return (
filterName === id ||
(filterName.startsWith("filters.") && filterName.endsWith("." + id))
)
})
if(exists){
if (exists) {
continue
}
if(!filterName){
context.err("Got undefined as filter expansion in "+tagRendering["id"])
if (!filterName) {
context.err("Got undefined as filter expansion in " + tagRendering["id"])
continue
}
filters.push(filterName)
@ -89,7 +95,7 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
for (let i = 0; i < filters.length; i++) {
const filter = filters[i]
if(filter === undefined){
if (filter === undefined) {
continue
}
if (typeof filter !== "string") {
@ -141,9 +147,9 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
const expandedFilter = (<(FilterConfigJson | string)[]>layer.filter).find(
(f) => typeof f !== "string" && f.id === expectedId
)
if(expandedFilter === undefined){
context.err("Did not find filter with name "+filter)
}else{
if (expandedFilter === undefined) {
context.err("Did not find filter with name " + filter)
} else {
newFilters.push(<FilterConfigJson>expandedFilter)
}
} else {
@ -644,7 +650,6 @@ export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
}
export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
private readonly _desugaring: DesugaringContext
private readonly _addedByDefaultAtTop: QuestionableTagRenderingConfigJson[]
private readonly _addedByDefault: QuestionableTagRenderingConfigJson[]
@ -669,7 +674,6 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
return Utils.NoNull(idsInOrder.map((id) => this._desugaring.tagRenderings.get(id)))
}
convert(json: LayerConfigJson, _: ConversionContext): LayerConfigJson {
if (this._desugaring.tagRenderings === null) {
return json
@ -734,7 +738,7 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
const trc: QuestionableTagRenderingConfigJson = {
id: "all-tags",
render: { "*": "{all_tags()}" },
labels:["ignore_docs"],
labels: ["ignore_docs"],
metacondition: {
or: [
"__featureSwitchIsDebugging=true",

View file

@ -71,8 +71,8 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
for (const name of names) {
const found = Utils.Clone(state.sharedLayers.get(name))
if(found === undefined){
context.err("Layer with name "+name+" not found")
if (found === undefined) {
context.err("Layer with name " + name + " not found")
continue
}
found["_basedOn"] = name
@ -393,7 +393,6 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
}[] = []
for (const layerConfig of alreadyLoaded) {
try {
const layerDeps = DependencyCalculator.getLayerDependencies(
new LayerConfig(layerConfig, themeId + "(dependencies)")
@ -402,7 +401,10 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
} catch (e) {
console.error(e)
throw (
"Detecting layer dependencies for " + layerConfig?.id + " failed due to " + e
"Detecting layer dependencies for " +
layerConfig?.id +
" failed due to " +
e
)
}
}

View file

@ -1773,7 +1773,7 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
// Calling another filter, we skip
return filter
}
if(filter === undefined){
if (filter === undefined) {
context.err("Trying to validate a filter, but this filter is undefined")
return undefined
}
@ -2002,7 +2002,7 @@ export class ValidateThemeEnsemble extends Conversion<
>()
for (const theme of json) {
if(theme.id === "personal"){
if (theme.id === "personal") {
continue
}
for (const layer of theme.layers) {

View file

@ -25,11 +25,13 @@ export default class FilterConfig {
public readonly defaultSelection?: number
constructor(json: FilterConfigJson, context: string) {
if(typeof json === "string"){
throw "Got a non-expanded filter, just a string: "+json
if (typeof json === "string") {
throw "Got a non-expanded filter, just a string: " + json
}
if (json.options === undefined) {
throw `A filter without options was given at ${context}. The ID is ${JSON.stringify(json)}`
throw `A filter without options was given at ${context}. The ID is ${JSON.stringify(
json
)}`
}
if (json.id === undefined) {
throw `A filter without id was found at ${context}`
@ -209,16 +211,16 @@ export default class FilterConfig {
Utils.NoNull(["id", "question", "osmTags", hasField ? "fields" : undefined]),
this.options.map((opt, i) => {
const isDefault = this.options.length > 1 && (this.defaultSelection ?? 0) == i
return <string[]> Utils.NoNull([
this.id + "." + i,
isDefault
? `*${opt.question.txt}* (default)`
: opt.question,
opt.osmTags?.asHumanString() ?? "",
opt.fields?.length > 0
? (opt.fields.map((f) => f.name + " (" + f.type + ")")).join(" ")
: undefined,
])
return <string[]>(
Utils.NoNull([
this.id + "." + i,
isDefault ? `*${opt.question.txt}* (default)` : opt.question,
opt.osmTags?.asHumanString() ?? "",
opt.fields?.length > 0
? opt.fields.map((f) => f.name + " (" + f.type + ")").join(" ")
: undefined,
])
)
})
)
}

View file

@ -93,7 +93,7 @@ export default class LayerConfig extends WithContextLoader {
overpassScript: json.source["overpassScript"],
isOsmCache: json.source["isOsmCache"],
mercatorCrs: json.source["mercatorCrs"],
idKey: json.source["idKey"]
idKey: json.source["idKey"],
},
json.id
)
@ -162,7 +162,7 @@ export default class LayerConfig extends WithContextLoader {
let preciseInput: PreciseInput = {
preferredBackground: ["photo"],
snapToLayers: undefined,
maxSnapDistance: undefined
maxSnapDistance: undefined,
}
if (pr["preciseInput"] !== undefined) {
throw (
@ -175,7 +175,7 @@ export default class LayerConfig extends WithContextLoader {
let snapToLayers = pr.snapToLayer
preciseInput = {
snapToLayers,
maxSnapDistance: pr.maxSnapDistance ?? 10
maxSnapDistance: pr.maxSnapDistance ?? 10,
}
}
@ -187,7 +187,7 @@ export default class LayerConfig extends WithContextLoader {
`${translationContext}.presets.${i}.description`
),
preciseInput: preciseInput,
exampleImages: pr.exampleImages
exampleImages: pr.exampleImages,
}
return config
})
@ -293,10 +293,10 @@ export default class LayerConfig extends WithContextLoader {
this.filters = []
} else {
this.filters = (<FilterConfigJson[]>json.filter ?? [])
.filter(f => typeof f !== "string")
.filter((f) => typeof f !== "string")
.map((option, i) => {
return new FilterConfig(option, `layers:${this.id}.filter.${i}`)
})
return new FilterConfig(option, `layers:${this.id}.filter.${i}`)
})
}
{
@ -311,7 +311,7 @@ export default class LayerConfig extends WithContextLoader {
}
this.titleIcons = this.ParseTagRenderings(<TagRenderingConfigJson[]>json.titleIcons ?? [], {
readOnlyMode: true
readOnlyMode: true,
})
this.title = this.tr("title", undefined, translationContext)
@ -412,7 +412,7 @@ export default class LayerConfig extends WithContextLoader {
[
"<img src='../warning.svg' height='1rem'/>",
"This layer is loaded from an external source, namely ",
"`" + this.source.geojsonSource + "`"
"`" + this.source.geojsonSource + "`",
].join("\n\n")
)
}
@ -428,10 +428,8 @@ export default class LayerConfig extends WithContextLoader {
usingLayer = [
"## Themes using this layer",
MarkdownUtils.list(
(usedInThemes ?? []).map(
(id) => (`[${id}](https://mapcomplete.org/${id})`)
)
)
(usedInThemes ?? []).map((id) => `[${id}](https://mapcomplete.org/${id})`)
),
]
} else if (this.source !== null) {
usingLayer = ["No themes use this layer"]
@ -442,45 +440,46 @@ export default class LayerConfig extends WithContextLoader {
extraProps.push(
[
"This layer will automatically load ",
(`[${dep.neededLayer}](./${dep.neededLayer}.md)`),
`[${dep.neededLayer}](./${dep.neededLayer}.md)`,
" into the layout as it depends on it: ",
dep.reason,
"(" + dep.context + ")"
"(" + dep.context + ")",
].join(" ")
)
}
for (const revDep of Utils.Dedup(layerIsNeededBy?.get(this.id) ?? [])) {
extraProps.push(
[
"This layer is needed as dependency for layer",
(`[${revDep}](#${revDep})`)
].join(" ")
["This layer is needed as dependency for layer", `[${revDep}](#${revDep})`].join(
" "
)
)
}
const tableRows: string[][] = Utils.NoNull(
this.tagRenderings
.map((tr) => tr.FreeformValues())
.filter(values => values !== undefined)
.filter(values => values.key !== "id")
.filter((values) => values !== undefined)
.filter((values) => values.key !== "id")
.map((values) => {
const embedded: (string)[] = values.values?.map((v) =>
const embedded: string[] = values.values?.map((v) =>
Link.OsmWiki(values.key, v, true).SetClass("mr-2").AsMarkdown()
) ?? ["_no preset options defined, or no values in them_"]
const statistics = `https://taghistory.raifer.tech/?#***/${encodeURIComponent(values.key)}/`
const statistics = `https://taghistory.raifer.tech/?#***/${encodeURIComponent(
values.key
)}/`
const tagInfo = `https://taginfo.openstreetmap.org/keys/${values.key}#values`
return [
[
`<a target="_blank" href='${tagInfo}'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a>`,
`<a target="_blank" href='${statistics}'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a>`,
Link.OsmWiki(values.key).AsMarkdown()
Link.OsmWiki(values.key).AsMarkdown(),
].join(" "),
values.type === undefined
? "Multiple choice"
: `[${values.type}](../SpecialInputElements.md#${values.type})`,
embedded.join(" ")
embedded.join(" "),
]
})
)
@ -488,31 +487,30 @@ export default class LayerConfig extends WithContextLoader {
let quickOverview: string[] = []
if (tableRows.length > 0) {
quickOverview = [
("**Warning:**"),
"**Warning:**",
"this quick overview is incomplete",
MarkdownUtils.table(
["attribute", "type", "values which are supported by this layer"],
tableRows
)
),
]
}
let overpassLink: string = undefined
if (this.source !== undefined) {
try {
overpassLink = (
overpassLink =
"[Execute on overpass](" +
Overpass.AsOverpassTurboLink(<TagsFilter>this.source.osmTags.optimize())
.replaceAll("(", "%28")
.replaceAll(")", "%29")
+ ")"
)
.replaceAll(")", "%29") +
")"
} catch (e) {
console.error("Could not generate overpasslink for " + this.id)
}
}
const filterDocs: (string)[] = []
const filterDocs: string[] = []
if (this.filters.length > 0) {
filterDocs.push("## Filters")
filterDocs.push(...this.filters.map((filter) => filter.GenerateDocs()))
@ -538,8 +536,8 @@ export default class LayerConfig extends WithContextLoader {
} else {
tagsDescription.push(
"Elements must match the expression **" +
neededTags.asHumanString(true, false, {}) +
"**"
neededTags.asHumanString(true, false, {}) +
"**"
)
}
@ -551,17 +549,21 @@ export default class LayerConfig extends WithContextLoader {
return [
[
"# " + this.id + "\n",
this._basedOn ? `This layer is based on [${this._basedOn}](../Layers/${this._basedOn}.md)` : "",
this.description, "\n"].join("\n\n"),
this._basedOn
? `This layer is based on [${this._basedOn}](../Layers/${this._basedOn}.md)`
: "",
this.description,
"\n",
].join("\n\n"),
MarkdownUtils.list(extraProps),
...usingLayer,
...tagsDescription,
"## Supported attributes",
quickOverview,
...this.tagRenderings
.filter(tr => tr.labels.indexOf("ignore_docs") < 0)
.filter((tr) => tr.labels.indexOf("ignore_docs") < 0)
.map((tr) => tr.GenerateDocumentation()),
...filterDocs
...filterDocs,
].join("\n\n")
}

View file

@ -8,7 +8,7 @@ import { Tag } from "../../Logic/Tags/Tag"
import Link from "../../UI/Base/Link"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson
QuestionableTagRenderingConfigJson,
} from "./Json/QuestionableTagRenderingConfigJson"
import Validators, { ValidatorType } from "../../UI/InputElement/Validators"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
@ -204,7 +204,7 @@ export default class TagRenderingConfig {
inline: json.freeform.inline ?? false,
default: json.freeform.default,
postfixDistinguished: json.freeform.postfixDistinguished?.trim(),
args: json.freeform.helperArgs
args: json.freeform.helperArgs,
}
if (json.freeform["extraTags"] !== undefined) {
throw `Freeform.extraTags is defined. This should probably be 'freeform.addExtraTag' (at ${context})`
@ -424,7 +424,7 @@ export default class TagRenderingConfig {
iconClass,
addExtraTags,
searchTerms: mapping.searchTerms,
priorityIf: prioritySearch
priorityIf: prioritySearch,
}
if (isQuestionable) {
if (hideInAnswer !== true && mp.if !== undefined && !mp.if.isUsableAsAnswer()) {
@ -525,7 +525,7 @@ export default class TagRenderingConfig {
then: new TypedTranslation<object>(
this.render.replace("{" + this.freeform.key + "}", leftover).translations,
this.render.context
)
),
})
}
}
@ -575,7 +575,7 @@ export default class TagRenderingConfig {
return {
then: this.render.PartialSubs({ [this.freeform.key]: v.trim() }),
icon: this.renderIcon,
iconClass: this.renderIconClass
iconClass: this.renderIconClass,
}
}
}
@ -630,7 +630,7 @@ export default class TagRenderingConfig {
key: commonKey,
values: Utils.NoNull(
values.map((arr) => arr.filter((item) => item.k === commonKey)[0]?.v)
)
),
}
}
@ -645,7 +645,7 @@ export default class TagRenderingConfig {
return {
key,
type: this.freeform.type,
values
values,
}
} catch (e) {
console.error("Could not create FreeformValues for tagrendering", this.id)
@ -751,7 +751,7 @@ export default class TagRenderingConfig {
// Either no mappings, or this is a radio-button selected freeform value
const tag = new And([
new Tag(this.freeform.key, freeformValue),
...(this.freeform.addExtraTags ?? [])
...(this.freeform.addExtraTags ?? []),
])
const newProperties = tag.applyOn(currentProperties)
if (this.invalidValues?.matchesProperties(newProperties)) {
@ -775,7 +775,7 @@ export default class TagRenderingConfig {
selectedMappings.push(
new And([
new Tag(this.freeform.key, freeformValue),
...(this.freeform.addExtraTags ?? [])
...(this.freeform.addExtraTags ?? []),
])
)
}
@ -803,12 +803,12 @@ export default class TagRenderingConfig {
if (useFreeform) {
return new And([
new Tag(this.freeform.key, freeformValue),
...(this.freeform.addExtraTags ?? [])
...(this.freeform.addExtraTags ?? []),
])
} else if (singleSelectedMapping !== undefined) {
return new And([
this.mappings[singleSelectedMapping].if,
...(this.mappings[singleSelectedMapping].addExtraTags ?? [])
...(this.mappings[singleSelectedMapping].addExtraTags ?? []),
])
} else {
console.error("TagRenderingConfig.ConstructSpecification has a weird fallback for", {
@ -816,7 +816,7 @@ export default class TagRenderingConfig {
singleSelectedMapping,
multiSelectedMapping,
currentProperties,
useFreeform
useFreeform,
})
return undefined
@ -846,11 +846,11 @@ export default class TagRenderingConfig {
}
const msgs: string[] = [
icon +
" " +
"*" +
m.then.textFor(lang) +
"* is shown if with " +
m.if.asHumanString(true, false, {})
" " +
"*" +
m.then.textFor(lang) +
"* is shown if with " +
m.if.asHumanString(true, false, {}),
]
if (m.hideInAnswer === true) {
@ -859,7 +859,7 @@ export default class TagRenderingConfig {
if (m.ifnot !== undefined) {
msgs.push(
"Unselecting this answer will add " +
m.ifnot.asHumanString(true, false, {})
m.ifnot.asHumanString(true, false, {})
)
}
return msgs.join(". ")
@ -883,7 +883,7 @@ export default class TagRenderingConfig {
if (this.labels?.length > 0) {
labels = [
"This tagrendering has labels ",
...this.labels.map((label) => "`" + label + "`")
...this.labels.map((label) => "`" + label + "`"),
].join("\n")
}
@ -896,15 +896,13 @@ export default class TagRenderingConfig {
freeform,
mappings,
condition,
labels
labels,
].join("\n")
}
public
usedTags()
:
TagsFilter[] {
usedTags(): TagsFilter[] {
const tags: TagsFilter[] = []
tags.push(
this.metacondition,
@ -932,9 +930,7 @@ export default class TagRenderingConfig {
*/
public
settableKeys()
:
string[] | undefined {
settableKeys(): string[] | undefined {
const toDelete = new Set<string>()
if (this.freeform) {
toDelete.add(this.freeform.key)
@ -983,7 +979,7 @@ export class TagRenderingConfigUtils {
const oldMappingsCloned =
clone.mappings?.map((m) => ({
...m,
priorityIf: m.priorityIf ?? TagUtils.Tag("id~*")
priorityIf: m.priorityIf ?? TagUtils.Tag("id~*"),
})) ?? []
clone.mappings = [...oldMappingsCloned, ...extraMappings]
return clone

View file

@ -161,7 +161,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.featureSwitches = new FeatureSwitchState(layout)
this.guistate = new MenuState(
this.featureSwitches.featureSwitchWelcomeMessage.data,
layout.id,
layout.id
)
this.map = new UIEventSource<MlMap>(undefined)
const geolocationState = new GeoLocationState()
@ -177,14 +177,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
oauth_token: QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login",
"Used to complete the login"
),
})
this.userRelatedState = new UserRelatedState(
this.osmConnection,
layout,
this.featureSwitches,
this.mapProperties,
this.mapProperties
)
this.userRelatedState.fixateNorth.addCallbackAndRunD((fixated) => {
this.mapProperties.allowRotating.setData(fixated !== "yes")
@ -195,13 +195,13 @@ export default class ThemeViewState implements SpecialVisualizationState {
geolocationState,
this.selectedElement,
this.mapProperties,
this.userRelatedState.gpsLocationHistoryRetentionTime,
this.userRelatedState.gpsLocationHistoryRetentionTime
)
this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties)
this.availableLayers = AvailableRasterLayers.layersAvailableAt(
this.mapProperties.location,
this.osmConnection.isLoggedIn,
this.osmConnection.isLoggedIn
)
const self = this
@ -209,7 +209,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.osmConnection,
layout.layers,
layout.id,
this.featureSwitches.featureSwitchLayerDefault,
this.featureSwitches.featureSwitchLayerDefault
)
{
@ -218,7 +218,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const isDisplayed = QueryParameters.GetBooleanQueryParameter(
"overlay-" + rasterInfo.id,
rasterInfo.defaultState ?? true,
"Whether or not overlay layer " + rasterInfo.id + " is shown",
"Whether or not overlay layer " + rasterInfo.id + " is shown"
)
const state = { isDisplayed }
overlayLayerStates.set(rasterInfo.id, state)
@ -243,7 +243,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.osmConnection.Backend(),
(id) => self.layerState.filteredLayers.get(id).isDisplayed,
mvtAvailableLayers,
this.fullNodeDatabase,
this.fullNodeDatabase
)
let currentViewIndex = 0
@ -261,7 +261,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
id: "current_view_" + currentViewIndex,
}),
]
}),
})
)
this.featuresInView = new BBoxFeatureSource(layoutSource, this.mapProperties.bounds)
@ -279,19 +279,19 @@ export default class ThemeViewState implements SpecialVisualizationState {
featureSwitches: this.featureSwitches,
},
layout?.isLeftRightSensitive() ?? false,
(e) => this.reportError(e),
(e) => this.reportError(e)
)
this.historicalUserLocations = this.geolocation.historicalUserLocations
this.newFeatures = new NewGeometryFromChangesFeatureSource(
this.changes,
layoutSource,
this.featureProperties,
this.featureProperties
)
layoutSource.addSource(this.newFeatures)
const perLayer = new PerLayerFeatureSourceSplitter(
Array.from(this.layerState.filteredLayers.values()).filter(
(l) => l.layerDef?.source !== null,
(l) => l.layerDef?.source !== null
),
new ChangeGeometryApplicator(this.indexedFeatures, this.changes),
{
@ -302,10 +302,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
"Got ",
features.length,
"leftover features, such as",
features[0].properties,
features[0].properties
)
},
},
}
)
this.perLayer = perLayer.perLayer
}
@ -345,12 +345,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.lastClickObject = new LastClickFeatureSource(
this.layout,
this.mapProperties.lastClickLocation,
this.userRelatedState.addNewFeatureMode,
this.userRelatedState.addNewFeatureMode
)
this.osmObjectDownloader = new OsmObjectDownloader(
this.osmConnection.Backend(),
this.changes,
this.changes
)
this.perLayerFiltered = this.showNormalDataOn(this.map)
@ -361,7 +361,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
currentZoom: this.mapProperties.zoom,
layerState: this.layerState,
bounds: this.visualFeedbackViewportBounds,
},
}
)
this.hasDataInView = new NoElementsInViewDetector(this).hasFeatureInView
this.imageUploadManager = new ImageUploadManager(
@ -369,15 +369,15 @@ export default class ThemeViewState implements SpecialVisualizationState {
Imgur.singleton,
this.featureProperties,
this.osmConnection,
this.changes,
this.changes
)
this.favourites = new FavouritesFeatureSource(this)
const longAgo = new Date()
longAgo.setTime(new Date().getTime() - 5 * 365 * 24 * 60 * 60 * 1000 )
longAgo.setTime(new Date().getTime() - 5 * 365 * 24 * 60 * 60 * 1000)
this.nearbyImageSearcher = new CombinedFetcher(50, longAgo, this.indexedFeatures)
this.featureSummary = this.setupSummaryLayer(
new LayerConfig(<LayerConfigJson>summaryLayer, "summaryLayer", true),
new LayerConfig(<LayerConfigJson>summaryLayer, "summaryLayer", true)
)
this.toCacheSavers = this.initSaveToLocalStorage()
this.initActors()
@ -417,7 +417,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
LayoutSource.fromCacheZoomLevel,
fs,
this.featureProperties,
fs.layer.layerDef.maxAgeOfCache,
fs.layer.layerDef.maxAgeOfCache
)
toLocalStorage.set(layerId, storage)
})
@ -430,7 +430,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const doShowLayer = this.mapProperties.zoom.map(
(z) =>
(fs.layer.isDisplayed?.data ?? true) && z >= (fs.layer.layerDef?.minzoom ?? 0),
[fs.layer.isDisplayed],
[fs.layer.isDisplayed]
)
if (!doShowLayer.data && this.featureSwitches.featureSwitchFilter.data === false) {
@ -447,7 +447,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
fs.layer,
fs,
(id) => this.featureProperties.getStore(id),
this.layerState.globalFilters,
this.layerState.globalFilters
)
filteringFeatureSource.set(layerName, filtered)
@ -591,7 +591,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
return
}
this.selectClosestAtCenter(0)
},
}
)
for (let i = 1; i < 9; i++) {
@ -609,7 +609,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
onUp: true,
},
doc,
() => this.selectClosestAtCenter(i - 1),
() => this.selectClosestAtCenter(i - 1)
)
}
@ -626,7 +626,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
if (this.featureSwitches.featureSwitchBackgroundSelection.data) {
this.guistate.backgroundLayerSelectionIsOpened.setData(true)
}
},
}
)
Hotkeys.RegisterHotkey(
{
@ -638,14 +638,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
if (this.featureSwitches.featureSwitchFilter.data) {
this.guistate.openFilterView()
}
},
}
)
Hotkeys.RegisterHotkey(
{ shift: "O" },
Translations.t.hotkeyDocumentation.selectMapnik,
() => {
this.mapProperties.rasterLayer.setData(AvailableRasterLayers.osmCarto)
},
}
)
const setLayerCategory = (category: EliCategory) => {
const available = this.availableLayers.data
@ -653,7 +653,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const best = RasterLayerUtils.SelectBestLayerAccordingTo(
available,
category,
current.data,
current.data
)
console.log("Best layer for category", category, "is", best.properties.id)
current.setData(best)
@ -662,26 +662,26 @@ export default class ThemeViewState implements SpecialVisualizationState {
Hotkeys.RegisterHotkey(
{ nomod: "O" },
Translations.t.hotkeyDocumentation.selectOsmbasedmap,
() => setLayerCategory("osmbasedmap"),
() => setLayerCategory("osmbasedmap")
)
Hotkeys.RegisterHotkey(
{ nomod: "M" },
Translations.t.hotkeyDocumentation.selectMap,
() => setLayerCategory("map"),
() => setLayerCategory("map")
)
Hotkeys.RegisterHotkey(
{ nomod: "P" },
Translations.t.hotkeyDocumentation.selectAerial,
() => setLayerCategory("photo"),
() => setLayerCategory("photo")
)
Hotkeys.RegisterHotkey(
{ nomod: "L" },
Translations.t.hotkeyDocumentation.geolocate,
() => {
this.geolocationControl.handleClick()
},
}
)
return true
})
@ -693,7 +693,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
Translations.t.hotkeyDocumentation.translationMode,
() => {
Locale.showLinkToWeblate.setData(!Locale.showLinkToWeblate.data)
},
}
)
}
@ -704,7 +704,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const normalLayers = this.layout.layers.filter(
(l) =>
Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
!l.id.startsWith("note_import"),
!l.id.startsWith("note_import")
)
const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom))
@ -712,7 +712,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
(l) =>
Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
l.source.geojsonSource === undefined &&
l.doCount,
l.doCount
)
const summaryTileSource = new SummaryTileSource(
Constants.SummaryServer,
@ -721,7 +721,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.mapProperties,
{
isActive: this.mapProperties.zoom.map((z) => z < maxzoom),
},
}
)
const src = new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers)
@ -743,12 +743,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
gps_location_history: this.geolocation.historicalUserLocations,
gps_track: this.geolocation.historicalUserLocationsTrack,
selected_element: new StaticFeatureSource(
this.selectedElement.map((f) => (f === undefined ? empty : [f])),
this.selectedElement.map((f) => (f === undefined ? empty : [f]))
),
range: new StaticFeatureSource(
this.mapProperties.maxbounds.map((bbox) =>
bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })],
),
bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })]
)
),
current_view: this.currentView,
favourite: this.favourites,
@ -763,7 +763,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
ShowDataLayer.showRange(
this.map,
new StaticFeatureSource([bbox.asGeoJson({ id: "range" })]),
this.featureSwitches.featureSwitchIsTesting,
this.featureSwitches.featureSwitchIsTesting
)
}
const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view")
@ -777,7 +777,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
currentViewLayer,
this.layout,
this.osmObjectDownloader,
this.featureProperties,
this.featureProperties
)
})
}
@ -821,20 +821,20 @@ export default class ThemeViewState implements SpecialVisualizationState {
const lastClickLayerConfig = new LayerConfig(
<LayerConfigJson>last_click_layerconfig,
"last_click",
"last_click"
)
const lastClickFiltered =
lastClickLayerConfig.isShown === undefined
? specialLayers.last_click
: specialLayers.last_click.features.mapD((fs) =>
fs.filter((f) => {
const matches = lastClickLayerConfig.isShown.matchesProperties(
f.properties,
)
console.debug("LastClick ", f, "matches", matches)
return matches
}),
)
fs.filter((f) => {
const matches = lastClickLayerConfig.isShown.matchesProperties(
f.properties
)
console.debug("LastClick ", f, "matches", matches)
return matches
})
)
new ShowDataLayer(this.map, {
features: new StaticFeatureSource(lastClickFiltered),
layer: lastClickLayerConfig,
@ -859,7 +859,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.selectedElement.addCallback((selected) => {
if (selected === undefined) {
this.focusOnMap()
}else{
} else {
this.lastClickObject.clear()
}
})
@ -881,7 +881,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.mapProperties.rasterLayer,
this.availableLayers,
this.featureSwitches.backgroundLayerId,
this.userRelatedState.preferredBackgroundLayer,
this.userRelatedState.preferredBackgroundLayer
)
}
@ -892,7 +892,13 @@ export default class ThemeViewState implements SpecialVisualizationState {
public async reportError(message: string | Error | XMLHttpRequest) {
const isTesting = this.featureSwitchIsTesting.data
console.log(isTesting ? ">>> _Not_ reporting error to report server as testmode is on" : ">>> Reporting error to", Constants.ErrorReportServer, message)
console.log(
isTesting
? ">>> _Not_ reporting error to report server as testmode is on"
: ">>> Reporting error to",
Constants.ErrorReportServer,
message
)
if (isTesting) {
return
}