forked from MapComplete/MapComplete
chore: automated housekeeping...
This commit is contained in:
parent
c10fecb7e8
commit
f5d7686c98
234 changed files with 3493 additions and 2482 deletions
|
@ -64,9 +64,9 @@ export class PreferredRasterLayerSelector {
|
|||
*/
|
||||
private async updateLayer() {
|
||||
// What is the ID of the layer we have to (try to) load?
|
||||
const targetLayerId = (
|
||||
(this._queryParameter.data ?? this._preferredBackgroundLayer.data)?.toLowerCase()
|
||||
)?.toLowerCase()
|
||||
const targetLayerId = (this._queryParameter.data ?? this._preferredBackgroundLayer.data)
|
||||
?.toLowerCase()
|
||||
?.toLowerCase()
|
||||
if (targetLayerId === undefined || targetLayerId === "default") {
|
||||
return
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ export class PreferredRasterLayerSelector {
|
|||
return
|
||||
}
|
||||
await AvailableRasterLayers.editorLayerIndex()
|
||||
const isCategory = (eliCategory).indexOf(<any> targetLayerId) >= 0
|
||||
const isCategory = eliCategory.indexOf(<any>targetLayerId) >= 0
|
||||
const available = this._availableLayers.store.data
|
||||
const foundLayer = isCategory
|
||||
? available.find((l) => l.properties.category === targetLayerId)
|
||||
|
|
|
@ -50,17 +50,20 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
|||
options?: {
|
||||
padToTiles?: Store<number>
|
||||
isActive?: Store<boolean>
|
||||
},
|
||||
}
|
||||
) {
|
||||
this.state = state
|
||||
this._isActive = options?.isActive ?? new ImmutableStore(true)
|
||||
this.padToZoomLevel = options?.padToTiles
|
||||
const self = this
|
||||
this._layersToDownload = state.zoom.map(zoom => this.layersToDownload(zoom))
|
||||
this._layersToDownload = state.zoom.map((zoom) => this.layersToDownload(zoom))
|
||||
|
||||
state.bounds.mapD((_) => {
|
||||
self.updateAsyncIfNeeded()
|
||||
}, [this._layersToDownload])
|
||||
state.bounds.mapD(
|
||||
(_) => {
|
||||
self.updateAsyncIfNeeded()
|
||||
},
|
||||
[this._layersToDownload]
|
||||
)
|
||||
}
|
||||
|
||||
private layersToDownload(zoom: number): LayerConfig[] {
|
||||
|
@ -82,7 +85,7 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
|||
// This is a special layer. Should not have been here
|
||||
console.warn(
|
||||
"OverpassFeatureSource received a layer for which the source is null:",
|
||||
layer.id,
|
||||
layer.id
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
@ -116,7 +119,7 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
|||
throw "Panic: overpassFeatureSource didn't receive any overpassUrls"
|
||||
}
|
||||
// Note: the bounds are updated between attempts, in case that the user zoomed around
|
||||
let bounds : BBox
|
||||
let bounds: BBox
|
||||
do {
|
||||
try {
|
||||
bounds = this.state.bounds.data
|
||||
|
@ -165,10 +168,16 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
|||
|
||||
const end = new Date()
|
||||
const timeNeeded = (end.getTime() - start.getTime()) / 1000
|
||||
console.log("Overpass returned", data.features.length, "features in", timeNeeded, "seconds")
|
||||
console.log(
|
||||
"Overpass returned",
|
||||
data.features.length,
|
||||
"features in",
|
||||
timeNeeded,
|
||||
"seconds"
|
||||
)
|
||||
self.features.setData(data.features)
|
||||
this._lastQueryBBox = bounds
|
||||
this._lastRequestedLayers= layersToDownload
|
||||
this._lastRequestedLayers = layersToDownload
|
||||
} catch (e) {
|
||||
console.error("Got the overpass response, but could not process it: ", e, e.stack)
|
||||
} finally {
|
||||
|
|
|
@ -53,7 +53,7 @@ export class Changes {
|
|||
featureSwitches?: FeatureSwitchState
|
||||
},
|
||||
leftRightSensitive: boolean = false,
|
||||
reportError?: (string: string | Error, extramessage?: string) => void,
|
||||
reportError?: (string: string | Error, extramessage?: string) => void
|
||||
) {
|
||||
this._leftRightSensitive = leftRightSensitive
|
||||
// We keep track of all changes just as well
|
||||
|
@ -68,7 +68,7 @@ export class Changes {
|
|||
state.osmConnection,
|
||||
state.featurePropertiesStore,
|
||||
this,
|
||||
(e, extramessage: string) => this._reportError(e, extramessage),
|
||||
(e, extramessage: string) => this._reportError(e, extramessage)
|
||||
)
|
||||
this.historicalUserLocations = state.historicalUserLocations
|
||||
|
||||
|
@ -82,7 +82,7 @@ export class Changes {
|
|||
modifiedObjects: OsmObject[]
|
||||
newObjects: OsmObject[]
|
||||
deletedObjects: OsmObject[]
|
||||
},
|
||||
}
|
||||
): string {
|
||||
const changedElements = allChanges.modifiedObjects ?? []
|
||||
const newElements = allChanges.newObjects ?? []
|
||||
|
@ -172,7 +172,7 @@ export class Changes {
|
|||
docs: "The identifier of the used background layer, this will probably be an identifier from the [editor layer index](https://github.com/osmlab/editor-layer-index)",
|
||||
},
|
||||
],
|
||||
"default",
|
||||
"default"
|
||||
),
|
||||
...addSource(ChangeTagAction.metatags, "ChangeTag"),
|
||||
...addSource(ChangeLocationAction.metatags, "ChangeLocation"),
|
||||
|
@ -201,7 +201,7 @@ export class Changes {
|
|||
: "",
|
||||
].join("\n"),
|
||||
source,
|
||||
]),
|
||||
])
|
||||
),
|
||||
].join("\n\n")
|
||||
}
|
||||
|
@ -217,7 +217,11 @@ export class Changes {
|
|||
// See #2082. We check for previous rewritings, as a remapping might be from a previous session
|
||||
do {
|
||||
this._nextId--
|
||||
} while (this._changesetHandler._remappings.has("node/" + this._nextId) || this._changesetHandler._remappings.has("way/" + this._nextId) || this._changesetHandler._remappings.has("relation/" + this._nextId))
|
||||
} while (
|
||||
this._changesetHandler._remappings.has("node/" + this._nextId) ||
|
||||
this._changesetHandler._remappings.has("way/" + this._nextId) ||
|
||||
this._changesetHandler._remappings.has("relation/" + this._nextId)
|
||||
)
|
||||
return this._nextId
|
||||
}
|
||||
|
||||
|
@ -254,7 +258,7 @@ export class Changes {
|
|||
const changeDescriptions = await action.Perform(this)
|
||||
const remapped = ChangeDescriptionTools.rewriteAllIds(
|
||||
changeDescriptions,
|
||||
this._changesetHandler._remappings,
|
||||
this._changesetHandler._remappings
|
||||
)
|
||||
|
||||
remapped[0].meta.distanceToObject = this.calculateDistanceToChanges(action, remapped)
|
||||
|
@ -319,7 +323,7 @@ export class Changes {
|
|||
}
|
||||
if (change.changes === undefined) {
|
||||
// This object is a change to a newly created object. However, we have not seen the creation changedescription yet!
|
||||
if(ignoreNoCreate){
|
||||
if (ignoreNoCreate) {
|
||||
continue
|
||||
}
|
||||
throw "Not a creation of the object: " + JSON.stringify(change)
|
||||
|
@ -462,7 +466,7 @@ export class Changes {
|
|||
result.modifiedObjects.length,
|
||||
"modified;",
|
||||
result.deletedObjects.length,
|
||||
"deleted",
|
||||
"deleted"
|
||||
)
|
||||
}
|
||||
return result
|
||||
|
@ -470,7 +474,7 @@ export class Changes {
|
|||
|
||||
private calculateDistanceToChanges(
|
||||
change: OsmChangeAction,
|
||||
changeDescriptions: ChangeDescription[],
|
||||
changeDescriptions: ChangeDescription[]
|
||||
) {
|
||||
const locations = this.historicalUserLocations?.features?.data
|
||||
if (locations === undefined) {
|
||||
|
@ -490,7 +494,7 @@ export class Changes {
|
|||
.filter((feat) => feat.geometry.type === "Point")
|
||||
.filter((feat) => {
|
||||
const visitTime = new Date(
|
||||
(<GeoLocationPointProperties>(<any>feat.properties)).date,
|
||||
(<GeoLocationPointProperties>(<any>feat.properties)).date
|
||||
)
|
||||
// In seconds
|
||||
const diff = (now.getTime() - visitTime.getTime()) / 1000
|
||||
|
@ -537,9 +541,9 @@ export class Changes {
|
|||
...recentLocationPoints.map((gpsPoint) => {
|
||||
const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint)
|
||||
return GeoOperations.distanceBetween(coor, otherCoor)
|
||||
}),
|
||||
),
|
||||
),
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -575,7 +579,7 @@ export class Changes {
|
|||
|
||||
public fragmentChanges(
|
||||
pending: ChangeDescription[],
|
||||
objects: OsmObject[],
|
||||
objects: OsmObject[]
|
||||
): {
|
||||
refused: ChangeDescription[]
|
||||
toUpload: ChangeDescription[]
|
||||
|
@ -585,7 +589,7 @@ export class Changes {
|
|||
|
||||
// All ids which have an 'update'
|
||||
const createdIds = new Set(
|
||||
pending.filter((cd) => cd.changes !== undefined).map((cd) => cd.id),
|
||||
pending.filter((cd) => cd.changes !== undefined).map((cd) => cd.id)
|
||||
)
|
||||
pending.forEach((c) => {
|
||||
if (c.id < 0) {
|
||||
|
@ -594,7 +598,7 @@ export class Changes {
|
|||
} else {
|
||||
this._reportError(
|
||||
`Got an orphaned change. The 'creation'-change description for ${c.type}/${c.id} got lost. Permanently dropping this change:` +
|
||||
JSON.stringify(c),
|
||||
JSON.stringify(c)
|
||||
)
|
||||
}
|
||||
return
|
||||
|
@ -605,10 +609,10 @@ export class Changes {
|
|||
} else {
|
||||
console.log(
|
||||
"Refusing change about " +
|
||||
c.type +
|
||||
"/" +
|
||||
c.id +
|
||||
" as not in the objects. No internet?",
|
||||
c.type +
|
||||
"/" +
|
||||
c.id +
|
||||
" as not in the objects. No internet?"
|
||||
)
|
||||
refused.push(c)
|
||||
}
|
||||
|
@ -623,16 +627,18 @@ export class Changes {
|
|||
*/
|
||||
private async flushSelectChanges(
|
||||
pending: ChangeDescription[],
|
||||
openChangeset: UIEventSource<number>,
|
||||
openChangeset: UIEventSource<number>
|
||||
): Promise<ChangeDescription[]> {
|
||||
const neededIds = Changes.GetNeededIds(pending)
|
||||
/* Download the latest version of the OSM-objects
|
||||
* We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes
|
||||
*/
|
||||
* We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes
|
||||
*/
|
||||
const downloader = new OsmObjectDownloader(this.backend, undefined)
|
||||
const osmObjects = Utils.NoNull(await Promise.all<{ id: string; osmObj: OsmObject | "deleted" }>(
|
||||
neededIds.map((id) => this.getOsmObject(id, downloader)),
|
||||
))
|
||||
const osmObjects = Utils.NoNull(
|
||||
await Promise.all<{ id: string; osmObj: OsmObject | "deleted" }>(
|
||||
neededIds.map((id) => this.getOsmObject(id, downloader))
|
||||
)
|
||||
)
|
||||
|
||||
// Drop changes to deleted items
|
||||
for (const { osmObj, id } of osmObjects) {
|
||||
|
@ -665,7 +671,7 @@ export class Changes {
|
|||
(csId, remappings) => {
|
||||
if (remappings.size > 0) {
|
||||
toUpload = toUpload.map((ch) =>
|
||||
ChangeDescriptionTools.rewriteIds(ch, remappings),
|
||||
ChangeDescriptionTools.rewriteIds(ch, remappings)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -678,7 +684,7 @@ export class Changes {
|
|||
return Changes.buildChangesetXML("" + csId, changes)
|
||||
},
|
||||
metatags,
|
||||
openChangeset,
|
||||
openChangeset
|
||||
)
|
||||
|
||||
console.log("Upload successful! Refused changes are", refused)
|
||||
|
@ -695,15 +701,15 @@ export class Changes {
|
|||
pending
|
||||
.filter(
|
||||
(descr) =>
|
||||
descr.meta.changeType !== undefined && descr.meta.changeType !== null,
|
||||
descr.meta.changeType !== undefined && descr.meta.changeType !== null
|
||||
)
|
||||
.map((descr) => descr.meta.changeType),
|
||||
.map((descr) => descr.meta.changeType)
|
||||
),
|
||||
([key, count]) => ({
|
||||
key: key,
|
||||
value: count,
|
||||
aggregate: true,
|
||||
}),
|
||||
})
|
||||
)
|
||||
const motivations = pending
|
||||
.filter((descr) => descr.meta.specialMotivation !== undefined)
|
||||
|
@ -742,7 +748,7 @@ export class Changes {
|
|||
value: count,
|
||||
aggregate: true,
|
||||
}
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
// This method is only called with changedescriptions for this theme
|
||||
|
@ -788,14 +794,14 @@ export class Changes {
|
|||
try {
|
||||
const openChangeset = UIEventSource.asInt(
|
||||
this.state.osmConnection.GetPreference(
|
||||
"current-open-changeset-" + theme,
|
||||
),
|
||||
"current-open-changeset-" + theme
|
||||
)
|
||||
)
|
||||
console.log(
|
||||
"Using current-open-changeset-" +
|
||||
theme +
|
||||
" from the preferences, got " +
|
||||
openChangeset.data,
|
||||
theme +
|
||||
" from the preferences, got " +
|
||||
openChangeset.data
|
||||
)
|
||||
|
||||
const refused = await self.flushSelectChanges(pendingChanges, openChangeset)
|
||||
|
@ -810,7 +816,7 @@ export class Changes {
|
|||
this.errors.ping()
|
||||
return pendingChanges
|
||||
}
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
// We keep all the refused changes to try them again
|
||||
|
@ -818,7 +824,7 @@ export class Changes {
|
|||
} catch (e) {
|
||||
console.error(
|
||||
"Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those",
|
||||
e,
|
||||
e
|
||||
)
|
||||
this.errors.data.push(e)
|
||||
this.errors.ping()
|
||||
|
|
|
@ -21,8 +21,11 @@ export type ChangesetMetadata = {
|
|||
uid: number
|
||||
user: string
|
||||
changes_count: number
|
||||
tags: Record<string, string>,
|
||||
minlat: number, minlon: number, maxlat: number, maxlon: number
|
||||
tags: Record<string, string>
|
||||
minlat: number
|
||||
minlon: number
|
||||
maxlat: number
|
||||
maxlon: number
|
||||
comments_count: number
|
||||
}
|
||||
|
||||
|
@ -49,7 +52,7 @@ export class ChangesetHandler {
|
|||
| { addAlias: (id0: string, id1: string) => void }
|
||||
| undefined,
|
||||
changes: Changes,
|
||||
reportError: (e: string | Error, extramessage: string) => void,
|
||||
reportError: (e: string | Error, extramessage: string) => void
|
||||
) {
|
||||
this.osmConnection = osmConnection
|
||||
this._reportError = reportError
|
||||
|
@ -107,27 +110,27 @@ export class ChangesetHandler {
|
|||
return hasChange
|
||||
}
|
||||
|
||||
private async UploadWithNew(generateChangeXML: (csid: number, remappings: Map<string, string>) => string, openChangeset: UIEventSource<number>, extraMetaTags: ChangesetTag[]) {
|
||||
private async UploadWithNew(
|
||||
generateChangeXML: (csid: number, remappings: Map<string, string>) => string,
|
||||
openChangeset: UIEventSource<number>,
|
||||
extraMetaTags: ChangesetTag[]
|
||||
) {
|
||||
const csId = await this.OpenChangeset(extraMetaTags)
|
||||
openChangeset.setData(csId)
|
||||
const changeset = generateChangeXML(csId, this._remappings)
|
||||
console.log(
|
||||
"Opened a new changeset (openChangeset.data is undefined):",
|
||||
changeset,
|
||||
extraMetaTags,
|
||||
extraMetaTags
|
||||
)
|
||||
const changes = await this.UploadChange(csId, changeset)
|
||||
const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(
|
||||
extraMetaTags,
|
||||
changes,
|
||||
)
|
||||
const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(extraMetaTags, changes)
|
||||
if (hasSpecialMotivationChanges) {
|
||||
// At this point, 'extraMetaTags' will have changed - we need to set the tags again
|
||||
await this.UpdateTags(csId, extraMetaTags)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The full logic to upload a change to one or more elements.
|
||||
*
|
||||
|
@ -141,7 +144,7 @@ export class ChangesetHandler {
|
|||
public async UploadChangeset(
|
||||
generateChangeXML: (csid: number, remappings: Map<string, string>) => string,
|
||||
extraMetaTags: ChangesetTag[],
|
||||
openChangeset: UIEventSource<number>,
|
||||
openChangeset: UIEventSource<number>
|
||||
): Promise<void> {
|
||||
if (
|
||||
!extraMetaTags.some((tag) => tag.key === "comment") ||
|
||||
|
@ -174,30 +177,30 @@ export class ChangesetHandler {
|
|||
// We can hopefully reuse the changeset
|
||||
|
||||
try {
|
||||
|
||||
const rewritings = await this.UploadChange(
|
||||
csId,
|
||||
generateChangeXML(csId, this._remappings),
|
||||
generateChangeXML(csId, this._remappings)
|
||||
)
|
||||
|
||||
const rewrittenTags = this.RewriteTagsOf(
|
||||
extraMetaTags,
|
||||
rewritings,
|
||||
oldChangesetMeta,
|
||||
oldChangesetMeta
|
||||
)
|
||||
await this.UpdateTags(csId, rewrittenTags)
|
||||
return // We are done!
|
||||
} catch (e) {
|
||||
this._reportError(e, "While reusing a changeset " + openChangeset.data)
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
this._reportError(e, "While getting metadata from a changeset " + openChangeset.data)
|
||||
this._reportError(
|
||||
e,
|
||||
"While getting metadata from a changeset " + openChangeset.data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We have to open a new changeset
|
||||
try {
|
||||
return await this.UploadWithNew(generateChangeXML, openChangeset, extraMetaTags)
|
||||
|
@ -212,7 +215,7 @@ export class ChangesetHandler {
|
|||
console.warn(
|
||||
"Could not open/upload changeset due to ",
|
||||
e,
|
||||
"trying again with a another fresh changeset ",
|
||||
"trying again with a another fresh changeset "
|
||||
)
|
||||
openChangeset.setData(undefined)
|
||||
|
||||
|
@ -238,7 +241,7 @@ export class ChangesetHandler {
|
|||
uid: number // User ID
|
||||
changes_count: number
|
||||
tags: any
|
||||
},
|
||||
}
|
||||
): ChangesetTag[] {
|
||||
// Note: extraMetaTags is where all the tags are collected into
|
||||
|
||||
|
@ -375,7 +378,7 @@ export class ChangesetHandler {
|
|||
tag.key !== undefined &&
|
||||
tag.value !== undefined &&
|
||||
tag.key !== "" &&
|
||||
tag.value !== "",
|
||||
tag.value !== ""
|
||||
)
|
||||
const metadata = tags.map((kv) => `<tag k="${kv.key}" v="${escapeHtml(kv.value)}"/>`)
|
||||
const content = [`<osm><changeset>`, metadata, `</changeset></osm>`].join("")
|
||||
|
@ -415,7 +418,7 @@ export class ChangesetHandler {
|
|||
const csId = await this.osmConnection.put(
|
||||
"changeset/create",
|
||||
[`<osm><changeset>`, metadata, `</changeset></osm>`].join(""),
|
||||
{ "Content-Type": "text/xml" },
|
||||
{ "Content-Type": "text/xml" }
|
||||
)
|
||||
return Number(csId)
|
||||
}
|
||||
|
@ -425,12 +428,12 @@ export class ChangesetHandler {
|
|||
*/
|
||||
private async UploadChange(
|
||||
changesetId: number,
|
||||
changesetXML: string,
|
||||
changesetXML: string
|
||||
): Promise<Map<string, string>> {
|
||||
const response = await this.osmConnection.post<XMLDocument>(
|
||||
"changeset/" + changesetId + "/upload",
|
||||
changesetXML,
|
||||
{ "Content-Type": "text/xml" },
|
||||
{ "Content-Type": "text/xml" }
|
||||
)
|
||||
const changes = this.parseUploadChangesetResponse(response)
|
||||
console.log("Uploaded changeset ", changesetId)
|
||||
|
|
|
@ -81,7 +81,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches {
|
|||
|
||||
const legacyRewrite: Record<string, string | string[]> = {
|
||||
"fs-userbadge": "fs-enable-login",
|
||||
"fs-layers": ["fs-filter", "fs-background"]
|
||||
"fs-layers": ["fs-filter", "fs-background"],
|
||||
}
|
||||
|
||||
for (const key in legacyRewrite) {
|
||||
|
@ -251,17 +251,20 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches {
|
|||
this.backgroundLayerId = QueryParameters.GetQueryParameter(
|
||||
"background",
|
||||
layoutToUse?.defaultBackgroundId,
|
||||
["When set, load this raster layer (or a layer of this category) as background layer instead of using the default background. This is as if the user opened the background selection menu and selected the layer with the given id or category.",
|
||||
[
|
||||
"When set, load this raster layer (or a layer of this category) as background layer instead of using the default background. This is as if the user opened the background selection menu and selected the layer with the given id or category.",
|
||||
"Most raster layers are based on the [editor layer index](https://github.com/osmlab/editor-layer-index)",
|
||||
|
||||
"#### Selecting a category",
|
||||
"If one of the following values is used, this parameter will be interpreted as a _category_ instead of the id of a specific layer. The best layer of this category will be used. Supported categories are those from the editor layer index and are:",
|
||||
eliCategory.map(c => "- " + c).join("\n"),
|
||||
eliCategory.map((c) => "- " + c).join("\n"),
|
||||
"#### Selecting a specific layer",
|
||||
"One can use the [ID of an ELI-layer](./ELI-overview.md) or use one of the global, builtin layers:",
|
||||
MarkdownUtils.list(AvailableRasterLayers.globalLayers.map(global =>
|
||||
global.properties.id+(global.properties.best ? " ⭐" : "")
|
||||
))
|
||||
MarkdownUtils.list(
|
||||
AvailableRasterLayers.globalLayers.map(
|
||||
(global) => global.properties.id + (global.properties.best ? " ⭐" : "")
|
||||
)
|
||||
),
|
||||
].join("\n\n")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ export default class UserRelatedState {
|
|||
this.showAllQuestionsAtOnce = UIEventSource.asBoolean(
|
||||
this.osmConnection.GetPreference("show-all-questions", "false", {
|
||||
documentation:
|
||||
"Either 'true' or 'false'. If set, all questions will be shown all at once"
|
||||
"Either 'true' or 'false'. If set, all questions will be shown all at once",
|
||||
})
|
||||
)
|
||||
this.language = this.osmConnection.GetPreference("language")
|
||||
|
@ -112,7 +112,7 @@ export default class UserRelatedState {
|
|||
undefined,
|
||||
{
|
||||
documentation:
|
||||
"The ID of a layer or layer category that MapComplete uses by default"
|
||||
"The ID of a layer or layer category that MapComplete uses by default",
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -120,12 +120,12 @@ export default class UserRelatedState {
|
|||
"preferences-add-new-mode",
|
||||
"button_click_right",
|
||||
{
|
||||
documentation: "How adding a new feature is done"
|
||||
documentation: "How adding a new feature is done",
|
||||
}
|
||||
)
|
||||
|
||||
this.imageLicense = this.osmConnection.GetPreference("pictures-license", "CC0", {
|
||||
documentation: "The license under which new images are uploaded"
|
||||
documentation: "The license under which new images are uploaded",
|
||||
})
|
||||
this.installedUserThemes = this.InitInstalledUserThemes()
|
||||
this.translationMode = this.initTranslationMode()
|
||||
|
@ -144,7 +144,6 @@ export default class UserRelatedState {
|
|||
this.language.syncWith(Locale.language)
|
||||
}
|
||||
|
||||
|
||||
private initTranslationMode(): UIEventSource<"false" | "true" | "mobile" | undefined | string> {
|
||||
const translationMode: UIEventSource<undefined | "true" | "false" | "mobile" | string> =
|
||||
this.osmConnection.GetPreference("translation-mode", "false")
|
||||
|
@ -164,7 +163,6 @@ export default class UserRelatedState {
|
|||
}
|
||||
})
|
||||
return translationMode
|
||||
|
||||
}
|
||||
|
||||
private static initUserSettingsState(): LayerConfig {
|
||||
|
@ -177,13 +175,13 @@ export default class UserRelatedState {
|
|||
|
||||
public GetUnofficialTheme(id: string):
|
||||
| {
|
||||
id: string
|
||||
icon: string
|
||||
title: any
|
||||
shortDescription: any
|
||||
definition?: any
|
||||
isOfficial: boolean
|
||||
}
|
||||
id: string
|
||||
icon: string
|
||||
title: any
|
||||
shortDescription: any
|
||||
definition?: any
|
||||
isOfficial: boolean
|
||||
}
|
||||
| undefined {
|
||||
console.log("GETTING UNOFFICIAL THEME")
|
||||
const pref = this.osmConnection.GetLongPreference("unofficial-theme-" + id)
|
||||
|
@ -208,8 +206,8 @@ export default class UserRelatedState {
|
|||
} catch (e) {
|
||||
console.warn(
|
||||
"Removing theme " +
|
||||
id +
|
||||
" as it could not be parsed from the preferences; the content is:",
|
||||
id +
|
||||
" as it could not be parsed from the preferences; the content is:",
|
||||
str
|
||||
)
|
||||
pref.setData(null)
|
||||
|
@ -239,7 +237,7 @@ export default class UserRelatedState {
|
|||
icon: layout.icon,
|
||||
title: layout.title.translations,
|
||||
shortDescription: layout.shortDescription.translations,
|
||||
definition: layout["definition"]
|
||||
definition: layout["definition"],
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -279,13 +277,13 @@ export default class UserRelatedState {
|
|||
id: "home",
|
||||
"user:home": "yes",
|
||||
_lon: homeLonLat[0],
|
||||
_lat: homeLonLat[1]
|
||||
_lat: homeLonLat[1],
|
||||
},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: homeLonLat
|
||||
}
|
||||
}
|
||||
coordinates: homeLonLat,
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
return new StaticFeatureSource(feature)
|
||||
|
@ -306,7 +304,7 @@ export default class UserRelatedState {
|
|||
_applicationOpened: new Date().toISOString(),
|
||||
_supports_sharing:
|
||||
typeof window === "undefined" ? "no" : window.navigator.share ? "yes" : "no",
|
||||
_iframe: Utils.isIframe ? "yes" : "no"
|
||||
_iframe: Utils.isIframe ? "yes" : "no",
|
||||
})
|
||||
|
||||
for (const key in Constants.userJourney) {
|
||||
|
@ -359,18 +357,18 @@ export default class UserRelatedState {
|
|||
const zenLinks: { link: string; id: string }[] = Utils.NoNull([
|
||||
hasMissingTheme
|
||||
? {
|
||||
id: "theme:" + layout.id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(
|
||||
language,
|
||||
"themes",
|
||||
layout.id
|
||||
)
|
||||
}
|
||||
id: "theme:" + layout.id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(
|
||||
language,
|
||||
"themes",
|
||||
layout.id
|
||||
),
|
||||
}
|
||||
: undefined,
|
||||
...missingLayers.map((id) => ({
|
||||
id: "layer:" + id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(language, "layers", id)
|
||||
}))
|
||||
link: LinkToWeblate.hrefToWeblateZen(language, "layers", id),
|
||||
})),
|
||||
])
|
||||
const untranslated_count = untranslated.length
|
||||
amendedPrefs.data["_translation_total"] = "" + total
|
||||
|
|
|
@ -1,14 +1,42 @@
|
|||
import { Utils } from "../../Utils"
|
||||
/** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */
|
||||
export class ThemeMetaTagging {
|
||||
public static readonly themeName = "usersettings"
|
||||
public static readonly themeName = "usersettings"
|
||||
|
||||
public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) {
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )
|
||||
Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/</g,'<')?.replace(/>/g,'>') ?? '' )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a )
|
||||
feat.properties['__current_backgroun'] = 'initial_value'
|
||||
}
|
||||
}
|
||||
public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) {
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () =>
|
||||
feat.properties._description
|
||||
.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)
|
||||
?.at(1)
|
||||
)
|
||||
Utils.AddLazyProperty(
|
||||
feat.properties,
|
||||
"_d",
|
||||
() => feat.properties._description?.replace(/</g, "<")?.replace(/>/g, ">") ?? ""
|
||||
)
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () =>
|
||||
((feat) => {
|
||||
const e = document.createElement("div")
|
||||
e.innerHTML = feat.properties._d
|
||||
return Array.from(e.getElementsByTagName("a")).filter(
|
||||
(a) => a.href.match(/mastodon|en.osm.town/) !== null
|
||||
)[0]?.href
|
||||
})(feat)
|
||||
)
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_link", () =>
|
||||
((feat) => {
|
||||
const e = document.createElement("div")
|
||||
e.innerHTML = feat.properties._d
|
||||
return Array.from(e.getElementsByTagName("a")).filter(
|
||||
(a) => a.getAttribute("rel")?.indexOf("me") >= 0
|
||||
)[0]?.href
|
||||
})(feat)
|
||||
)
|
||||
Utils.AddLazyProperty(
|
||||
feat.properties,
|
||||
"_mastodon_candidate",
|
||||
() => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a
|
||||
)
|
||||
feat.properties["__current_backgroun"] = "initial_value"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,17 @@ export class And extends TagsFilter {
|
|||
}
|
||||
|
||||
public static construct(and: ReadonlyArray<TagsFilter>): TagsFilter
|
||||
public static construct(and: ReadonlyArray<(FlatTag | (Or & OptimizedTag))>): TagsFilterClosed & OptimizedTag
|
||||
public static construct(and: ReadonlyArray< TagsFilter>): TagsFilter {
|
||||
public static construct(
|
||||
and: ReadonlyArray<FlatTag | (Or & OptimizedTag)>
|
||||
): TagsFilterClosed & OptimizedTag
|
||||
public static construct(and: ReadonlyArray<TagsFilter>): TagsFilter {
|
||||
if (and.length === 1) {
|
||||
return and[0]
|
||||
}
|
||||
return new And(and)
|
||||
}
|
||||
|
||||
private static combine(filter: string, choices: ReadonlyArray< string>): string[] {
|
||||
private static combine(filter: string, choices: ReadonlyArray<string>): string[] {
|
||||
const values = []
|
||||
for (const or of choices) {
|
||||
values.push(filter + or)
|
||||
|
@ -447,7 +449,7 @@ export class And extends TagsFilter {
|
|||
if (containedOrs.length === 1) {
|
||||
newAnds.push(containedOrs[0])
|
||||
} else if (containedOrs.length > 1) {
|
||||
let commonValues: TagsFilter[] = [...(containedOrs[0].or)]
|
||||
let commonValues: TagsFilter[] = [...containedOrs[0].or]
|
||||
for (let i = 1; i < containedOrs.length && commonValues.length > 0; i++) {
|
||||
const containedOr = containedOrs[i]
|
||||
commonValues = commonValues.filter((cv) =>
|
||||
|
|
|
@ -264,7 +264,7 @@ export class Or extends TagsFilter {
|
|||
if (containedAnds.length === 1) {
|
||||
newOrs.push(containedAnds[0])
|
||||
} else if (containedAnds.length > 1) {
|
||||
let commonValues: TagsFilter[] = [...(containedAnds[0].and)]
|
||||
let commonValues: TagsFilter[] = [...containedAnds[0].and]
|
||||
for (let i = 1; i < containedAnds.length && commonValues.length > 0; i++) {
|
||||
const containedAnd = containedAnds[i]
|
||||
commonValues = commonValues.filter((cv) =>
|
||||
|
|
|
@ -685,7 +685,10 @@ export class TagUtils {
|
|||
* TagUtils.containsEquivalents([new Tag("key","value")], [ new Tag("other_key","value")]) // => false
|
||||
* TagUtils.containsEquivalents([new Tag("key","value")], [ new Tag("key","other_value")]) // => false
|
||||
*/
|
||||
public static containsEquivalents(guards: ReadonlyArray<TagsFilter>, listToFilter: ReadonlyArray<TagsFilter>): boolean {
|
||||
public static containsEquivalents(
|
||||
guards: ReadonlyArray<TagsFilter>,
|
||||
listToFilter: ReadonlyArray<TagsFilter>
|
||||
): boolean {
|
||||
return listToFilter.some((tf) => guards.some((guard) => guard.shadows(tf)))
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export default class ThemeViewStateHashActor {
|
|||
"",
|
||||
"The possible hashes are:",
|
||||
"",
|
||||
MenuState.pageNames.map((tab) => "`" + tab + "`").join(",")
|
||||
MenuState.pageNames.map((tab) => "`" + tab + "`").join(","),
|
||||
]
|
||||
|
||||
/**
|
||||
|
@ -41,14 +41,13 @@ export default class ThemeViewStateHashActor {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
// At last, register callbacks on the state to update the hash when they change.
|
||||
// Note: these should use 'addCallback', not 'addCallbackAndRun'
|
||||
state.selectedElement.addCallback(() => this.setHash())
|
||||
|
||||
// Register a hash change listener to correctly handle the back button
|
||||
Hash.hash.addCallback((hash) => {
|
||||
if(this.isUpdatingHash){
|
||||
if (this.isUpdatingHash) {
|
||||
return
|
||||
}
|
||||
if (!hash) {
|
||||
|
@ -91,12 +90,7 @@ export default class ThemeViewStateHashActor {
|
|||
if (found.properties.id.startsWith("last_click")) {
|
||||
return true
|
||||
}
|
||||
console.log(
|
||||
"Setting selected element based on hash",
|
||||
hash,
|
||||
"; found",
|
||||
found
|
||||
)
|
||||
console.log("Setting selected element based on hash", hash, "; found", found)
|
||||
selectedElement.setData(found)
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue