diff --git a/Logic/Actors/OverpassFeatureSource.ts b/Logic/Actors/OverpassFeatureSource.ts index e2ab5ea87..ccc1bcca7 100644 --- a/Logic/Actors/OverpassFeatureSource.ts +++ b/Logic/Actors/OverpassFeatureSource.ts @@ -191,7 +191,7 @@ export default class OverpassFeatureSource implements FeatureSource { const self = this const overpassUrls = self.state.overpassUrl.data - if(overpassUrls === undefined || overpassUrls.length === 0){ + if (overpassUrls === undefined || overpassUrls.length === 0) { throw "Panic: overpassFeatureSource didn't receive any overpassUrls" } let bounds: BBox diff --git a/Logic/Actors/TitleHandler.ts b/Logic/Actors/TitleHandler.ts index c9817677a..729f172c1 100644 --- a/Logic/Actors/TitleHandler.ts +++ b/Logic/Actors/TitleHandler.ts @@ -46,9 +46,9 @@ export default class TitleHandler { if (Utils.runningFromConsole) { return } - try{ - document.title = title - }catch (e) { + try { + document.title = title + } catch (e) { console.error(e) } }) diff --git a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts index d8c6faa9c..6829a25a4 100644 --- a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts +++ b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts @@ -84,7 +84,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { } try { - const tags: OsmTags & {id: OsmId & string} = { + const tags: OsmTags & { id: OsmId & string } = { id: (change.type + "/" + change.id), } for (const kv of change.tags) { diff --git a/Logic/FeatureSource/Sources/StaticFeatureSource.ts b/Logic/FeatureSource/Sources/StaticFeatureSource.ts index 5c1628387..d99304a47 100644 --- a/Logic/FeatureSource/Sources/StaticFeatureSource.ts +++ b/Logic/FeatureSource/Sources/StaticFeatureSource.ts @@ -1,8 +1,8 @@ -import FeatureSource, {FeatureSourceForLayer, Tiled} from "../FeatureSource" -import {ImmutableStore, Store} from "../../UIEventSource" +import FeatureSource, { FeatureSourceForLayer, Tiled } from "../FeatureSource" +import { ImmutableStore, Store } from "../../UIEventSource" import FilteredLayer from "../../../Models/FilteredLayer" -import {BBox} from "../../BBox" -import {Feature} from "geojson"; +import { BBox } from "../../BBox" +import { Feature } from "geojson" /** * A simple, read only feature store. diff --git a/Logic/Osm/Actions/CreateNewNodeAction.ts b/Logic/Osm/Actions/CreateNewNodeAction.ts index afec56403..7e69e8317 100644 --- a/Logic/Osm/Actions/CreateNewNodeAction.ts +++ b/Logic/Osm/Actions/CreateNewNodeAction.ts @@ -19,7 +19,11 @@ export default class CreateNewNodeAction extends OsmCreateAction { private readonly _lon: number private readonly _snapOnto: OsmWay private readonly _reusePointDistance: number - private readonly meta: { changeType: "create" | "import"; theme: string; specialMotivation?: string } + private readonly meta: { + changeType: "create" | "import" + theme: string + specialMotivation?: string + } private readonly _reusePreviouslyCreatedPoint: boolean constructor( diff --git a/Logic/Osm/Actions/DeleteAction.ts b/Logic/Osm/Actions/DeleteAction.ts index 008bbf3dc..fb3712eb7 100644 --- a/Logic/Osm/Actions/DeleteAction.ts +++ b/Logic/Osm/Actions/DeleteAction.ts @@ -3,10 +3,10 @@ import OsmChangeAction from "./OsmChangeAction" import { Changes } from "../Changes" import { ChangeDescription } from "./ChangeDescription" import ChangeTagAction from "./ChangeTagAction" -import {TagsFilter} from "../../Tags/TagsFilter" -import {And} from "../../Tags/And" -import {Tag} from "../../Tags/Tag" -import {OsmId} from "../../../Models/OsmFeature"; +import { TagsFilter } from "../../Tags/TagsFilter" +import { And } from "../../Tags/And" +import { Tag } from "../../Tags/Tag" +import { OsmId } from "../../../Models/OsmFeature" import { Utils } from "../../../Utils" export default class DeleteAction extends OsmChangeAction { @@ -19,7 +19,6 @@ export default class DeleteAction extends OsmChangeAction { private readonly _id: OsmId private readonly _hardDelete: boolean - constructor( id: OsmId, softDeletionTags: TagsFilter | undefined, @@ -39,11 +38,12 @@ export default class DeleteAction extends OsmChangeAction { this._softDeletionTags = new And( Utils.NoNull([ softDeletionTags, - new Tag( - "fixme", - `A mapcomplete user marked this feature to be deleted (${meta.specialMotivation})` - ) - ])) + new Tag( + "fixme", + `A mapcomplete user marked this feature to be deleted (${meta.specialMotivation})` + ), + ]) + ) } } /** @@ -63,8 +63,11 @@ export default class DeleteAction extends OsmChangeAction { * const descr = await da.CreateChangeDescriptions(new Changes(), obj) * descr[0] // => {doDelete: true, meta: {theme: "test", specialMotivation: "Testcase", changeType: "deletion"}, type: "node",id: 1 } */ - public async CreateChangeDescriptions(changes: Changes, object?: OsmObject): Promise { - const osmObject = object ?? await OsmObject.DownloadObjectAsync(this._id) + public async CreateChangeDescriptions( + changes: Changes, + object?: OsmObject + ): Promise { + const osmObject = object ?? (await OsmObject.DownloadObjectAsync(this._id)) if (this._hardDelete) { return [ diff --git a/Logic/Osm/Actions/ReplaceGeometryAction.ts b/Logic/Osm/Actions/ReplaceGeometryAction.ts index c8104f55e..94390f61f 100644 --- a/Logic/Osm/Actions/ReplaceGeometryAction.ts +++ b/Logic/Osm/Actions/ReplaceGeometryAction.ts @@ -13,7 +13,7 @@ import { Utils } from "../../../Utils" import { OsmConnection } from "../OsmConnection" import { Feature } from "@turf/turf" import FeaturePipeline from "../../FeatureSource/FeaturePipeline" -import {Geometry, LineString, Point, Polygon} from "geojson"; +import { Geometry, LineString, Point, Polygon } from "geojson" export default class ReplaceGeometryAction extends OsmChangeAction { /** @@ -85,7 +85,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { public async getPreview(): Promise { const { closestIds, allNodesById, detachedNodes, reprojectedNodes } = await this.GetClosestIds() - const preview: Feature [] = closestIds.map((newId, i) => { + const preview: Feature[] = closestIds.map((newId, i) => { if (this.identicalTo[i] !== undefined) { return undefined } @@ -390,7 +390,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { const node = allNodesById.get(id) // Project the node onto the target way to calculate the new coordinates - const way = > { + const way = >{ type: "Feature", properties: {}, geometry: { diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index 19aa92423..e12df9419 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -1,10 +1,10 @@ -import {Utils} from "../../Utils" +import { Utils } from "../../Utils" import * as polygon_features from "../../assets/polygon-features.json" -import {Store, UIEventSource} from "../UIEventSource" -import {BBox} from "../BBox" +import { Store, UIEventSource } from "../UIEventSource" +import { BBox } from "../BBox" import * as OsmToGeoJson from "osmtogeojson" -import {NodeId, OsmFeature, OsmId, OsmTags, RelationId, WayId} from "../../Models/OsmFeature" -import {Feature, LineString, Polygon} from "geojson"; +import { NodeId, OsmFeature, OsmId, OsmTags, RelationId, WayId } from "../../Models/OsmFeature" +import { Feature, LineString, Polygon } from "geojson" export abstract class OsmObject { private static defaultBackend = "https://www.openstreetmap.org/" @@ -17,7 +17,7 @@ export abstract class OsmObject { /** * The OSM tags as simple object */ - tags: OsmTags & {id: OsmId} + tags: OsmTags & { id: OsmId } version: number public changed: boolean = false timestamp: Date @@ -41,9 +41,9 @@ export abstract class OsmObject { this.backendURL = url } - public static DownloadObject(id: NodeId, forceRefresh?: boolean): Store ; - public static DownloadObject(id: RelationId, forceRefresh?: boolean): Store ; - public static DownloadObject(id: WayId, forceRefresh?: boolean): Store ; + public static DownloadObject(id: NodeId, forceRefresh?: boolean): Store + public static DownloadObject(id: RelationId, forceRefresh?: boolean): Store + public static DownloadObject(id: WayId, forceRefresh?: boolean): Store public static DownloadObject(id: string, forceRefresh: boolean = false): Store { let src: UIEventSource if (OsmObject.objectCache.has(id)) { @@ -73,12 +73,30 @@ export abstract class OsmObject { return rawData.elements[0].tags } - static async DownloadObjectAsync(id: NodeId, maxCacheAgeInSecs?: number): Promise - static async DownloadObjectAsync(id: WayId, maxCacheAgeInSecs?: number): Promise - static async DownloadObjectAsync(id: RelationId, maxCacheAgeInSecs?: number): Promise - static async DownloadObjectAsync(id: OsmId, maxCacheAgeInSecs?: number): Promise - static async DownloadObjectAsync(id: string, maxCacheAgeInSecs?: number): Promise - static async DownloadObjectAsync(id: string, maxCacheAgeInSecs?: number): Promise { + static async DownloadObjectAsync( + id: NodeId, + maxCacheAgeInSecs?: number + ): Promise + static async DownloadObjectAsync( + id: WayId, + maxCacheAgeInSecs?: number + ): Promise + static async DownloadObjectAsync( + id: RelationId, + maxCacheAgeInSecs?: number + ): Promise + static async DownloadObjectAsync( + id: OsmId, + maxCacheAgeInSecs?: number + ): Promise + static async DownloadObjectAsync( + id: string, + maxCacheAgeInSecs?: number + ): Promise + static async DownloadObjectAsync( + id: string, + maxCacheAgeInSecs?: number + ): Promise { const splitted = id.split("/") const type = splitted[0] const idN = Number(splitted[1]) @@ -210,7 +228,7 @@ export abstract class OsmObject { case "relation": osmObject = new OsmRelation(idN) const allGeojsons = OsmToGeoJson.default( - {elements}, + { elements }, // @ts-ignore { flatProperties: true, @@ -264,14 +282,16 @@ export abstract class OsmObject { return false } - private static constructPolygonFeatures(): Map; blacklist: boolean }> { + private static constructPolygonFeatures(): Map< + string, + { values: Set; blacklist: boolean } + > { const result = new Map; blacklist: boolean }>() for (const polygonFeature of polygon_features["default"] ?? polygon_features) { const key = polygonFeature.key if (polygonFeature.polygon === "all") { - result.set(key, {values: null, blacklist: false}) + result.set(key, { values: null, blacklist: false }) continue } diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index 60bb1e0c2..ce5dafcd6 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -1,13 +1,13 @@ -import {Tag} from "./Tag" -import {TagsFilter} from "./TagsFilter" -import {And} from "./And" -import {Utils} from "../../Utils" +import { Tag } from "./Tag" +import { TagsFilter } from "./TagsFilter" +import { And } from "./And" +import { Utils } from "../../Utils" import ComparingTag from "./ComparingTag" -import {RegexTag} from "./RegexTag" +import { RegexTag } from "./RegexTag" import SubstitutingTag from "./SubstitutingTag" -import {Or} from "./Or" -import {TagConfigJson} from "../../Models/ThemeConfig/Json/TagConfigJson" -import {isRegExp} from "util" +import { Or } from "./Or" +import { TagConfigJson } from "../../Models/ThemeConfig/Json/TagConfigJson" +import { isRegExp } from "util" import * as key_counts from "../../assets/key_totals.json" type Tags = Record @@ -373,7 +373,7 @@ export class TagUtils { return null } const [_, key, invert, modifier, value] = match - return {key, value, invert: invert == "!", modifier: modifier == "i~" ? "i" : ""} + return { key, value, invert: invert == "!", modifier: modifier == "i~" ? "i" : "" } } /** @@ -557,9 +557,9 @@ export class TagUtils { if (tag.indexOf("~~") >= 0) { const split = Utils.SplitFirst(tag, "~~") - let keyRegex: RegExp; + let keyRegex: RegExp if (split[0] === "*") { - keyRegex = new RegExp(".+","i") + keyRegex = new RegExp(".+", "i") } else { keyRegex = new RegExp("^(" + split[0] + ")$") } @@ -569,10 +569,7 @@ export class TagUtils { } else { valueRegex = new RegExp("^(" + split[1] + ")$", "s") } - return new RegexTag( - keyRegex, - valueRegex - ) + return new RegexTag(keyRegex, valueRegex) } const withRegex = TagUtils.parseRegexOperator(tag) if (withRegex != null) { @@ -627,7 +624,7 @@ export class TagUtils { ) } if (split[1] === "") { - return new RegexTag(split[0], /.+/si) + return new RegexTag(split[0], /.+/is) } return new RegexTag(split[0], split[1], true) } diff --git a/Logic/Web/QueryParameters.ts b/Logic/Web/QueryParameters.ts index 501da39b4..ac885184c 100644 --- a/Logic/Web/QueryParameters.ts +++ b/Logic/Web/QueryParameters.ts @@ -6,7 +6,7 @@ import Hash from "./Hash" import { Utils } from "../../Utils" export class QueryParameters { - static defaults : Record = {} + static defaults: Record = {} static documentation: Map = new Map() private static order: string[] = ["layout", "test", "z", "lat", "lon"] protected static readonly _wasInitialized: Set = new Set() @@ -105,9 +105,9 @@ export class QueryParameters { } if (!Utils.runningFromConsole) { // Don't pollute the history every time a parameter changes - try{ + try { history.replaceState(null, "", "?" + parts.join("&") + Hash.Current()) - }catch(e){ + } catch (e) { console.error(e) } } diff --git a/Models/ThemeConfig/Conversion/PrepareLayer.ts b/Models/ThemeConfig/Conversion/PrepareLayer.ts index 399d7892e..ae3860ce8 100644 --- a/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -1,64 +1,90 @@ -import {Concat, Conversion, DesugaringContext, DesugaringStep, Each, FirstOf, Fuse, On, SetDefault,} from "./Conversion" -import {LayerConfigJson} from "../Json/LayerConfigJson" -import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson" -import {Utils} from "../../../Utils" +import { + Concat, + Conversion, + DesugaringContext, + DesugaringStep, + Each, + FirstOf, + Fuse, + On, + SetDefault, +} from "./Conversion" +import { LayerConfigJson } from "../Json/LayerConfigJson" +import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" +import { Utils } from "../../../Utils" import RewritableConfigJson from "../Json/RewritableConfigJson" import SpecialVisualizations from "../../../UI/SpecialVisualizations" import Translations from "../../../UI/i18n/Translations" -import {Translation} from "../../../UI/i18n/Translation" +import { Translation } from "../../../UI/i18n/Translation" import * as tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json" -import {AddContextToTranslations} from "./AddContextToTranslations" -import FilterConfigJson from "../Json/FilterConfigJson"; +import { AddContextToTranslations } from "./AddContextToTranslations" +import FilterConfigJson from "../Json/FilterConfigJson" import * as predifined_filters from "../../../assets/layers/filters/filters.json" -class ExpandFilter extends DesugaringStep{ - - - private static load_filters(): Map{ - let filters = new Map(); - for (const filter of (predifined_filters.filter)) { +class ExpandFilter extends DesugaringStep { + private static load_filters(): Map { + let filters = new Map() + for (const filter of predifined_filters.filter) { filters.set(filter.id, filter) } - return filters; + return filters } - private static readonly predefinedFilters = ExpandFilter.load_filters(); + private static readonly predefinedFilters = ExpandFilter.load_filters() constructor() { - super("Expands filters: replaces a shorthand by the value found in 'filters.json'", ["filter"], "ExpandFilter"); + super( + "Expands filters: replaces a shorthand by the value found in 'filters.json'", + ["filter"], + "ExpandFilter" + ) } - convert(json: LayerConfigJson, context: string): { result: LayerConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { - if(json.filter === undefined || json.filter === null){ - return {result: json} // Nothing to change here + convert( + json: LayerConfigJson, + context: string + ): { result: LayerConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { + if (json.filter === undefined || json.filter === null) { + return { result: json } // Nothing to change here } - if( json.filter["sameAs"] !== undefined){ - return {result: json} // Nothing to change here + if (json.filter["sameAs"] !== undefined) { + return { result: json } // Nothing to change here } - const newFilters : FilterConfigJson[] = [] - const errors :string[]= [] - for (const filter of (<(FilterConfigJson|string)[]> json.filter)) { + const newFilters: FilterConfigJson[] = [] + const errors: string[] = [] + for (const filter of <(FilterConfigJson | string)[]>json.filter) { if (typeof filter !== "string") { newFilters.push(filter) continue } // Search for the filter: const found = ExpandFilter.predefinedFilters.get(filter) - if(found === undefined){ - const suggestions = Utils.sortedByLevenshteinDistance(filter, Array.from(ExpandFilter.predefinedFilters.keys()), t => t) - const err = context+".filter: while searching for predifined filter "+filter+": this filter is not found. Perhaps you meant one of: "+suggestions + if (found === undefined) { + const suggestions = Utils.sortedByLevenshteinDistance( + filter, + Array.from(ExpandFilter.predefinedFilters.keys()), + (t) => t + ) + const err = + context + + ".filter: while searching for predifined filter " + + filter + + ": this filter is not found. Perhaps you meant one of: " + + suggestions errors.push(err) } newFilters.push(found) } - return {result: { - ...json, filter: newFilters - }, errors}; + return { + result: { + ...json, + filter: newFilters, + }, + errors, + } } - - } class ExpandTagRendering extends Conversion< diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index 22db9808d..c316aa879 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -1,21 +1,21 @@ -import {DesugaringStep, Each, Fuse, On} from "./Conversion" -import {LayerConfigJson} from "../Json/LayerConfigJson" +import { DesugaringStep, Each, Fuse, On } from "./Conversion" +import { LayerConfigJson } from "../Json/LayerConfigJson" import LayerConfig from "../LayerConfig" -import {Utils} from "../../../Utils" +import { Utils } from "../../../Utils" import Constants from "../../Constants" -import {Translation} from "../../../UI/i18n/Translation" -import {LayoutConfigJson} from "../Json/LayoutConfigJson" +import { Translation } from "../../../UI/i18n/Translation" +import { LayoutConfigJson } from "../Json/LayoutConfigJson" import LayoutConfig from "../LayoutConfig" -import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson" -import {TagUtils} from "../../../Logic/Tags/TagUtils" -import {ExtractImages} from "./FixImages" +import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" +import { TagUtils } from "../../../Logic/Tags/TagUtils" +import { ExtractImages } from "./FixImages" import ScriptUtils from "../../../scripts/ScriptUtils" -import {And} from "../../../Logic/Tags/And" +import { And } from "../../../Logic/Tags/And" import Translations from "../../../UI/i18n/Translations" import Svg from "../../../Svg" -import {QuestionableTagRenderingConfigJson} from "../Json/QuestionableTagRenderingConfigJson" -import FilterConfigJson from "../Json/FilterConfigJson"; -import DeleteConfig from "../DeleteConfig"; +import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson" +import FilterConfigJson from "../Json/FilterConfigJson" +import DeleteConfig from "../DeleteConfig" class ValidateLanguageCompleteness extends DesugaringStep { private readonly _languages: string[] @@ -42,12 +42,12 @@ class ValidateLanguageCompleteness extends DesugaringStep { .forEach((missing) => { errors.push( context + - "A theme should be translation-complete for " + - neededLanguage + - ", but it lacks a translation for " + - missing.context + - ".\n\tThe known translation is " + - missing.tr.textFor("en") + "A theme should be translation-complete for " + + neededLanguage + + ", but it lacks a translation for " + + missing.context + + ".\n\tThe known translation is " + + missing.tr.textFor("en") ) }) } @@ -81,16 +81,16 @@ export class DoesImageExist extends DesugaringStep { const information = [] if (image.indexOf("{") >= 0) { information.push("Ignoring image with { in the path: " + image) - return {result: image} + return { result: image } } if (image === "assets/SocialImage.png") { - return {result: image} + return { result: image } } if (image.match(/[a-z]*/)) { if (Svg.All[image + ".svg"] !== undefined) { // This is a builtin img, e.g. 'checkmark' or 'crosshair' - return {result: image} + return { result: image } } } @@ -157,15 +157,15 @@ class ValidateTheme extends DesugaringStep { if (json["units"] !== undefined) { errors.push( "The theme " + - json.id + - " has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) " + json.id + + " has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) " ) } if (json["roamingRenderings"] !== undefined) { errors.push( "Theme " + - json.id + - " contains an old 'roamingRenderings'. Use an 'overrideAll' instead" + json.id + + " contains an old 'roamingRenderings'. Use an 'overrideAll' instead" ) } } @@ -180,10 +180,10 @@ class ValidateTheme extends DesugaringStep { for (const remoteImage of remoteImages) { errors.push( "Found a remote image: " + - remoteImage + - " in theme " + - json.id + - ", please download it." + remoteImage + + " in theme " + + json.id + + ", please download it." ) } for (const image of images) { @@ -212,10 +212,10 @@ class ValidateTheme extends DesugaringStep { const h = parseInt(height) if (w < 370 || h < 370) { const e: string = [ - `the icon for theme ${json.id} is too small. Please rescale the icon at ${json.icon}`, - `Even though an SVG is 'infinitely scaleable', the icon should be dimensioned bigger. One of the build steps of the theme does convert the image to a PNG (to serve as PWA-icon) and having a small dimension will cause blurry images.`, - ` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`, - ].join("\n") + `the icon for theme ${json.id} is too small. Please rescale the icon at ${json.icon}`, + `Even though an SVG is 'infinitely scaleable', the icon should be dimensioned bigger. One of the build steps of the theme does convert the image to a PNG (to serve as PWA-icon) and having a small dimension will cause blurry images.`, + ` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`, + ].join("\n") ;(json.hideFromOverview ? warnings : errors).push(e) } }) @@ -227,7 +227,6 @@ class ValidateTheme extends DesugaringStep { try { if (this._isBuiltin) { - if (theme.id !== theme.id.toLowerCase()) { errors.push("Theme ids should be in lowercase, but it is " + theme.id) } @@ -239,12 +238,12 @@ class ValidateTheme extends DesugaringStep { if (theme.id !== filename) { errors.push( "Theme ids should be the same as the name.json, but we got id: " + - theme.id + - " and filename " + - filename + - " (" + - this._path + - ")" + theme.id + + " and filename " + + filename + + " (" + + this._path + + ")" ) } this._validateImage.convertJoin( @@ -323,7 +322,7 @@ class OverrideShadowingCheck extends DesugaringStep { ): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } { const overrideAll = json.overrideAll if (overrideAll === undefined) { - return {result: json} + return { result: json } } const errors = [] @@ -350,7 +349,7 @@ class OverrideShadowingCheck extends DesugaringStep { } } - return {result: json, errors} + return { result: json, errors } } } @@ -460,7 +459,7 @@ export class DetectShadowedMappings extends DesugaringStep { + keyValues.forEach(({ k, v }) => { properties[k] = v }) for (let j = 0; j < i; j++) { @@ -506,10 +505,10 @@ export class DetectShadowedMappings extends DesugaringStep { if (json.title === undefined) { errors.push( context + - ": this layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error." + ": this layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error." ) } if (json.title === null) { information.push( context + - ": title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set." + ": title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set." ) } } @@ -697,16 +696,16 @@ export class ValidateLayer extends DesugaringStep { if (duplicates.length > 0) { errors.push( "At " + - context + - ": some tagrenderings have a duplicate id: " + - duplicates.join(", ") + context + + ": some tagrenderings have a duplicate id: " + + duplicates.join(", ") ) } } - if(json.deletion !== undefined && json.deletion instanceof DeleteConfig){ - if(json.deletion.softDeletionTags === undefined){ - warnings.push("No soft-deletion tags in deletion block for layer "+json.id) + if (json.deletion !== undefined && json.deletion instanceof DeleteConfig) { + if (json.deletion.softDeletionTags === undefined) { + warnings.push("No soft-deletion tags in deletion block for layer " + json.id) } } @@ -717,8 +716,8 @@ export class ValidateLayer extends DesugaringStep { if (json["overpassTags"] !== undefined) { errors.push( "Layer " + - json.id + - 'still uses the old \'overpassTags\'-format. Please use "source": {"osmTags": }\' instead of "overpassTags": (note: this isn\'t your fault, the custom theme generator still spits out the old format)' + json.id + + 'still uses the old \'overpassTags\'-format. Please use "source": {"osmTags": }\' instead of "overpassTags": (note: this isn\'t your fault, the custom theme generator still spits out the old format)' ) } const forbiddenTopLevel = [ @@ -736,18 +735,18 @@ export class ValidateLayer extends DesugaringStep { if (json[forbiddenKey] !== undefined) errors.push( context + - ": layer " + - json.id + - " still has a forbidden key " + - forbiddenKey + ": layer " + + json.id + + " still has a forbidden key " + + forbiddenKey ) } if (json["hideUnderlayingFeaturesMinPercentage"] !== undefined) { errors.push( context + - ": layer " + - json.id + - " contains an old 'hideUnderlayingFeaturesMinPercentage'" + ": layer " + + json.id + + " contains an old 'hideUnderlayingFeaturesMinPercentage'" ) } @@ -764,9 +763,9 @@ export class ValidateLayer extends DesugaringStep { if (this._path != undefined && this._path.indexOf(expected) < 0) { errors.push( "Layer is in an incorrect place. The path is " + - this._path + - ", but expected " + - expected + this._path + + ", but expected " + + expected ) } } @@ -824,9 +823,9 @@ export class ValidateLayer extends DesugaringStep { if (hasCondition?.length > 0) { errors.push( "At " + - context + - ":\n One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n" + - JSON.stringify(hasCondition, null, " ") + context + + ":\n One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n" + + JSON.stringify(hasCondition, null, " ") ) } } @@ -838,7 +837,7 @@ export class ValidateLayer extends DesugaringStep { const preset = json.presets[i] const tags: { k: string; v: string }[] = new And( preset.tags.map((t) => TagUtils.Tag(t)) - ).asChange({id: "node/-1"}) + ).asChange({ id: "node/-1" }) const properties = {} for (const tag of tags) { properties[tag.k] = tag.v @@ -847,12 +846,12 @@ export class ValidateLayer extends DesugaringStep { if (!doMatch) { errors.push( context + - ".presets[" + - i + - "]: This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " + - JSON.stringify(properties) + - "\n The required tags are: " + - baseTags.asHumanString(false, false, {}) + ".presets[" + + i + + "]: This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " + + JSON.stringify(properties) + + "\n The required tags are: " + + baseTags.asHumanString(false, false, {}) ) } } @@ -870,32 +869,45 @@ export class ValidateLayer extends DesugaringStep { } } -export class DetectDuplicateFilters extends DesugaringStep<{ layers: LayerConfigJson[], themes: LayoutConfigJson[]}> { - +export class DetectDuplicateFilters extends DesugaringStep<{ + layers: LayerConfigJson[] + themes: LayoutConfigJson[] +}> { constructor() { - super("Tries to detect layers where a shared filter can be used (or where similar filters occur)", [], "DetectDuplicateFilters"); + super( + "Tries to detect layers where a shared filter can be used (or where similar filters occur)", + [], + "DetectDuplicateFilters" + ) } /** * Add all filter options into 'perOsmTag' */ - private addLayerFilters(layer: LayerConfigJson, perOsmTag: Map, layout?: LayoutConfigJson | undefined): void { + perOsmTag: Map< + string, + { + layer: LayerConfigJson + layout: LayoutConfigJson | undefined + filter: FilterConfigJson + }[] + >, + layout?: LayoutConfigJson | undefined + ): void { if (layer.filter === undefined || layer.filter === null) { - return; + return } if (layer.filter["sameAs"] !== undefined) { - return; + return } - for (const filter of (<(string | FilterConfigJson) []>layer.filter)) { + for (const filter of <(string | FilterConfigJson)[]>layer.filter) { if (typeof filter === "string") { continue } - if(filter["#"]?.indexOf("ignore-possible-duplicate")>=0){ + if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) { continue } @@ -908,57 +920,66 @@ export class DetectDuplicateFilters extends DesugaringStep<{ layers: LayerConfig perOsmTag.set(key, []) } perOsmTag.get(key).push({ - layer, filter, layout + layer, + filter, + layout, }) } - } - } - convert(json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, context: string): { result: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }; errors?: string[]; warnings?: string[]; information?: string[] } { - + convert( + json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, + context: string + ): { + result: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } + errors?: string[] + warnings?: string[] + information?: string[] + } { const errors: string[] = [] const warnings: string[] = [] const information: string[] = [] - const {layers, themes} = json - const perOsmTag = new Map() + const { layers, themes } = json + const perOsmTag = new Map< + string, + { + layer: LayerConfigJson + layout: LayoutConfigJson | undefined + filter: FilterConfigJson + }[] + >() for (const layer of layers) { this.addLayerFilters(layer, perOsmTag) } for (const theme of themes) { - if(theme.id === "personal"){ + if (theme.id === "personal") { continue } for (const layer of theme.layers) { - if(typeof layer === "string"){ + if (typeof layer === "string") { continue } - if(layer["builtin"] !== undefined){ + if (layer["builtin"] !== undefined) { continue } - this.addLayerFilters( layer, perOsmTag, theme) + this.addLayerFilters(layer, perOsmTag, theme) } } - // At this point, we have gathered all filters per tag - time to find duplicates perOsmTag.forEach((value, key) => { - if(value.length <= 1){ + if (value.length <= 1) { // Seen this key just once, it is unique - return; + return } - let msg = "Possible duplicate filter: "+ key - for (const {filter, layer, layout} of value) { + let msg = "Possible duplicate filter: " + key + for (const { filter, layer, layout } of value) { let id = "" - if(layout !== undefined){ + if (layout !== undefined) { id = layout.id + ":" } msg += `\n - ${id}${layer.id}.${filter.id}` @@ -970,8 +991,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{ layers: LayerConfig result: json, errors, warnings, - information - }; + information, + } } - } diff --git a/Models/ThemeConfig/FilterConfig.ts b/Models/ThemeConfig/FilterConfig.ts index e67cba117..a95dc3b29 100644 --- a/Models/ThemeConfig/FilterConfig.ts +++ b/Models/ThemeConfig/FilterConfig.ts @@ -1,15 +1,15 @@ -import {Translation} from "../../UI/i18n/Translation" -import {TagsFilter} from "../../Logic/Tags/TagsFilter" +import { Translation } from "../../UI/i18n/Translation" +import { TagsFilter } from "../../Logic/Tags/TagsFilter" import FilterConfigJson from "./Json/FilterConfigJson" import Translations from "../../UI/i18n/Translations" -import {TagUtils} from "../../Logic/Tags/TagUtils" +import { TagUtils } from "../../Logic/Tags/TagUtils" import ValidatedTextField from "../../UI/Input/ValidatedTextField" -import {TagConfigJson} from "./Json/TagConfigJson" -import {UIEventSource} from "../../Logic/UIEventSource" -import {FilterState} from "../FilteredLayer" -import {QueryParameters} from "../../Logic/Web/QueryParameters" -import {Utils} from "../../Utils" -import {RegexTag} from "../../Logic/Tags/RegexTag" +import { TagConfigJson } from "./Json/TagConfigJson" +import { UIEventSource } from "../../Logic/UIEventSource" +import { FilterState } from "../FilteredLayer" +import { QueryParameters } from "../../Logic/Web/QueryParameters" +import { Utils } from "../../Utils" +import { RegexTag } from "../../Logic/Tags/RegexTag" export default class FilterConfig { public readonly id: string diff --git a/Models/ThemeConfig/TagRenderingConfig.ts b/Models/ThemeConfig/TagRenderingConfig.ts index e12fdaa1a..e1f9de872 100644 --- a/Models/ThemeConfig/TagRenderingConfig.ts +++ b/Models/ThemeConfig/TagRenderingConfig.ts @@ -267,7 +267,10 @@ export default class TagRenderingConfig { if (this.freeform.key === "wikidata" && txt.indexOf("{wikipedia()") >= 0) { continue } - if (this.freeform.type === "wikidata" && txt.indexOf(`{wikidata_label(${this.freeform.key})`) >= 0) { + if ( + this.freeform.type === "wikidata" && + txt.indexOf(`{wikidata_label(${this.freeform.key})`) >= 0 + ) { continue } throw `${context}: The rendering for language ${ln} does not contain the freeform key {${this.freeform.key}}. This is a bug, as this rendering should show exactly this freeform key!\nThe rendering is ${txt} ` diff --git a/UI/Base/LinkToWeblate.ts b/UI/Base/LinkToWeblate.ts index 914854d6c..e6bc59a90 100644 --- a/UI/Base/LinkToWeblate.ts +++ b/UI/Base/LinkToWeblate.ts @@ -7,7 +7,6 @@ import Svg from "../../Svg" * The little 'translate'-icon next to every icon + some static helper functions */ export default class LinkToWeblate extends VariableUiElement { - constructor(context: string, availableTranslations: object) { super( Locale.language.map( diff --git a/UI/Base/Minimap.ts b/UI/Base/Minimap.ts index bbd764fb5..b7dccbe4e 100644 --- a/UI/Base/Minimap.ts +++ b/UI/Base/Minimap.ts @@ -3,7 +3,7 @@ import Loc from "../../Models/Loc" import BaseLayer from "../../Models/BaseLayer" import { UIEventSource } from "../../Logic/UIEventSource" import { BBox } from "../../Logic/BBox" -import {deprecate} from "util"; +import { deprecate } from "util" export interface MinimapOptions { background?: UIEventSource @@ -27,7 +27,7 @@ export interface MinimapObj { TakeScreenshot(format): Promise TakeScreenshot(format: "image"): Promise - TakeScreenshot(format:"blob"): Promise + TakeScreenshot(format: "blob"): Promise TakeScreenshot(format?: "image" | "blob"): Promise } diff --git a/UI/Base/MinimapImplementation.ts b/UI/Base/MinimapImplementation.ts index 3e507c223..dec687ca1 100644 --- a/UI/Base/MinimapImplementation.ts +++ b/UI/Base/MinimapImplementation.ts @@ -114,22 +114,22 @@ export default class MinimapImplementation extends BaseUIElement implements Mini * @param format: image: give a base64 encoded png image; * @constructor */ - public async TakeScreenshot(): Promise ; - public async TakeScreenshot(format: "image"): Promise ; - public async TakeScreenshot(format: "blob"): Promise ; - public async TakeScreenshot(format: "image" | "blob"): Promise ; + public async TakeScreenshot(): Promise + public async TakeScreenshot(format: "image"): Promise + public async TakeScreenshot(format: "blob"): Promise + public async TakeScreenshot(format: "image" | "blob"): Promise public async TakeScreenshot(format: "image" | "blob" = "image"): Promise { console.log("Taking a screenshot...") const screenshotter = new SimpleMapScreenshoter() screenshotter.addTo(this.leafletMap.data) - const result = await screenshotter.takeScreen(( format) ?? "image") - if(format === "image" && typeof result === "string"){ + const result = await screenshotter.takeScreen(format ?? "image") + if (format === "image" && typeof result === "string") { return result } - if(format === "blob" && result instanceof Blob){ + if (format === "blob" && result instanceof Blob) { return result } - throw "Something went wrong while creating the screenshot: "+result + throw "Something went wrong while creating the screenshot: " + result } protected InnerConstructElement(): HTMLElement { diff --git a/UI/BigComponents/PdfExportGui.ts b/UI/BigComponents/PdfExportGui.ts index f73ed9484..a55148160 100644 --- a/UI/BigComponents/PdfExportGui.ts +++ b/UI/BigComponents/PdfExportGui.ts @@ -1,62 +1,73 @@ -import Combine from "../Base/Combine"; -import {FlowPanelFactory, FlowStep} from "../ImportFlow/FlowStep"; -import {ImmutableStore, Store, UIEventSource} from "../../Logic/UIEventSource"; -import {InputElement} from "../Input/InputElement"; -import {SvgToPdf, SvgToPdfOptions} from "../../Utils/svgToPdf"; -import {FixedInputElement} from "../Input/FixedInputElement"; -import {FixedUiElement} from "../Base/FixedUiElement"; -import FileSelectorButton from "../Input/FileSelectorButton"; -import InputElementMap from "../Input/InputElementMap"; -import {RadioButton} from "../Input/RadioButton"; -import {Utils} from "../../Utils"; -import {VariableUiElement} from "../Base/VariableUIElement"; -import Loading from "../Base/Loading"; -import BaseUIElement from "../BaseUIElement"; -import Img from "../Base/Img"; -import Title from "../Base/Title"; -import {CheckBox} from "../Input/Checkboxes"; -import Minimap from "../Base/Minimap"; -import SearchAndGo from "./SearchAndGo"; -import Toggle from "../Input/Toggle"; -import List from "../Base/List"; -import LeftIndex from "../Base/LeftIndex"; -import Constants from "../../Models/Constants"; -import Toggleable from "../Base/Toggleable"; -import Lazy from "../Base/Lazy"; -import LinkToWeblate from "../Base/LinkToWeblate"; -import Link from "../Base/Link"; -import {SearchablePillsSelector} from "../Input/SearchableMappingsSelector"; +import Combine from "../Base/Combine" +import { FlowPanelFactory, FlowStep } from "../ImportFlow/FlowStep" +import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" +import { InputElement } from "../Input/InputElement" +import { SvgToPdf, SvgToPdfOptions } from "../../Utils/svgToPdf" +import { FixedInputElement } from "../Input/FixedInputElement" +import { FixedUiElement } from "../Base/FixedUiElement" +import FileSelectorButton from "../Input/FileSelectorButton" +import InputElementMap from "../Input/InputElementMap" +import { RadioButton } from "../Input/RadioButton" +import { Utils } from "../../Utils" +import { VariableUiElement } from "../Base/VariableUIElement" +import Loading from "../Base/Loading" +import BaseUIElement from "../BaseUIElement" +import Img from "../Base/Img" +import Title from "../Base/Title" +import { CheckBox } from "../Input/Checkboxes" +import Minimap from "../Base/Minimap" +import SearchAndGo from "./SearchAndGo" +import Toggle from "../Input/Toggle" +import List from "../Base/List" +import LeftIndex from "../Base/LeftIndex" +import Constants from "../../Models/Constants" +import Toggleable from "../Base/Toggleable" +import Lazy from "../Base/Lazy" +import LinkToWeblate from "../Base/LinkToWeblate" +import Link from "../Base/Link" +import { SearchablePillsSelector } from "../Input/SearchableMappingsSelector" import * as languages from "../../assets/language_translations.json" -import {Translation} from "../i18n/Translation"; +import { Translation } from "../i18n/Translation" -class SelectTemplate extends Combine implements FlowStep<{ title: string, pages: string[] }> { - readonly IsValid: Store; - readonly Value: Store<{ title: string, pages: string[] }>; +class SelectTemplate extends Combine implements FlowStep<{ title: string; pages: string[] }> { + readonly IsValid: Store + readonly Value: Store<{ title: string; pages: string[] }> constructor() { - const elements: InputElement<{ templateName: string, pages: string[] }>[] = [] + const elements: InputElement<{ templateName: string; pages: string[] }>[] = [] for (const templateName in SvgToPdf.templates) { const template = SvgToPdf.templates[templateName] - elements.push(new FixedInputElement( - new Combine([new FixedUiElement(templateName).SetClass("font-bold pr-2"), - template.description - ]) - , new UIEventSource({templateName, pages: template.pages}))) + elements.push( + new FixedInputElement( + new Combine([ + new FixedUiElement(templateName).SetClass("font-bold pr-2"), + template.description, + ]), + new UIEventSource({ templateName, pages: template.pages }) + ) + ) } - const file = new FileSelectorButton(new FixedUiElement("Select an svg image which acts as template"), { - acceptType: "image/svg+xml", - allowMultiple: true - }) - const fileMapped = new InputElementMap(file, (x0, x1) => x0 === x1, + const file = new FileSelectorButton( + new FixedUiElement("Select an svg image which acts as template"), + { + acceptType: "image/svg+xml", + allowMultiple: true, + } + ) + const fileMapped = new InputElementMap< + FileList, + { templateName: string; pages: string[]; fromFile: true } + >( + file, + (x0, x1) => x0 === x1, (filelist) => { if (filelist === undefined) { - return undefined; + return undefined } const pages = [] - let templateName: string = undefined; + let templateName: string = undefined for (const file of Array.from(filelist)) { - if (templateName == undefined) { templateName = file.name.substring(file.name.lastIndexOf("/") + 1) templateName = templateName.substring(0, templateName.lastIndexOf(".")) @@ -67,40 +78,46 @@ class SelectTemplate extends Combine implements FlowStep<{ title: string, pages: return { templateName, pages, - fromFile: true + fromFile: true, } - }, - _ => undefined + (_) => undefined ) elements.push(fileMapped) - const radio = new RadioButton(elements, {selectFirstAsDefault: true}) + const radio = new RadioButton(elements, { selectFirstAsDefault: true }) - const loaded: Store<{ success: { title: string, pages: string[] } } | { error: any }> = radio.GetValue().bind(template => { - if (template === undefined) { - return undefined - } - if (template["fromFile"]) { - return UIEventSource.FromPromiseWithErr(Promise.all(template.pages).then(pages => ({ + const loaded: Store<{ success: { title: string; pages: string[] } } | { error: any }> = + radio.GetValue().bind((template) => { + if (template === undefined) { + return undefined + } + if (template["fromFile"]) { + return UIEventSource.FromPromiseWithErr( + Promise.all(template.pages).then((pages) => ({ + title: template.templateName, + pages, + })) + ) + } + const urls = template.pages.map((p) => SelectTemplate.ToUrl(p)) + const dloadAll: Promise<{ title: string; pages: string[] }> = Promise.all( + urls.map((url) => Utils.download(url)) + ).then((pages) => ({ + pages, title: template.templateName, - pages - }))) - } - const urls = template.pages.map(p => SelectTemplate.ToUrl(p)) - const dloadAll: Promise<{ title: string, pages: string[] }> = Promise.all(urls.map(url => Utils.download(url))).then(pages => ({ - pages, - title: template.templateName - })) + })) - return UIEventSource.FromPromiseWithErr(dloadAll) - }) + return UIEventSource.FromPromiseWithErr(dloadAll) + }) const preview = new VariableUiElement( - loaded.map(pages => { + loaded.map((pages) => { if (pages === undefined) { return new Loading() } if (pages["error"] !== undefined) { - return new FixedUiElement("Loading preview failed: " + pages["err"]).SetClass("alert") + return new FixedUiElement("Loading preview failed: " + pages["err"]).SetClass( + "alert" + ) } const svgs = pages["success"].pages if (svgs.length === 0) { @@ -108,22 +125,16 @@ class SelectTemplate extends Combine implements FlowStep<{ title: string, pages: } const els: BaseUIElement[] = [] for (const pageSrc of svgs) { - const el = new Img(pageSrc, true) - .SetClass("w-96 m-2 border-black border-2") + const el = new Img(pageSrc, true).SetClass("w-96 m-2 border-black border-2") els.push(el) } - return new Combine(els).SetClass("flex border border-subtle rounded-xl"); + return new Combine(els).SetClass("flex border border-subtle rounded-xl") }) ) - super([ - new Title("Select template"), - radio, - new Title("Preview"), - preview - ]); - this.Value = loaded.map(l => l === undefined ? undefined : l["success"]) - this.IsValid = this.Value.map(v => v !== undefined) + super([new Title("Select template"), radio, new Title("Preview"), preview]) + this.Value = loaded.map((l) => (l === undefined ? undefined : l["success"])) + this.IsValid = this.Value.map((v) => v !== undefined) } public static ToUrl(spec: string) { @@ -134,63 +145,78 @@ class SelectTemplate extends Combine implements FlowStep<{ title: string, pages: path = path.substring(0, path.lastIndexOf("/")) return window.location.protocol + "//" + window.location.host + path + "/" + spec } - } -class SelectPdfOptions extends Combine implements FlowStep<{ title: string, pages: string[], options: SvgToPdfOptions }> { - readonly IsValid: Store; - readonly Value: Store<{ title: string, pages: string[], options: SvgToPdfOptions }>; +class SelectPdfOptions + extends Combine + implements FlowStep<{ title: string; pages: string[]; options: SvgToPdfOptions }> +{ + readonly IsValid: Store + readonly Value: Store<{ title: string; pages: string[]; options: SvgToPdfOptions }> constructor(title: string, pages: string[], getFreeDiv: () => string) { const dummy = new CheckBox("Don't add data to the map (to quickly preview the PDF)", false) - const overrideMapLocation = new CheckBox("Override map location: use a selected location instead of the location set in the template", false) + const overrideMapLocation = new CheckBox( + "Override map location: use a selected location instead of the location set in the template", + false + ) const locationInput = Minimap.createMiniMap().SetClass("block w-full") - const searchField = new SearchAndGo({leafletMap: locationInput.leafletMap}) - const selectLocation = - new Combine([ - new Toggle(new Combine([new Title("Select override location"), searchField]).SetClass("flex"), undefined, overrideMapLocation.GetValue()), - new Toggle(locationInput.SetStyle("height: 20rem"), undefined, overrideMapLocation.GetValue()).SetStyle("height: 20rem") - ]).SetClass("block").SetStyle("height: 25rem") - super([new Title("Select options"), - dummy, - overrideMapLocation, - selectLocation - ]); - this.Value = dummy.GetValue().map((disableMaps) => { - return { - pages, - title, - options: { - disableMaps, - getFreeDiv, - overrideLocation: overrideMapLocation.GetValue().data ? locationInput.location.data : undefined + const searchField = new SearchAndGo({ leafletMap: locationInput.leafletMap }) + const selectLocation = new Combine([ + new Toggle( + new Combine([new Title("Select override location"), searchField]).SetClass("flex"), + undefined, + overrideMapLocation.GetValue() + ), + new Toggle( + locationInput.SetStyle("height: 20rem"), + undefined, + overrideMapLocation.GetValue() + ).SetStyle("height: 20rem"), + ]) + .SetClass("block") + .SetStyle("height: 25rem") + super([new Title("Select options"), dummy, overrideMapLocation, selectLocation]) + this.Value = dummy.GetValue().map( + (disableMaps) => { + return { + pages, + title, + options: { + disableMaps, + getFreeDiv, + overrideLocation: overrideMapLocation.GetValue().data + ? locationInput.location.data + : undefined, + }, } - } - }, [overrideMapLocation.GetValue(), locationInput.location]) + }, + [overrideMapLocation.GetValue(), locationInput.location] + ) this.IsValid = new ImmutableStore(true) } - } -class PreparePdf extends Combine implements FlowStep<{ svgToPdf: SvgToPdf, languages: string[] }> { - readonly IsValid: Store; - readonly Value: Store<{ svgToPdf: SvgToPdf, languages: string[] }>; +class PreparePdf extends Combine implements FlowStep<{ svgToPdf: SvgToPdf; languages: string[] }> { + readonly IsValid: Store + readonly Value: Store<{ svgToPdf: SvgToPdf; languages: string[] }> constructor(title: string, pages: string[], options: SvgToPdfOptions) { const svgToPdf = new SvgToPdf(title, pages, options) const languageOptions = [ new FixedInputElement("Nederlands", "nl"), - new FixedInputElement("English", "en") + new FixedInputElement("English", "en"), ] const langs: string[] = Array.from(Object.keys(languages["default"] ?? languages)) console.log("Available languages are:", langs) const languageSelector = new SearchablePillsSelector( - langs.map(l => ({ + langs.map((l) => ({ show: new Translation(languages[l]), value: l, - mainTerm: languages[l] - })), { - mode: "select-many" + mainTerm: languages[l], + })), + { + mode: "select-many", } ) @@ -202,45 +228,54 @@ class PreparePdf extends Combine implements FlowStep<{ svgToPdf: SvgToPdf, langu new Toggle( new Loading("Preparing maps..."), undefined, - isPrepared.map(p => p === undefined) - ) - ]); - this.Value = isPrepared.map(isPrepped => { - if (isPrepped === undefined) { - return undefined - } - if (isPrepped["success"] !== undefined) { - const svgToPdf = isPrepped["success"] - const langs = languageSelector.GetValue().data - console.log("Languages are", langs) - if (langs.length === 0) { + isPrepared.map((p) => p === undefined) + ), + ]) + this.Value = isPrepared.map( + (isPrepped) => { + if (isPrepped === undefined) { return undefined } - return {svgToPdf, languages: langs} - } - return undefined; - }, [languageSelector.GetValue()]) - this.IsValid = this.Value.map(v => v !== undefined) + if (isPrepped["success"] !== undefined) { + const svgToPdf = isPrepped["success"] + const langs = languageSelector.GetValue().data + console.log("Languages are", langs) + if (langs.length === 0) { + return undefined + } + return { svgToPdf, languages: langs } + } + return undefined + }, + [languageSelector.GetValue()] + ) + this.IsValid = this.Value.map((v) => v !== undefined) } - } -class InspectStrings extends Toggle implements FlowStep<{ svgToPdf: SvgToPdf, languages: string[] }> { - readonly IsValid: Store; - readonly Value: Store<{ svgToPdf: SvgToPdf; languages: string[] }>; +class InspectStrings + extends Toggle + implements FlowStep<{ svgToPdf: SvgToPdf; languages: string[] }> +{ + readonly IsValid: Store + readonly Value: Store<{ svgToPdf: SvgToPdf; languages: string[] }> constructor(svgToPdf: SvgToPdf, languages: string[]) { + const didLoadLanguages = UIEventSource.FromPromiseWithErr( + svgToPdf.PrepareLanguages(languages) + ).map((l) => l !== undefined && l["success"] !== undefined) - const didLoadLanguages = UIEventSource.FromPromiseWithErr(svgToPdf.PrepareLanguages(languages)).map(l => l !== undefined && l["success"] !== undefined) - - super(new Combine([ + super( + new Combine([ new Title("Inspect translation strings"), - ...languages.map(l => new Lazy(() => InspectStrings.createOverviewPanel(svgToPdf, l))) + ...languages.map( + (l) => new Lazy(() => InspectStrings.createOverviewPanel(svgToPdf, l)) + ), ]), new Loading(), didLoadLanguages - ); - this.Value = new ImmutableStore({svgToPdf, languages}) + ) + this.Value = new ImmutableStore({ svgToPdf, languages }) this.IsValid = didLoadLanguages } @@ -259,64 +294,82 @@ class InspectStrings extends Toggle implements FlowStep<{ svgToPdf: SvgToPdf, la if (translated) { foundTranslations++ } - const linkToWeblate = new Link(spec, LinkToWeblate.hrefToWeblate(language, spec), true).SetClass("font-bold link-underline") - elements.push(new Combine([ - linkToWeblate, - " ", - translated ?? new FixedUiElement("No translation found!").SetClass("alert") - - ])) + const linkToWeblate = new Link( + spec, + LinkToWeblate.hrefToWeblate(language, spec), + true + ).SetClass("font-bold link-underline") + elements.push( + new Combine([ + linkToWeblate, + " ", + translated ?? new FixedUiElement("No translation found!").SetClass("alert"), + ]) + ) } return new Toggleable( new Title("Translations for " + language), new Combine([ - `${foundTranslations}/${allKeys.length} of translations are found (${Math.floor(100 * foundTranslations / allKeys.length)}%)`, + `${foundTranslations}/${allKeys.length} of translations are found (${Math.floor( + (100 * foundTranslations) / allKeys.length + )}%)`, "The following keys are used:", - new List(elements) + new List(elements), ]), - {closeOnClick: false, height: "15rem"}) + { closeOnClick: false, height: "15rem" } + ) } - } class SavePdf extends Combine { - constructor(svgToPdf: SvgToPdf, languages: string[]) { - super([ new Title("Generating your pdfs..."), - new List(languages.map(lng => new Toggle( - lng + " is done!", - new Loading("Creating pdf for " + lng), - UIEventSource.FromPromiseWithErr(svgToPdf.ConvertSvg(lng).then(() => true)) - .map(x => x !== undefined && x["success"] === true) - ))) - ]); + new List( + languages.map( + (lng) => + new Toggle( + lng + " is done!", + new Loading("Creating pdf for " + lng), + UIEventSource.FromPromiseWithErr( + svgToPdf.ConvertSvg(lng).then(() => true) + ).map((x) => x !== undefined && x["success"] === true) + ) + ) + ), + ]) } } export class PdfExportGui extends LeftIndex { - - constructor(freeDivId: string) { - let i = 0 const createDiv = (): string => { const div = document.createElement("div") - div.id = "freediv-" + (i++) + div.id = "freediv-" + i++ document.getElementById(freeDivId).append(div) return div.id } Constants.defaultOverpassUrls.splice(0, 1) - const {flow, furthestStep, titles} = FlowPanelFactory.start( - new Title("Select template"), new SelectTemplate() - ).then(new Title("Select options"), ({title, pages}) => new SelectPdfOptions(title, pages, createDiv)) - .then("Generate maps...", ({title, pages, options}) => new PreparePdf(title, pages, options)) - .then("Inspect translations", (({svgToPdf, languages}) => new InspectStrings(svgToPdf, languages))) - .finish("Generating...", ({svgToPdf, languages}) => new SavePdf(svgToPdf, languages)) - + const { flow, furthestStep, titles } = FlowPanelFactory.start( + new Title("Select template"), + new SelectTemplate() + ) + .then( + new Title("Select options"), + ({ title, pages }) => new SelectPdfOptions(title, pages, createDiv) + ) + .then( + "Generate maps...", + ({ title, pages, options }) => new PreparePdf(title, pages, options) + ) + .then( + "Inspect translations", + ({ svgToPdf, languages }) => new InspectStrings(svgToPdf, languages) + ) + .finish("Generating...", ({ svgToPdf, languages }) => new SavePdf(svgToPdf, languages)) const toc = new List( titles.map( @@ -338,9 +391,7 @@ export class PdfExportGui extends LeftIndex { true ) - const leftContents: BaseUIElement[] = [ - toc - ].map((el) => el?.SetClass("pl-4")) + const leftContents: BaseUIElement[] = [toc].map((el) => el?.SetClass("pl-4")) super(leftContents, flow) } diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index e01805883..24865c4da 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -26,7 +26,7 @@ import BaseLayer from "../../Models/BaseLayer" import Loading from "../Base/Loading" import Hash from "../../Logic/Web/Hash" import { GlobalFilter } from "../../Logic/State/MapState" -import {WayId} from "../../Models/OsmFeature"; +import { WayId } from "../../Models/OsmFeature" /* * The SimpleAddUI is a single panel, which can have multiple states: diff --git a/UI/Input/Checkboxes.ts b/UI/Input/Checkboxes.ts index 1a9253263..2c72fc4ee 100644 --- a/UI/Input/Checkboxes.ts +++ b/UI/Input/Checkboxes.ts @@ -3,10 +3,10 @@ import { UIEventSource } from "../../Logic/UIEventSource" import { Utils } from "../../Utils" import BaseUIElement from "../BaseUIElement" import InputElementMap from "./InputElementMap" -import Translations from "../i18n/Translations"; +import Translations from "../i18n/Translations" export class CheckBox extends InputElementMap { - constructor(el: (BaseUIElement | string), defaultValue?: boolean) { + constructor(el: BaseUIElement | string, defaultValue?: boolean) { super( new CheckBoxes([Translations.W(el)]), (x0, x1) => x0 === x1, diff --git a/UI/Input/LocationInput.ts b/UI/Input/LocationInput.ts index 83ab997d0..b2bc0ba10 100644 --- a/UI/Input/LocationInput.ts +++ b/UI/Input/LocationInput.ts @@ -1,38 +1,40 @@ -import {ReadonlyInputElement} from "./InputElement" +import { ReadonlyInputElement } from "./InputElement" import Loc from "../../Models/Loc" -import {Store, UIEventSource} from "../../Logic/UIEventSource" -import Minimap, {MinimapObj} from "../Base/Minimap" +import { Store, UIEventSource } from "../../Logic/UIEventSource" +import Minimap, { MinimapObj } from "../Base/Minimap" import BaseLayer from "../../Models/BaseLayer" import Combine from "../Base/Combine" import Svg from "../../Svg" -import {GeoOperations} from "../../Logic/GeoOperations" +import { GeoOperations } from "../../Logic/GeoOperations" import ShowDataMultiLayer from "../ShowDataLayer/ShowDataMultiLayer" import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import {BBox} from "../../Logic/BBox" -import {FixedUiElement} from "../Base/FixedUiElement" +import { BBox } from "../../Logic/BBox" +import { FixedUiElement } from "../Base/FixedUiElement" import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" import BaseUIElement from "../BaseUIElement" import Toggle from "./Toggle" import * as matchpoint from "../../assets/layers/matchpoint/matchpoint.json" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"; -import FilteredLayer from "../../Models/FilteredLayer"; -import {ElementStorage} from "../../Logic/ElementStorage"; -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; -import {RelationId, WayId} from "../../Models/OsmFeature"; -import {Feature, LineString, Polygon} from "geojson"; -import {OsmObject, OsmWay} from "../../Logic/Osm/OsmObject"; +import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import FilteredLayer from "../../Models/FilteredLayer" +import { ElementStorage } from "../../Logic/ElementStorage" +import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" +import { RelationId, WayId } from "../../Models/OsmFeature" +import { Feature, LineString, Polygon } from "geojson" +import { OsmObject, OsmWay } from "../../Logic/Osm/OsmObject" export default class LocationInput extends BaseUIElement - implements ReadonlyInputElement, MinimapObj { + implements ReadonlyInputElement, MinimapObj +{ private static readonly matchLayer = new LayerConfig( matchpoint, "LocationInput.matchpoint", true ) - public readonly snappedOnto: UIEventSource = new UIEventSource(undefined) + public readonly snappedOnto: UIEventSource = + new UIEventSource(undefined) public readonly _matching_layer: LayerConfig public readonly leafletMap: UIEventSource public readonly bounds @@ -43,13 +45,15 @@ export default class LocationInput * The features to which the input should be snapped * @private */ - private readonly _snapTo: Store< (Feature & {properties: {id : WayId}})[]> + private readonly _snapTo: Store< + (Feature & { properties: { id: WayId } })[] + > /** * The features to which the input should be snapped without cleanup of relations and memberships * Used for rendering * @private */ - private readonly _snapToRaw: Store< {feature: Feature}[]> + private readonly _snapToRaw: Store<{ feature: Feature }[]> private readonly _value: Store private readonly _snappedPoint: Store private readonly _maxSnapDistance: number @@ -59,10 +63,10 @@ export default class LocationInput private readonly clickLocation: UIEventSource private readonly _minZoom: number private readonly _state: { - readonly filteredLayers: Store; - readonly backgroundLayer: UIEventSource; - readonly layoutToUse: LayoutConfig; - readonly selectedElement: UIEventSource; + readonly filteredLayers: Store + readonly backgroundLayer: UIEventSource + readonly layoutToUse: LayoutConfig + readonly selectedElement: UIEventSource readonly allElements: ElementStorage } @@ -74,27 +78,35 @@ export default class LocationInput * * @private */ - private static async prepareSnapOnto(features: Feature[]): Promise<(Feature & {properties : {id: WayId}})[]> { - const linesAndPolygon : Feature[] = features.filter(f => f.geometry.type !== "Point") + private static async prepareSnapOnto( + features: Feature[] + ): Promise<(Feature & { properties: { id: WayId } })[]> { + const linesAndPolygon: Feature[] = ( + features.filter((f) => f.geometry.type !== "Point") + ) // Clean the features: multipolygons are split into their it's members - const linestrings : (Feature & {properties: {id: WayId}})[] = [] + const linestrings: (Feature & { properties: { id: WayId } })[] = [] for (const feature of linesAndPolygon) { - if(feature.properties.id.startsWith("way")){ + if (feature.properties.id.startsWith("way")) { // A normal way - we continue - linestrings.push( feature) + linestrings.push(feature) continue } // We have a multipolygon, thus: a relation // Download the members - const relation = await OsmObject.DownloadObjectAsync( feature.properties.id, 60 * 60) - const members: OsmWay[] = await Promise.all(relation.members - .filter(m => m.type === "way") - .map(m => OsmObject.DownloadObjectAsync( ("way/"+m.ref), 60 * 60))) - linestrings.push(...members.map(m => m.asGeoJson())) + const relation = await OsmObject.DownloadObjectAsync( + feature.properties.id, + 60 * 60 + ) + const members: OsmWay[] = await Promise.all( + relation.members + .filter((m) => m.type === "way") + .map((m) => OsmObject.DownloadObjectAsync(("way/" + m.ref), 60 * 60)) + ) + linestrings.push(...members.map((m) => m.asGeoJson())) } return linestrings - } constructor(options?: { @@ -107,20 +119,32 @@ export default class LocationInput centerLocation?: UIEventSource bounds?: UIEventSource state?: { - readonly filteredLayers: Store; - readonly backgroundLayer: UIEventSource; - readonly layoutToUse: LayoutConfig; - readonly selectedElement: UIEventSource; + readonly filteredLayers: Store + readonly backgroundLayer: UIEventSource + readonly layoutToUse: LayoutConfig + readonly selectedElement: UIEventSource readonly allElements: ElementStorage } }) { super() - this._snapToRaw = options?.snapTo?.map(feats => feats.filter(f => f.feature.geometry.type !== "Point")) - this._snapTo = options?.snapTo?.bind((features) => UIEventSource.FromPromise(LocationInput.prepareSnapOnto(features.map(f => f.feature))))?.map(f => f ?? []) + this._snapToRaw = options?.snapTo?.map((feats) => + feats.filter((f) => f.feature.geometry.type !== "Point") + ) + this._snapTo = options?.snapTo + ?.bind((features) => + UIEventSource.FromPromise( + LocationInput.prepareSnapOnto(features.map((f) => f.feature)) + ) + ) + ?.map((f) => f ?? []) this._maxSnapDistance = options?.maxSnapDistance - this._centerLocation = options?.centerLocation ?? new UIEventSource({ - lat: 0, lon: 0, zoom: 0 - }) + this._centerLocation = + options?.centerLocation ?? + new UIEventSource({ + lat: 0, + lon: 0, + zoom: 0, + }) this._snappedPointTags = options?.snappedPointTags this._bounds = options?.bounds this._minZoom = options?.minZoom @@ -152,11 +176,11 @@ export default class LocationInput return undefined } - // We reproject the location onto every 'snap-to-feature' and select the closest let min = undefined - let matchedWay: Feature & {properties : {id : WayId}} = undefined + let matchedWay: Feature & { properties: { id: WayId } } = + undefined for (const feature of self._snapTo.data ?? []) { try { const nearestPointOnLine = GeoOperations.nearestPoint(feature, [ @@ -191,18 +215,16 @@ export default class LocationInput return { type: "Feature", properties: options?.snappedPointTags ?? min.properties, - geometry: {type: "Point", coordinates: [loc.lon, loc.lat]}, + geometry: { type: "Point", coordinates: [loc.lon, loc.lat] }, } } } min.properties = options?.snappedPointTags ?? min.properties - if(matchedWay.properties.id.startsWith("relation/")){ + if (matchedWay.properties.id.startsWith("relation/")) { // We matched a relation instead of a way console.log("Snapping onto a relation. The relation is", matchedWay) - - } - self.snappedOnto.setData( matchedWay) + self.snappedOnto.setData(matchedWay) return min }, [this._snapTo] @@ -217,7 +239,10 @@ export default class LocationInput } }) } - this.mapBackground = options?.mapBackground ?? this._state?.backgroundLayer ?? new UIEventSource(AvailableBaseLayers.osmCarto) + this.mapBackground = + options?.mapBackground ?? + this._state?.backgroundLayer ?? + new UIEventSource(AvailableBaseLayers.osmCarto) this.SetClass("block h-full") this.clickLocation = new UIEventSource(undefined) @@ -249,7 +274,7 @@ export default class LocationInput try { const self = this const hasMoved = new UIEventSource(false) - const startLocation = {...this._centerLocation.data} + const startLocation = { ...this._centerLocation.data } this._centerLocation.addCallbackD((newLocation) => { const f = 100000 console.log(newLocation.lon, startLocation.lon) @@ -279,7 +304,7 @@ export default class LocationInput if (loc === undefined) { return [] } - return [{feature: loc}] + return [{ feature: loc }] }) console.log("Constructing the match layer", matchPoint) @@ -335,9 +360,9 @@ export default class LocationInput } } - TakeScreenshot(format: "image"): Promise; - TakeScreenshot(format: "blob"): Promise; - TakeScreenshot(format: "image" | "blob"): Promise; + TakeScreenshot(format: "image"): Promise + TakeScreenshot(format: "blob"): Promise + TakeScreenshot(format: "image" | "blob"): Promise TakeScreenshot(format: "image" | "blob"): Promise { return this.map.TakeScreenshot(format) } diff --git a/UI/NewPoint/ConfirmLocationOfPoint.ts b/UI/NewPoint/ConfirmLocationOfPoint.ts index 4afbfd779..76429a007 100644 --- a/UI/NewPoint/ConfirmLocationOfPoint.ts +++ b/UI/NewPoint/ConfirmLocationOfPoint.ts @@ -18,7 +18,7 @@ import Title from "../Base/Title" import { GlobalFilter } from "../../Logic/State/MapState" import { VariableUiElement } from "../Base/VariableUIElement" import { Tag } from "../../Logic/Tags/Tag" -import {WayId} from "../../Models/OsmFeature"; +import { WayId } from "../../Models/OsmFeature" export default class ConfirmLocationOfPoint extends Combine { constructor( @@ -76,7 +76,7 @@ export default class ConfirmLocationOfPoint extends Combine { snappedPointTags: tags, maxSnapDistance: preset.preciseInput.maxSnapDistance, bounds: mapBounds, - state: state + state: state, }) preciseInput.installBounds(preset.boundsFactor ?? 0.25, true) preciseInput diff --git a/UI/Popup/DeleteWizard.ts b/UI/Popup/DeleteWizard.ts index 2988c40fd..862e660de 100644 --- a/UI/Popup/DeleteWizard.ts +++ b/UI/Popup/DeleteWizard.ts @@ -22,7 +22,7 @@ import Title from "../Base/Title" import { SubstitutedTranslation } from "../SubstitutedTranslation" import FeaturePipelineState from "../../Logic/State/FeaturePipelineState" import TagRenderingQuestion from "./TagRenderingQuestion" -import {OsmId} from "../../Models/OsmFeature"; +import { OsmId } from "../../Models/OsmFeature" export default class DeleteWizard extends Toggle { /** diff --git a/UI/Popup/FeatureInfoBox.ts b/UI/Popup/FeatureInfoBox.ts index be00c7cb9..399b70640 100644 --- a/UI/Popup/FeatureInfoBox.ts +++ b/UI/Popup/FeatureInfoBox.ts @@ -248,29 +248,27 @@ export default class FeatureInfoBox extends ScrollableFullScreen { ) editElements.push( - Toggle.If(state.featureSwitchIsDebugging, - () => { - const config_all_tags: TagRenderingConfig = new TagRenderingConfig( - { render: "{all_tags()}" }, - "" - ) - const config_download: TagRenderingConfig = new TagRenderingConfig( - { render: "{export_as_geojson()}" }, - "" - ) - const config_id: TagRenderingConfig = new TagRenderingConfig( - { render: "{open_in_iD()}" }, - "" - ) - - return new Combine([ - new TagRenderingAnswer(tags, config_all_tags, state), - new TagRenderingAnswer(tags, config_download, state), - new TagRenderingAnswer(tags, config_id, state), - "This is layer " + layerConfig.id, - ]) - } + Toggle.If(state.featureSwitchIsDebugging, () => { + const config_all_tags: TagRenderingConfig = new TagRenderingConfig( + { render: "{all_tags()}" }, + "" ) + const config_download: TagRenderingConfig = new TagRenderingConfig( + { render: "{export_as_geojson()}" }, + "" + ) + const config_id: TagRenderingConfig = new TagRenderingConfig( + { render: "{open_in_iD()}" }, + "" + ) + + return new Combine([ + new TagRenderingAnswer(tags, config_all_tags, state), + new TagRenderingAnswer(tags, config_download, state), + new TagRenderingAnswer(tags, config_id, state), + "This is layer " + layerConfig.id, + ]) + }) ) return new Combine(editElements).SetClass("flex flex-col") diff --git a/UI/Popup/MoveWizard.ts b/UI/Popup/MoveWizard.ts index 0c051a0ac..41e3941cd 100644 --- a/UI/Popup/MoveWizard.ts +++ b/UI/Popup/MoveWizard.ts @@ -145,7 +145,7 @@ export default class MoveWizard extends Toggle { minZoom: reason.minZoom, centerLocation: loc, mapBackground: new UIEventSource(preferredBackground), // We detach the layer - state: state + state: state, }) if (reason.lockBounds) { diff --git a/UI/Popup/TagApplyButton.ts b/UI/Popup/TagApplyButton.ts index df5d22f34..d8bf2091b 100644 --- a/UI/Popup/TagApplyButton.ts +++ b/UI/Popup/TagApplyButton.ts @@ -51,18 +51,18 @@ export default class TagApplyButton implements AutoAction { * // Should handle escaped ";" * TagApplyButton.parseTagSpec("key=value;key0=value0\\;value1") // => [["key","value"],["key0","value0;value1"]] */ - private static parseTagSpec(spec: string): [string, string][]{ - const tgsSpec : [string, string][] = [] + private static parseTagSpec(spec: string): [string, string][] { + const tgsSpec: [string, string][] = [] - while(spec.length > 0){ + while (spec.length > 0) { const [part] = spec.match(/((\\;)|[^;])*/) spec = spec.substring(part.length + 1) // +1 to remove the pending ';' as well - const kv = part.split("=").map((s) => s.trim().replace("\\;",";")) + const kv = part.split("=").map((s) => s.trim().replace("\\;", ";")) if (kv.length == 2) { - tgsSpec.push(<[string, string]> kv) - }else if (kv.length < 2) { + tgsSpec.push(<[string, string]>kv) + } else if (kv.length < 2) { throw "Invalid key spec: no '=' found in " + spec - }else{ + } else { throw "Invalid key spec: multiple '=' found in " + spec } } @@ -83,7 +83,7 @@ export default class TagApplyButton implements AutoAction { spec = tagSource.data[spec.replace("$", "")] } - const tgsSpec = TagApplyButton.parseTagSpec(spec) + const tgsSpec = TagApplyButton.parseTagSpec(spec) return tagSource.map((tags) => { const newTags: Tag[] = [] diff --git a/UI/Popup/TagRenderingQuestion.ts b/UI/Popup/TagRenderingQuestion.ts index d83740da4..c8f3afd91 100644 --- a/UI/Popup/TagRenderingQuestion.ts +++ b/UI/Popup/TagRenderingQuestion.ts @@ -304,7 +304,7 @@ export default class TagRenderingQuestion extends Combine { const patchedMapping = { ...mapping, iconClass: mapping.iconClass ?? `small-height`, - icon: mapping.icon ?? (addIcons ? "./assets/svg/none.svg" : undefined) + icon: mapping.icon ?? (addIcons ? "./assets/svg/none.svg" : undefined), } const fancy = TagRenderingQuestion.GenerateMappingContent( patchedMapping, diff --git a/UI/ShowDataLayer/ShowTileInfo.ts b/UI/ShowDataLayer/ShowTileInfo.ts index 9536fdabf..9f4d4b4d5 100644 --- a/UI/ShowDataLayer/ShowTileInfo.ts +++ b/UI/ShowDataLayer/ShowTileInfo.ts @@ -10,12 +10,15 @@ import * as clusterstyle from "../../assets/layers/cluster_style/cluster_style.j export default class ShowTileInfo { public static readonly styling = new LayerConfig(clusterstyle, "ShowTileInfo", true) - constructor(options: { - source: FeatureSource & Tiled - leafletMap: UIEventSource - layer?: LayerConfig - doShowLayer?: UIEventSource - }, state) { + constructor( + options: { + source: FeatureSource & Tiled + leafletMap: UIEventSource + layer?: LayerConfig + doShowLayer?: UIEventSource + }, + state + ) { const source = options.source const metaFeature: Store<{ feature; freshness: Date }[]> = source.features.map( (features) => { @@ -55,7 +58,7 @@ export default class ShowTileInfo { features: new StaticFeatureSource(metaFeature), leafletMap: options.leafletMap, doShowLayer: options.doShowLayer, - state + state, }) } } diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index f3757507e..dc8080903 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -41,7 +41,10 @@ export default class Translations { * translation.textFor("nl") // => "Nederlands" * */ - static T(t: string | undefined | null | Translation | TypedTranslation, context = undefined): TypedTranslation { + static T( + t: string | undefined | null | Translation | TypedTranslation, + context = undefined + ): TypedTranslation { if (t === undefined || t === null) { return undefined } diff --git a/Utils.ts b/Utils.ts index 2a3901d24..8a169cd95 100644 --- a/Utils.ts +++ b/Utils.ts @@ -823,7 +823,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be } else if (xhr.status === 509 || xhr.status === 429) { reject("rate limited") } else { - reject("Could not download "+url+" due to "+xhr.statusText) + reject("Could not download " + url + " due to " + xhr.statusText) } } xhr.open("GET", url) diff --git a/all_themes_index.ts b/all_themes_index.ts index 3e0fe301f..fb15e2671 100644 --- a/all_themes_index.ts +++ b/all_themes_index.ts @@ -1,11 +1,11 @@ -import MinimapImplementation from "./UI/Base/MinimapImplementation"; +import MinimapImplementation from "./UI/Base/MinimapImplementation" import { Utils } from "./Utils" import AllThemesGui from "./UI/AllThemesGui" import { QueryParameters } from "./Logic/Web/QueryParameters" import StatisticsGUI from "./UI/StatisticsGUI" import { FixedUiElement } from "./UI/Base/FixedUiElement" -import {PdfExportGui} from "./UI/BigComponents/PdfExportGui"; +import { PdfExportGui } from "./UI/BigComponents/PdfExportGui" const layout = QueryParameters.GetQueryParameter("layout", undefined).data ?? "" const customLayout = QueryParameters.GetQueryParameter("userlayout", undefined).data ?? "" @@ -45,7 +45,7 @@ if (mode.data === "statistics") { console.log("Statistics mode!") new FixedUiElement("").AttachTo("centermessage") new StatisticsGUI().SetClass("w-full h-full pointer-events-auto").AttachTo("topleft-tools") -} else if(mode.data === "pdf"){ +} else if (mode.data === "pdf") { MinimapImplementation.initialize() new FixedUiElement("").AttachTo("centermessage") const div = document.createElement("div") diff --git a/scripts/thieves/stealLanguages.ts b/scripts/thieves/stealLanguages.ts index cc563e7d6..1f6bda27f 100644 --- a/scripts/thieves/stealLanguages.ts +++ b/scripts/thieves/stealLanguages.ts @@ -108,10 +108,11 @@ function main() { { id: "tactile_writing-braille", // @ts-ignore - description: "Enables to pick *multiple* 'tactile_writing:braille=' within the mappings", + description: + "Enables to pick *multiple* 'tactile_writing:braille=' within the mappings", multiAnswer: true, mappings: brailemappings, - } + }, ], } const dir = "./assets/layers/wikidata/"