Full code cleanup

This commit is contained in:
Pieter Vander Vennet 2022-01-26 21:40:38 +01:00
parent 3a4a2a2016
commit fa971ffbbf
300 changed files with 16352 additions and 19284 deletions

View file

@ -19,13 +19,13 @@ export default class Constants {
public static readonly added_by_default: string[] = ["gps_location", "gps_location_history", "home_location", "gps_track"]
public static readonly no_include: string[] = ["conflation", "left_right_style", "split_point","current_view","matchpoint"]
public static readonly no_include: string[] = ["conflation", "left_right_style", "split_point", "current_view", "matchpoint"]
/**
* Layer IDs of layers which have special properties through built-in hooks
*/
public static readonly priviliged_layers: string[] = [...Constants.added_by_default, "type_node", "note","import_candidate", ...Constants.no_include]
public static readonly priviliged_layers: string[] = [...Constants.added_by_default, "type_node", "note", "import_candidate", ...Constants.no_include]
// The user journey states thresholds when a new feature gets unlocked
public static userJourney = {
moreScreenUnlock: 1,
@ -54,13 +54,13 @@ export default class Constants {
* The point closest to the changed feature will be considered and this distance will be tracked.
* ALl these distances are used to calculate a nearby-score
*/
static nearbyVisitTime: number= 30 * 60;
static nearbyVisitTime: number = 30 * 60;
/**
* If a user makes a change, the distance to the changed object is calculated.
* If a user makes multiple changes, all these distances are put into multiple bins, depending on this distance.
* For every bin, the totals are uploaded as metadata
*/
static distanceToChangeObjectBins = [25,50,100,500,1000,5000, Number.MAX_VALUE]
static distanceToChangeObjectBins = [25, 50, 100, 500, 1000, 5000, Number.MAX_VALUE]
static themeOrder = ["personal", "cyclofix", "hailhydrant", "bookcases", "toilets", "aed"];
private static isRetina(): boolean {

View file

@ -3,7 +3,8 @@ import LayerConfig from "./ThemeConfig/LayerConfig";
import {TagsFilter} from "../Logic/Tags/TagsFilter";
export interface FilterState {
currentFilter: TagsFilter, state: string | number
currentFilter: TagsFilter,
state: string | number
}
export default interface FilteredLayer {

View file

@ -12,7 +12,7 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
*/
private readonly _includeClosedNotesDays: number;
constructor(includeClosedNotesDays= 0) {
constructor(includeClosedNotesDays = 0) {
super([
"Advanced conversion which deducts a layer showing all notes that are 'importable' (i.e. a note that contains a link to some MapComplete theme, with hash '#import').",
"The import buttons and matches will be based on the presets of the given theme",
@ -24,55 +24,55 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
const errors = []
const warnings = []
const t = Translations.t.importLayer;
/**
* The note itself will contain `tags=k=v;k=v;k=v;...
* This must be matched with a regex.
* This is a simple JSON-object as how it'll be put into the layerConfigJson directly
*/
const isShownIfAny : any[] = []
const isShownIfAny: any[] = []
const layer = new LayerConfig(layerJson, "while constructing a note-import layer")
for (const preset of layer.presets) {
const mustMatchAll = []
for (const tag of preset.tags) {
const key = tag.key
const value = tag.value
const condition = "_tags~(^|.*;)"+key+"\="+value+"($|;.*)"
const condition = "_tags~(^|.*;)" + key + "\=" + value + "($|;.*)"
mustMatchAll.push(condition)
}
isShownIfAny.push({and:mustMatchAll})
isShownIfAny.push({and: mustMatchAll})
}
const pointRenderings = (layerJson.mapRendering??[]).filter(r => r!== null && r["location"] !== undefined);
const firstRender = <PointRenderingConfigJson>(pointRenderings [0])
const pointRenderings = (layerJson.mapRendering ?? []).filter(r => r !== null && r["location"] !== undefined);
const firstRender = <PointRenderingConfigJson>(pointRenderings [0])
const icon = firstRender.icon
const iconBadges = []
const title = layer.presets[0].title
if(icon !== undefined){
if (icon !== undefined) {
iconBadges.push({
if: {and:[]},
then:icon
if: {and: []},
then: icon
})
}
const importButton = {}
{
const translations = t.importButton.Subs({layerId: layer.id, title: layer.presets[0].title}).translations
const translations = t.importButton.Subs({layerId: layer.id, title: layer.presets[0].title}).translations
for (const key in translations) {
importButton[key] = "{"+translations[key]+"}"
}
importButton[key] = "{" + translations[key] + "}"
}
}
function embed(prefix, translation: Translation, postfix){
function embed(prefix, translation: Translation, postfix) {
const result = {}
for (const language in translation.translations) {
result[language] = prefix+translation.translations[language] + postfix
result[language] = prefix + translation.translations[language] + postfix
}
return result
}
const result : LayerConfigJson = {
"id": "note_import_"+layer.id,
const result: LayerConfigJson = {
"id": "note_import_" + layer.id,
// By disabling the name, the import-layers won't pollute the filter view "name": t.layerName.Subs({title: layer.title.render}).translations,
"description": t.description.Subs({title: layer.title.render}).translations,
"source": {
@ -81,7 +81,7 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
"id~*"
]
},
"geoJson": "https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed="+this._includeClosedNotesDays+"&bbox={x_min},{y_min},{x_max},{y_max}",
"geoJson": "https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed=" + this._includeClosedNotesDays + "&bbox={x_min},{y_min},{x_max},{y_max}",
"geoJsonZoomLevel": 10,
"maxCacheAge": 0
},
@ -101,13 +101,15 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
"mappings": [
{
"if": "comments!~.*https://mapcomplete.osm.be.*",
"then":"no"
"then": "no"
},
{
"if": {and:
"if": {
and:
["_trigger_index~*",
{or: isShownIfAny}
]},
]
},
"then": "yes"
}
]
@ -135,12 +137,12 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
{
"id": "close_note_",
"render": embed(
"{close_note(", t.notFound.Subs({title}),", ./assets/svg/close.svg, id, This feature does not exist)}" ),
"{close_note(", t.notFound.Subs({title}), ", ./assets/svg/close.svg, id, This feature does not exist)}"),
condition: "closed_at="
},
{
"id": "close_note_mapped",
"render": embed("{close_note(",t.alreadyMapped.Subs({title}), ", ./assets/svg/checkmark.svg, id, Already mapped)}"),
"render": embed("{close_note(", t.alreadyMapped.Subs({title}), ", ./assets/svg/checkmark.svg, id, Already mapped)}"),
condition: "closed_at="
},
{
@ -164,9 +166,9 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
],
"icon": {
"render": "circle:white;help:black",
mappings:[{
if: {or:["closed_at~*","_imported=yes"]},
then:"circle:white;checkmark:black"
mappings: [{
if: {or: ["closed_at~*", "_imported=yes"]},
then: "circle:white;checkmark:black"
}]
},
iconBadges,
@ -174,8 +176,8 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L
}
]
}
return {
result,
errors, warnings

View file

@ -8,7 +8,6 @@ import {AllKnownLayouts} from "../../../Customizations/AllKnownLayouts";
import CreateNoteImportLayer from "./CreateNoteImportLayer";
import LayerConfig from "../LayerConfig";
import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson";
import {Translation} from "../../../UI/i18n/Translation";
import {SubstitutedTranslation} from "../../../UI/SubstitutedTranslation";
import DependencyCalculator from "../DependencyCalculator";
@ -126,12 +125,12 @@ class AddImportLayers extends DesugaringStep<LayoutConfigJson> {
convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
const errors = []
const warnings = []
json = {...json}
const allLayers: LayerConfigJson[] = <LayerConfigJson[]>json.layers;
json.layers = [...json.layers]
const creator = new CreateNoteImportLayer()
for (let i1 = 0; i1 < allLayers.length; i1++) {
const layer = allLayers[i1];
@ -191,10 +190,10 @@ export class AddMiniMap extends DesugaringStep<LayerConfigJson> {
static hasMinimap(renderingConfig: TagRenderingConfigJson): boolean {
const translations: any[] = Utils.NoNull([renderingConfig.render, ...(renderingConfig.mappings ?? []).map(m => m.then)]);
for (let translation of translations) {
if(typeof translation == "string"){
if (typeof translation == "string") {
translation = {"*": translation}
}
for (const key in translation) {
if (!translation.hasOwnProperty(key)) {
continue
@ -341,7 +340,7 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
constructor() {
super(
"Fully prepares and expands a theme",
new OnEveryConcat("layers", new SubstituteLayer()),
new SetDefault("socialImage", "assets/SocialImage.png", true),
new OnEvery("layers", new PrepareLayer()),

View file

@ -8,7 +8,7 @@ export default class DependencyCalculator {
public static GetTagRenderingDependencies(tr: TagRenderingConfig): string[] {
if(tr === undefined){
if (tr === undefined) {
throw "Got undefined tag rendering in getTagRenderingDependencies"
}
const deps: string[] = []
@ -74,11 +74,11 @@ export default class DependencyCalculator {
getFeatureById: _ => undefined,
getFeaturesWithin: (layerId, _) => {
if(layerId === '*'){
if (layerId === '*') {
// This is a wildcard
return []
}
// The important line: steal the dependencies!
deps.push({
neededLayer: layerId, reason: "A calculated tag loads features from this layer",

View file

@ -12,8 +12,8 @@ export default interface FilterConfigJson {
* Filtering is done based on the given osmTags that are compared to the objects in that layer.
*/
options: {
question: string | any;
osmTags?: AndOrTagConfigJson | string,
question: string | any;
osmTags?: AndOrTagConfigJson | string,
fields?: {
name: string,
type?: string | "string"

View file

@ -84,13 +84,13 @@ export interface LayerConfigJson {
*
* The specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),
* the expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.
*
*
* If a tag has to be evaluated strictly, use ':=' instead:
*
*
* [
* "_some_key:=some_javascript_expression"
* ]
*
*
*/
calculatedTags?: string[];
@ -124,7 +124,7 @@ export interface LayerConfigJson {
* can be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)
*/
shownByDefault?: true | boolean;
/**
* The zoom level at which point the data is hidden again
* Default: 100 (thus: always visible

View file

@ -9,7 +9,7 @@ export interface TagRenderingConfigJson {
/**
* The id of the tagrendering, should be an unique string.
* Used to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.
*
*
* Use 'questions' to trigger the question box of this group (if a group is defined)
*/
id?: string,

View file

@ -67,9 +67,9 @@ export default class LayerConfig extends WithContextLoader {
context = context + "." + json.id;
super(json, context)
this.id = json.id;
if(json.id === undefined){
throw "Not a valid layer: id is undefined: "+JSON.stringify(json)
if (json.id === undefined) {
throw "Not a valid layer: id is undefined: " + JSON.stringify(json)
}
if (json.source === undefined) {
@ -259,7 +259,7 @@ export default class LayerConfig extends WithContextLoader {
}
this.titleIcons = this.ParseTagRenderings((<TagRenderingConfigJson[]> json.titleIcons), {
this.titleIcons = this.ParseTagRenderings((<TagRenderingConfigJson[]>json.titleIcons), {
readOnlyMode: true
});
@ -375,9 +375,9 @@ export default class LayerConfig extends WithContextLoader {
return [
new Combine([
new Link(
"<img src='https://mapcomplete.osm.be/assets/svg/statistics.svg' height='18px'>",
"https://taginfo.openstreetmap.org/keys/"+values.key+"#values"
),Link.OsmWiki(values.key)
"<img src='https://mapcomplete.osm.be/assets/svg/statistics.svg' height='18px'>",
"https://taginfo.openstreetmap.org/keys/" + values.key + "#values"
), Link.OsmWiki(values.key)
]),
values.type === undefined ? "Multiple choice" : new Link(values.type, "../SpecialInputElements.md#" + values.type),
new Combine(embedded)

View file

@ -54,12 +54,12 @@ export default class LayoutConfig {
constructor(json: LayoutConfigJson, official = true, context?: string) {
this.official = official;
this.id = json.id;
if(official){
if(json.id.toLowerCase() !== json.id){
throw "The id of a theme should be lowercase: "+json.id
if (official) {
if (json.id.toLowerCase() !== json.id) {
throw "The id of a theme should be lowercase: " + json.id
}
if(json.id.match(/[a-z0-9-_]/) == null){
throw "The id of a theme should match [a-z0-9-_]*: "+json.id
if (json.id.match(/[a-z0-9-_]/) == null) {
throw "The id of a theme should match [a-z0-9-_]*: " + json.id
}
}
context = (context ?? "") + "." + this.id;
@ -102,9 +102,9 @@ export default class LayoutConfig {
this.descriptionTail = json.descriptionTail === undefined ? undefined : new Translation(json.descriptionTail, context + ".descriptionTail");
this.icon = json.icon;
this.socialImage = json.socialImage;
if(this.socialImage === null || this.socialImage === "" || this.socialImage === undefined){
if(official){
throw "Theme "+json.id+" has no social image defined"
if (this.socialImage === null || this.socialImage === "" || this.socialImage === undefined) {
if (official) {
throw "Theme " + json.id + " has no social image defined"
}
}
this.startZoom = json.startZoom;

View file

@ -44,7 +44,9 @@ export default class LineRenderingConfig extends WithContextLoader {
if (tags === undefined) {
return deflt
}
if(tr === undefined){return deflt}
if (tr === undefined) {
return deflt
}
const str = tr?.GetRenderValue(tags)?.txt ?? deflt;
if (str === "") {
return deflt
@ -59,7 +61,7 @@ export default class LineRenderingConfig extends WithContextLoader {
"--catch-detail-color"
);
}
const style = {
color,
dashArray,
@ -73,13 +75,13 @@ export default class LineRenderingConfig extends WithContextLoader {
if (fillStr !== undefined && fillStr !== "") {
style["fill"] = fillStr === "yes" || fillStr === "true"
}
const fillColorStr = render(this.fillColor, undefined)
if(fillColorStr !== undefined){
if (fillColorStr !== undefined) {
style["fillColor"] = fillColorStr
}
return style
}
}

View file

@ -69,7 +69,7 @@ export default class PointRenderingConfig extends WithContextLoader {
if (iconPath !== undefined && iconPath.startsWith(Utils.assets_path)) {
const iconKey = iconPath.substr(Utils.assets_path.length);
if (Svg.All[iconKey] === undefined) {
throw context+": builtin SVG asset not found: " + iconPath;
throw context + ": builtin SVG asset not found: " + iconPath;
}
}
this.iconSize = this.tr("iconSize", "40,40,center");
@ -209,16 +209,16 @@ export default class PointRenderingConfig extends WithContextLoader {
} else {
iconAndBadges.SetClass("w-full h-full")
}
let label = this.GetLabel(tags)
let htmlEl : BaseUIElement;
if(icon === undefined && label === undefined){
let htmlEl: BaseUIElement;
if (icon === undefined && label === undefined) {
htmlEl = undefined
}else if(icon === undefined){
} else if (icon === undefined) {
htmlEl = new Combine([label])
}else if(label === undefined){
htmlEl = new Combine([iconAndBadges])
}else {
} else if (label === undefined) {
htmlEl = new Combine([iconAndBadges])
} else {
htmlEl = new Combine([iconAndBadges, label]).SetStyle("flex flex-col")
}

View file

@ -45,6 +45,7 @@ export default class TagRenderingConfig {
readonly hideInAnswer: boolean | TagsFilter
readonly addExtraTags: Tag[]
}[]
constructor(json: string | TagRenderingConfigJson, context?: string) {
if (json === undefined) {
throw "Initing a TagRenderingConfig with undefined in " + context;
@ -373,8 +374,8 @@ export default class TagRenderingConfig {
return mapping.then;
}
if (mapping.if.matchesProperties(tags)) {
if(this.id === "uk_addresses_placename"){
console.log("Matched",mapping.if,"with ",tags["addr:place"])
if (this.id === "uk_addresses_placename") {
console.log("Matched", mapping.if, "with ", tags["addr:place"])
}
return mapping.then;
}
@ -487,12 +488,11 @@ export default class TagRenderingConfig {
mappings = new List(
this.mappings.map(m => {
let txt = "**" + m.then.txt + "** corresponds with " + m.if.asHumanString(true, false, {});
if(m.hideInAnswer === true)
{
if (m.hideInAnswer === true) {
txt += "_This option cannot be chosen as answer_"
}
if(m.ifnot !== undefined){
txt += "Unselecting this answer will add "+m.ifnot.asHumanString(true, false, {})
if (m.ifnot !== undefined) {
txt += "Unselecting this answer will add " + m.ifnot.asHumanString(true, false, {})
}
return txt;
}