forked from MapComplete/MapComplete
		
	chore: refactoring, linting, removing obsolete files
This commit is contained in:
		
							parent
							
								
									b7a4930583
								
							
						
					
					
						commit
						2bc2a6cddf
					
				
					 54 changed files with 125 additions and 457 deletions
				
			
		| 
						 | 
				
			
			@ -1,2 +1,3 @@
 | 
			
		|||
src/test.ts
 | 
			
		||||
android/*
 | 
			
		||||
src/assets/generated/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,4 +24,7 @@ module.exports = {
 | 
			
		|||
    browser: true,
 | 
			
		||||
    node: true,
 | 
			
		||||
  },
 | 
			
		||||
  rules:{
 | 
			
		||||
    '@typescript-eslint/no-explicit-any': 'off'
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ export class AllSharedLayers {
 | 
			
		|||
            if (layer.id === undefined) {
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            sharedLayers.set(layer.id, <any>layer)
 | 
			
		||||
            sharedLayers.set(layer.id, <LayerConfigJson>layer)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return sharedLayers
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ export class AllSharedLayers {
 | 
			
		|||
        const sharedLayers = new Map<string, LayerConfig>()
 | 
			
		||||
        for (const layer of known_layers["layers"]) {
 | 
			
		||||
            try {
 | 
			
		||||
                // @ts-ignore
 | 
			
		||||
                const parsed = new LayerConfig(layer, "shared_layers")
 | 
			
		||||
                sharedLayers.set(layer.id, parsed)
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,32 +27,30 @@ export class PreferredRasterLayerSelector {
 | 
			
		|||
        this._availableLayers = availableLayers
 | 
			
		||||
        this._queryParameter = queryParameter
 | 
			
		||||
        this._preferredBackgroundLayer = preferredBackgroundLayer
 | 
			
		||||
        const self = this
 | 
			
		||||
 | 
			
		||||
        this._rasterLayerSetting.addCallbackD((layer) => {
 | 
			
		||||
            this._queryParameter.setData(layer.properties.id)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        this._queryParameter.addCallbackAndRunD((_) => {
 | 
			
		||||
            const isApplied = self.updateLayer()
 | 
			
		||||
        this._queryParameter.addCallbackAndRunD(() => {
 | 
			
		||||
            const isApplied = this.updateLayer()
 | 
			
		||||
            if (!isApplied) {
 | 
			
		||||
                // A different layer was set as background
 | 
			
		||||
                // We remove this queryParameter instead
 | 
			
		||||
                self._queryParameter.setData(undefined)
 | 
			
		||||
                this._queryParameter.setData(undefined)
 | 
			
		||||
                return true // Unregister
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer())
 | 
			
		||||
        this._preferredBackgroundLayer.addCallbackD(() => this.updateLayer())
 | 
			
		||||
 | 
			
		||||
        rasterLayerSetting.addCallbackAndRunD((layer) => {
 | 
			
		||||
            if (AvailableRasterLayers.globalLayers.find((l) => l.id === layer.properties.id)) {
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            this._availableLayers.store.addCallbackD((_) => self.updateLayer())
 | 
			
		||||
            this._availableLayers.store.addCallbackD(() => this.updateLayer())
 | 
			
		||||
            return true // unregister
 | 
			
		||||
        })
 | 
			
		||||
        self.updateLayer()
 | 
			
		||||
        this.updateLayer()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,10 +83,9 @@ export default class FeaturePropertiesStore {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public trackFeatureSource(source: FeatureSource) {
 | 
			
		||||
        const self = this
 | 
			
		||||
        source.features.addCallbackAndRunD((features) => {
 | 
			
		||||
            for (const feature of features) {
 | 
			
		||||
                self.trackFeature(<any>feature)
 | 
			
		||||
                this.trackFeature(<any>feature)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ export default class PerLayerFeatureSourceSplitter<T extends FeatureSource = Fea
 | 
			
		|||
         * Keeps track of the ids that are included per layer.
 | 
			
		||||
         * Used to know if the downstream feature source needs to be pinged
 | 
			
		||||
         */
 | 
			
		||||
        let layerIndexes: ReadonlySet<string>[] = layers.map((_) => new Set<string>())
 | 
			
		||||
        let layerIndexes: ReadonlySet<string>[] = layers.map(() => new Set<string>())
 | 
			
		||||
        this.perLayer = knownLayers
 | 
			
		||||
        const layerSources = new Map<string, UIEventSource<Feature[]>>()
 | 
			
		||||
        const constructStore =
 | 
			
		||||
| 
						 | 
				
			
			@ -47,8 +47,8 @@ export default class PerLayerFeatureSourceSplitter<T extends FeatureSource = Fea
 | 
			
		|||
             * Indexed on layer-position
 | 
			
		||||
             * Will be true if a new id pops up
 | 
			
		||||
             */
 | 
			
		||||
            const hasChanged: boolean[] = layers.map((_) => false)
 | 
			
		||||
            const newIndices: Set<string>[] = layers.map((_) => new Set<string>())
 | 
			
		||||
            const hasChanged: boolean[] = layers.map(() => false)
 | 
			
		||||
            const newIndices: Set<string>[] = layers.map(() => new Set<string>())
 | 
			
		||||
            const noLayerFound: Feature[] = []
 | 
			
		||||
 | 
			
		||||
            for (const layer of layers) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,11 +23,10 @@ export default class FeatureSourceMerger<Src extends FeatureSource = FeatureSour
 | 
			
		|||
    constructor(...sources: Src[]) {
 | 
			
		||||
        this._featuresById = new UIEventSource<Map<string, Feature>>(new Map<string, Feature>())
 | 
			
		||||
        this.featuresById = this._featuresById
 | 
			
		||||
        const self = this
 | 
			
		||||
        sources = Utils.NoNull(sources)
 | 
			
		||||
        for (const source of sources) {
 | 
			
		||||
            source.features.addCallback(() => {
 | 
			
		||||
                self.addDataFromSources(sources)
 | 
			
		||||
                this.addDataFromSources(sources)
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        this._sources = sources
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,8 +38,7 @@ export class NewGeometryFromChangesFeatureSource implements WritableFeatureSourc
 | 
			
		|||
        this._seenChanges = new Set<ChangeDescription>()
 | 
			
		||||
        this._features = this.features.data
 | 
			
		||||
        this._backend = changes.backend
 | 
			
		||||
        const self = this
 | 
			
		||||
        changes.pendingChanges.addCallbackAndRunD((changes) => self.handleChanges(changes))
 | 
			
		||||
        changes.pendingChanges.addCallbackAndRunD((changes) => this.handleChanges(changes))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private addNewFeature(feature: Feature) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -161,7 +161,6 @@ export default class OsmFeatureSource extends FeatureSourceMerger {
 | 
			
		|||
                this.options?.fullNodeDatabase?.handleOsmJson(osmJson, z, x, y)
 | 
			
		||||
                let features = <Feature<any, { id: string }>[]>OsmToGeoJson(
 | 
			
		||||
                    osmJson,
 | 
			
		||||
                    // @ts-ignore
 | 
			
		||||
                    {
 | 
			
		||||
                        flatProperties: true,
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +174,7 @@ export default class OsmFeatureSource extends FeatureSourceMerger {
 | 
			
		|||
                )
 | 
			
		||||
 | 
			
		||||
                for (let i = 0; i < features.length; i++) {
 | 
			
		||||
                    features[i] = await this.patchIncompleteRelations(features[i], osmJson)
 | 
			
		||||
                    features[i] = await this.patchIncompleteRelations(features[i], <any> osmJson)
 | 
			
		||||
                }
 | 
			
		||||
                features = Utils.NoNull(features)
 | 
			
		||||
                features.forEach((f) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import { BBox } from "../../BBox"
 | 
			
		|||
import { Utils } from "../../../Utils"
 | 
			
		||||
import { Feature } from "geojson"
 | 
			
		||||
import { GeoOperations } from "../../GeoOperations"
 | 
			
		||||
import DynamicTileSource, { UpdatableDynamicTileSource } from "./DynamicTileSource"
 | 
			
		||||
import { UpdatableDynamicTileSource } from "./DynamicTileSource"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The PolygonSourceMerger receives various small pieces of bigger polygons and stitches them together.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -370,7 +370,7 @@ export class GeoOperations {
 | 
			
		|||
    ): Feature<LineString | MultiLineString>[] {
 | 
			
		||||
        if (way.geometry.type === "Polygon") {
 | 
			
		||||
            const poly: Feature<Polygon> = <Feature<Polygon>>way
 | 
			
		||||
            return poly.geometry.coordinates.map((linestringCoors, i) => {
 | 
			
		||||
            return poly.geometry.coordinates.map(linestringCoors => {
 | 
			
		||||
                return <Feature<LineString>>{
 | 
			
		||||
                    type: "Feature",
 | 
			
		||||
                    geometry: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ export default class GenericImageProvider extends ImageProvider {
 | 
			
		|||
        return undefined
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DownloadAttribution(_) {
 | 
			
		||||
    public DownloadAttribution() {
 | 
			
		||||
        return undefined
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,6 @@ export default class InsertPointIntoWayAction {
 | 
			
		|||
        console.log("Attempting to snap:", { geojson, projected, projectedCoor, index })
 | 
			
		||||
        // We check that it isn't close to an already existing point
 | 
			
		||||
        let reusedPointId = undefined
 | 
			
		||||
        let reusedPointCoordinates: [number, number] = undefined
 | 
			
		||||
        let outerring: [number, number][]
 | 
			
		||||
 | 
			
		||||
        if (geojson.geometry.type === "LineString") {
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +61,6 @@ export default class InsertPointIntoWayAction {
 | 
			
		|||
        ) {
 | 
			
		||||
            // We reuse this point instead!
 | 
			
		||||
            reusedPointId = this._snapOnto.nodes[index]
 | 
			
		||||
            reusedPointCoordinates = this._snapOnto.coordinates[index]
 | 
			
		||||
        }
 | 
			
		||||
        const next = outerring[index + 1]
 | 
			
		||||
        if (
 | 
			
		||||
| 
						 | 
				
			
			@ -71,14 +69,13 @@ export default class InsertPointIntoWayAction {
 | 
			
		|||
        ) {
 | 
			
		||||
            // We reuse this point instead!
 | 
			
		||||
            reusedPointId = this._snapOnto.nodes[index + 1]
 | 
			
		||||
            reusedPointCoordinates = this._snapOnto.coordinates[index + 1]
 | 
			
		||||
        }
 | 
			
		||||
        if (reusedPointId !== undefined) {
 | 
			
		||||
            return undefined
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const locations = [
 | 
			
		||||
            ...this._snapOnto.coordinates?.map(([lat, lon]) => <[number, number]>[lon, lat]),
 | 
			
		||||
            ...(this._snapOnto.coordinates ?? []).map(([lat, lon]) => <[number, number]>[lon, lat]),
 | 
			
		||||
        ]
 | 
			
		||||
        const ids = [...this._snapOnto.nodes]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -181,7 +181,7 @@ export class InPlaceReplacedmentRTSH extends AbstractRelationSplitHandler {
 | 
			
		|||
        super(input, theme, objectDownloader)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
 | 
			
		||||
    async CreateChangeDescriptions(): Promise<ChangeDescription[]> {
 | 
			
		||||
        const wayId = this._input.originalWayId
 | 
			
		||||
        const relation = this._input.relation
 | 
			
		||||
        const members = relation.members
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -382,7 +382,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr
 | 
			
		|||
        >()
 | 
			
		||||
        {
 | 
			
		||||
            // Lets check the unused ids: can they be detached or do they signify some relation with the object?
 | 
			
		||||
            unusedIds.forEach(({}, id) => {
 | 
			
		||||
            unusedIds.forEach((_, id) => {
 | 
			
		||||
                const info = nodeInfo.get(id)
 | 
			
		||||
                if (!(info.hasTags || info.partOfWay)) {
 | 
			
		||||
                    // Nothing special here, we detach
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,9 +144,6 @@ export default class SplitAction extends OsmChangeAction {
 | 
			
		|||
                // Copy the tags from the original object onto the new
 | 
			
		||||
                const kv = []
 | 
			
		||||
                for (const k in originalElement.tags) {
 | 
			
		||||
                    if (!originalElement.tags.hasOwnProperty(k)) {
 | 
			
		||||
                        continue
 | 
			
		||||
                    }
 | 
			
		||||
                    if (k.startsWith("_") || k === "id") {
 | 
			
		||||
                        continue
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,200 +0,0 @@
 | 
			
		|||
export default class AspectedRouting {
 | 
			
		||||
    public readonly name: string
 | 
			
		||||
    public readonly description: string
 | 
			
		||||
    public readonly units: string
 | 
			
		||||
    public readonly program: any
 | 
			
		||||
 | 
			
		||||
    public constructor(program) {
 | 
			
		||||
        this.name = program.name
 | 
			
		||||
        this.description = program.description
 | 
			
		||||
        this.units = program.unit
 | 
			
		||||
        this.program = JSON.parse(JSON.stringify(program))
 | 
			
		||||
        delete this.program.name
 | 
			
		||||
        delete this.program.description
 | 
			
		||||
        delete this.program.unit
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Interprets the given Aspected-routing program for the given properties
 | 
			
		||||
     */
 | 
			
		||||
    public static interpret(program: any, properties: any) {
 | 
			
		||||
        if (typeof program !== "object") {
 | 
			
		||||
            return program
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let functionName /*: string*/ = undefined
 | 
			
		||||
        let functionArguments /*: any */ = undefined
 | 
			
		||||
        const otherValues = {}
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        Object.entries(program).forEach((tag) => {
 | 
			
		||||
            const [key, value] = tag
 | 
			
		||||
            if (key.startsWith("$")) {
 | 
			
		||||
                functionName = key
 | 
			
		||||
                functionArguments = value
 | 
			
		||||
            } else {
 | 
			
		||||
                otherValues[key] = value
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (functionName === undefined) {
 | 
			
		||||
            return AspectedRouting.interpretAsDictionary(program, properties)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (functionName === "$multiply") {
 | 
			
		||||
            return AspectedRouting.multiplyScore(properties, functionArguments)
 | 
			
		||||
        } else if (functionName === "$firstMatchOf") {
 | 
			
		||||
            return AspectedRouting.getFirstMatchScore(properties, functionArguments)
 | 
			
		||||
        } else if (functionName === "$min") {
 | 
			
		||||
            return AspectedRouting.getMinValue(properties, functionArguments)
 | 
			
		||||
        } else if (functionName === "$max") {
 | 
			
		||||
            return AspectedRouting.getMaxValue(properties, functionArguments)
 | 
			
		||||
        } else if (functionName === "$default") {
 | 
			
		||||
            return AspectedRouting.defaultV(functionArguments, otherValues, properties)
 | 
			
		||||
        } else {
 | 
			
		||||
            console.error(
 | 
			
		||||
                `Error: Program ${functionName} is not implemented yet. ${JSON.stringify(program)}`
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Given a 'program' without function invocation, interprets it as a dictionary
 | 
			
		||||
     *
 | 
			
		||||
     * E.g., given the program
 | 
			
		||||
     *
 | 
			
		||||
     * {
 | 
			
		||||
     *     highway: {
 | 
			
		||||
     *         residential: 30,
 | 
			
		||||
     *         living_street: 20
 | 
			
		||||
     *     },
 | 
			
		||||
     *     surface: {
 | 
			
		||||
     *         sett : 0.9
 | 
			
		||||
     *     }
 | 
			
		||||
     *
 | 
			
		||||
     * }
 | 
			
		||||
     *
 | 
			
		||||
     * in combination with the tags {highway: residential},
 | 
			
		||||
     *
 | 
			
		||||
     * the result should be [30, undefined];
 | 
			
		||||
     *
 | 
			
		||||
     * For the tags {highway: residential, surface: sett} we should get [30, 0.9]
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
     * @param program
 | 
			
		||||
     * @param tags
 | 
			
		||||
     * @return {(undefined|*)[]}
 | 
			
		||||
     */
 | 
			
		||||
    private static interpretAsDictionary(program, tags) {
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        return Object.entries(tags).map((tag) => {
 | 
			
		||||
            const [key, value] = tag
 | 
			
		||||
            const propertyValue = program[key]
 | 
			
		||||
            if (propertyValue === undefined) {
 | 
			
		||||
                return undefined
 | 
			
		||||
            }
 | 
			
		||||
            if (typeof propertyValue !== "object") {
 | 
			
		||||
                return propertyValue
 | 
			
		||||
            }
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            return propertyValue[value]
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static defaultV(subProgram, otherArgs, tags) {
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        const normalProgram = Object.entries(otherArgs)[0][1]
 | 
			
		||||
        const value = AspectedRouting.interpret(normalProgram, tags)
 | 
			
		||||
        if (value !== undefined) {
 | 
			
		||||
            return value
 | 
			
		||||
        }
 | 
			
		||||
        return AspectedRouting.interpret(subProgram, tags)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Multiplies the default score with the proper values
 | 
			
		||||
     * @param tags {object} the active tags to check against
 | 
			
		||||
     * @param subprograms which should generate a list of values
 | 
			
		||||
     * @returns score after multiplication
 | 
			
		||||
     */
 | 
			
		||||
    private static multiplyScore(tags, subprograms) {
 | 
			
		||||
        let number = 1
 | 
			
		||||
 | 
			
		||||
        let subResults: any[]
 | 
			
		||||
        if (subprograms.length !== undefined) {
 | 
			
		||||
            subResults = AspectedRouting.concatMap(subprograms, (subprogram) =>
 | 
			
		||||
                AspectedRouting.interpret(subprogram, tags)
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            subResults = AspectedRouting.interpret(subprograms, tags)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        subResults.filter((r) => r !== undefined).forEach((r) => (number *= parseFloat(r)))
 | 
			
		||||
        return number.toFixed(2)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static getFirstMatchScore(tags, order: any) {
 | 
			
		||||
        /*Order should be a list of arguments after evaluation*/
 | 
			
		||||
        order = <string[]>AspectedRouting.interpret(order, tags)
 | 
			
		||||
        for (const key of order) {
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            for (const entry of Object.entries(JSON.parse(tags))) {
 | 
			
		||||
                const [tagKey, value] = entry
 | 
			
		||||
                if (key === tagKey) {
 | 
			
		||||
                    // We have a match... let's evaluate the subprogram
 | 
			
		||||
                    const evaluated = AspectedRouting.interpret(value, tags)
 | 
			
		||||
                    if (evaluated !== undefined) {
 | 
			
		||||
                        return evaluated
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Not a single match found...
 | 
			
		||||
        return undefined
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static getMinValue(tags, subprogram) {
 | 
			
		||||
        const minArr = subprogram
 | 
			
		||||
            .map((part) => {
 | 
			
		||||
                if (typeof part === "object") {
 | 
			
		||||
                    const calculatedValue = this.interpret(part, tags)
 | 
			
		||||
                    return parseFloat(calculatedValue)
 | 
			
		||||
                } else {
 | 
			
		||||
                    return parseFloat(part)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .filter((v) => !isNaN(v))
 | 
			
		||||
        return Math.min(...minArr)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static getMaxValue(tags, subprogram) {
 | 
			
		||||
        const maxArr = subprogram
 | 
			
		||||
            .map((part) => {
 | 
			
		||||
                if (typeof part === "object") {
 | 
			
		||||
                    return parseFloat(AspectedRouting.interpret(part, tags))
 | 
			
		||||
                } else {
 | 
			
		||||
                    return parseFloat(part)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            .filter((v) => !isNaN(v))
 | 
			
		||||
        return Math.max(...maxArr)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static concatMap(list, f): any[] {
 | 
			
		||||
        const result = []
 | 
			
		||||
        list = list.map(f)
 | 
			
		||||
        for (const elem of list) {
 | 
			
		||||
            if (elem.length !== undefined) {
 | 
			
		||||
                // This is a list
 | 
			
		||||
                result.push(...elem)
 | 
			
		||||
            } else {
 | 
			
		||||
                result.push(elem)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public evaluate(properties) {
 | 
			
		||||
        return AspectedRouting.interpret(this.program, properties)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,6 @@ import { ExtraFuncParams, ExtraFunctions } from "../../Logic/ExtraFunctions"
 | 
			
		|||
import LayerConfig from "./LayerConfig"
 | 
			
		||||
import { SpecialVisualization } from "../../UI/SpecialVisualization"
 | 
			
		||||
import SpecialVisualizations from "../../UI/SpecialVisualizations"
 | 
			
		||||
import { LayerConfigJson } from "./Json/LayerConfigJson"
 | 
			
		||||
 | 
			
		||||
export default class DependencyCalculator {
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ import { TagsFilter } from "../../Logic/Tags/TagsFilter"
 | 
			
		|||
import { TagUtils } from "../../Logic/Tags/TagUtils"
 | 
			
		||||
import { Utils } from "../../Utils"
 | 
			
		||||
import WithContextLoader from "./WithContextLoader"
 | 
			
		||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
 | 
			
		||||
import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
import BaseUIElement from "../../UI/BaseUIElement"
 | 
			
		||||
import { FixedUiElement } from "../../UI/Base/FixedUiElement"
 | 
			
		||||
import Combine from "../../UI/Base/Combine"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,6 @@
 | 
			
		|||
  import { ariaLabelStore } from "../../Utils/ariaLabel"
 | 
			
		||||
  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
			
		||||
  import Center from "../../assets/svg/Center.svelte"
 | 
			
		||||
  import Tr from "./Tr.svelte"
 | 
			
		||||
 | 
			
		||||
  export let state: SpecialVisualizationState
 | 
			
		||||
  export let feature: Feature
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,5 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import { createEventDispatcher } from "svelte"
 | 
			
		||||
  import { ariaLabel } from "../../Utils/ariaLabel"
 | 
			
		||||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
 | 
			
		||||
  import { CloseButton } from "flowbite-svelte"
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import { Utils } from "../../Utils"
 | 
			
		||||
import BaseUIElement from "../BaseUIElement"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +57,6 @@ export default class Img extends BaseUIElement {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    protected InnerConstructElement(): HTMLElement {
 | 
			
		||||
        const self = this
 | 
			
		||||
        if (this._rawSvg) {
 | 
			
		||||
            const e = document.createElement("div")
 | 
			
		||||
            e.innerHTML = this._src
 | 
			
		||||
| 
						 | 
				
			
			@ -69,12 +69,12 @@ export default class Img extends BaseUIElement {
 | 
			
		|||
            el.style.opacity = "1"
 | 
			
		||||
        }
 | 
			
		||||
        el.onerror = () => {
 | 
			
		||||
            if (self._options?.fallbackImage) {
 | 
			
		||||
                if (el.src === self._options.fallbackImage) {
 | 
			
		||||
            if (this._options?.fallbackImage) {
 | 
			
		||||
                if (el.src === this._options.fallbackImage) {
 | 
			
		||||
                    // Sigh... nothing to be done anymore
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
                el.src = self._options.fallbackImage
 | 
			
		||||
                el.src = this._options.fallbackImage
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return el
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,5 @@
 | 
			
		|||
import BaseUIElement from "../BaseUIElement"
 | 
			
		||||
import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
import { UIElement } from "../UIElement"
 | 
			
		||||
import SvelteUIElement from "./SvelteUIElement"
 | 
			
		||||
import SubtleLink from "./SubtleLink.svelte"
 | 
			
		||||
import Translations from "../i18n/Translations"
 | 
			
		||||
import Combine from "./Combine"
 | 
			
		||||
import Img from "./Img"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,44 +10,24 @@ import Img from "./Img"
 | 
			
		|||
export class SubtleButton extends UIElement {
 | 
			
		||||
    private readonly imageUrl: string | BaseUIElement
 | 
			
		||||
    private readonly message: string | BaseUIElement
 | 
			
		||||
    private readonly options: {
 | 
			
		||||
        url?: string | Store<string>
 | 
			
		||||
        newTab?: boolean
 | 
			
		||||
        imgSize?: string
 | 
			
		||||
        extraClasses?: string
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        imageUrl: string | BaseUIElement,
 | 
			
		||||
        message: string | BaseUIElement,
 | 
			
		||||
        options: {
 | 
			
		||||
            url?: string | Store<string>
 | 
			
		||||
            newTab?: boolean
 | 
			
		||||
            imgSize?: "h-11 w-11" | string
 | 
			
		||||
            extraClasses?: string
 | 
			
		||||
        } = {}
 | 
			
		||||
        message: string | BaseUIElement
 | 
			
		||||
    ) {
 | 
			
		||||
        super()
 | 
			
		||||
        this.imageUrl = imageUrl
 | 
			
		||||
        this.message = message
 | 
			
		||||
        this.options = options
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected InnerRender(): string | BaseUIElement {
 | 
			
		||||
        if (this.options.url !== undefined) {
 | 
			
		||||
            return new SvelteUIElement(SubtleLink, {
 | 
			
		||||
                href: this.options.url,
 | 
			
		||||
                newTab: this.options.newTab,
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const classes = "button"
 | 
			
		||||
        const message = Translations.W(this.message)?.SetClass(
 | 
			
		||||
            "block overflow-ellipsis no-images flex-shrink"
 | 
			
		||||
        )
 | 
			
		||||
        let img
 | 
			
		||||
        const imgClasses =
 | 
			
		||||
            "block justify-center flex-none mr-4 " + (this.options?.imgSize ?? "h-11 w-11")
 | 
			
		||||
            "block justify-center flex-none mr-4 h-11 w-11"
 | 
			
		||||
        if ((this.imageUrl ?? "") === "") {
 | 
			
		||||
            img = undefined
 | 
			
		||||
        } else if (typeof this.imageUrl === "string") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,50 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import { onMount } from "svelte"
 | 
			
		||||
  import { twJoin, twMerge } from "tailwind-merge"
 | 
			
		||||
  import BaseUIElement from "../BaseUIElement"
 | 
			
		||||
  import Img from "./Img"
 | 
			
		||||
 | 
			
		||||
  export let imageUrl: string | BaseUIElement = undefined
 | 
			
		||||
  export let href: string
 | 
			
		||||
  export let newTab = false
 | 
			
		||||
  export let options: {
 | 
			
		||||
    imgSize?: string
 | 
			
		||||
    extraClasses?: string
 | 
			
		||||
  } = {}
 | 
			
		||||
 | 
			
		||||
  let imgElem: HTMLElement
 | 
			
		||||
  let imgClasses = twJoin("block justify-center shrink-0 mr-4", options?.imgSize ?? "h-11 w-11")
 | 
			
		||||
 | 
			
		||||
  onMount(() => {
 | 
			
		||||
    // Image
 | 
			
		||||
    if (imgElem && imageUrl) {
 | 
			
		||||
      let img: BaseUIElement
 | 
			
		||||
 | 
			
		||||
      if ((imageUrl ?? "") === "") {
 | 
			
		||||
        img = undefined
 | 
			
		||||
      } else if (typeof imageUrl !== "string") {
 | 
			
		||||
        img = imageUrl?.SetClass(imgClasses)
 | 
			
		||||
      }
 | 
			
		||||
      if (img) imgElem.replaceWith(img.ConstructElement())
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<a
 | 
			
		||||
  class={twMerge(options.extraClasses, "button text-ellipsis")}
 | 
			
		||||
  {href}
 | 
			
		||||
  target={newTab ? "_blank" : undefined}
 | 
			
		||||
  rel={newTab ? "noopener" : undefined}
 | 
			
		||||
>
 | 
			
		||||
  <slot name="image">
 | 
			
		||||
    {#if imageUrl !== undefined}
 | 
			
		||||
      {#if typeof imageUrl === "string"}
 | 
			
		||||
        <Img src={imageUrl} class={imgClasses} />
 | 
			
		||||
      {:else}
 | 
			
		||||
        <template bind:this={imgElem} />
 | 
			
		||||
      {/if}
 | 
			
		||||
    {/if}
 | 
			
		||||
  </slot>
 | 
			
		||||
 | 
			
		||||
  <slot />
 | 
			
		||||
</a>
 | 
			
		||||
| 
						 | 
				
			
			@ -5,9 +5,10 @@
 | 
			
		|||
  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
			
		||||
  import UserRelatedState from "../../Logic/State/UserRelatedState"
 | 
			
		||||
  import type { Feature } from "geojson"
 | 
			
		||||
  import { ImmutableStore } from "../../Logic/UIEventSource"
 | 
			
		||||
 | 
			
		||||
  const t = Translations.t.privacy
 | 
			
		||||
  export let state: SpecialVisualizationState
 | 
			
		||||
  export let state: Partial<SpecialVisualizationState>
 | 
			
		||||
  const usersettings = UserRelatedState.usersettingsConfig
 | 
			
		||||
  const editPrivacy = usersettings.tagRenderings.find((tr) => tr.id === "more_privacy")
 | 
			
		||||
  const editThemeHistory = usersettings.tagRenderings.find((tr) => tr.id === "sync-visited-themes")
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +23,7 @@
 | 
			
		|||
    properties: { id: "settings" },
 | 
			
		||||
    geometry: { type: "Point", coordinates: [0, 0] },
 | 
			
		||||
  }
 | 
			
		||||
  const isLoggedIn = state.osmConnection.isLoggedIn
 | 
			
		||||
  const isLoggedIn = state?.osmConnection?.isLoggedIn ?? new ImmutableStore(false)
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="link-underline flex flex-col">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@
 | 
			
		|||
  state.mapProperties.onKeyNavigationEvent((event) => {
 | 
			
		||||
    lastAction.setData(event)
 | 
			
		||||
  })
 | 
			
		||||
  lastAction.stabilized(750).addCallbackAndRunD((_) => lastAction.setData(undefined))
 | 
			
		||||
  lastAction.stabilized(750).addCallbackAndRunD(() => lastAction.setData(undefined))
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div aria-live="assertive" class="m-1 rounded bg-white p-1">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@
 | 
			
		|||
  {#if $userdetails !== undefined}
 | 
			
		||||
    <div style="width: max-content" class="flex items-center">
 | 
			
		||||
      {#if $userdetails.img}
 | 
			
		||||
        <img src={$userdetails.img} alt="profile picture" class="mr-4 h-8 w-8 rounded-full" />
 | 
			
		||||
        <img src={$userdetails.img} alt="avatar" class="mr-4 h-8 w-8 rounded-full" />
 | 
			
		||||
      {/if}
 | 
			
		||||
      <div>
 | 
			
		||||
        <div>Welcome back</div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
import { OsmTags } from "../../Models/OsmFeature"
 | 
			
		||||
import { SpecialVisualizationState } from "../SpecialVisualization"
 | 
			
		||||
 | 
			
		||||
export class ComparisonState {
 | 
			
		||||
    public readonly hasDifferencesAtStart: boolean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,6 @@
 | 
			
		|||
  import ThemeViewState from "../../Models/ThemeViewState"
 | 
			
		||||
  import DownloadPdf from "./DownloadPdf.svelte"
 | 
			
		||||
  import { PngMapCreator } from "../../Utils/pngMapCreator"
 | 
			
		||||
  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
  import ValidatedInput from "../InputElement/ValidatedInput.svelte"
 | 
			
		||||
  import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,8 +19,6 @@
 | 
			
		|||
  import ThemeViewState from "../../Models/ThemeViewState"
 | 
			
		||||
  import { MenuState } from "../../Models/MenuState"
 | 
			
		||||
  import { LicenseInfo } from "../../Logic/ImageProviders/LicenseInfo"
 | 
			
		||||
  import Tr from "../Base/Tr.svelte"
 | 
			
		||||
  import { ExternalLinkIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
			
		||||
 | 
			
		||||
  export let tags: UIEventSource<OsmTags>
 | 
			
		||||
  export let state: ThemeViewState
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@
 | 
			
		|||
  import { UIEventSource } from "../../../Logic/UIEventSource"
 | 
			
		||||
  import BasicTagInput from "../../Studio/TagInput/BasicTagInput.svelte"
 | 
			
		||||
  import { TagUtils } from "../../../Logic/Tags/TagUtils"
 | 
			
		||||
  import FromHtml from "../../Base/FromHtml.svelte"
 | 
			
		||||
  import Markdown from "../../Base/Markdown.svelte"
 | 
			
		||||
  export let value: UIEventSource<undefined | string>
 | 
			
		||||
  export let args: string[] = []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@
 | 
			
		|||
  import LanguageUtils from "../../../Utils/LanguageUtils"
 | 
			
		||||
  import { createEventDispatcher, onDestroy } from "svelte"
 | 
			
		||||
  import ValidatedInput from "../ValidatedInput.svelte"
 | 
			
		||||
  import { del } from "idb-keyval"
 | 
			
		||||
 | 
			
		||||
  export let value: UIEventSource<Record<string, string>> = new UIEventSource<
 | 
			
		||||
    Record<string, string>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@
 | 
			
		|||
  import { twMerge } from "tailwind-merge"
 | 
			
		||||
  import type { ValueRange } from "../../Models/ThemeConfig/TagRenderingConfig"
 | 
			
		||||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import FloatValidator from "./Validators/FloatValidator"
 | 
			
		||||
  import BaseUIElement from "../BaseUIElement"
 | 
			
		||||
 | 
			
		||||
  export let type: ValidatorType
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ export class BingRasterLayerProperties implements Partial<RasterLayerProperties>
 | 
			
		|||
 | 
			
		||||
export class BingRasterLayer implements RasterLayerPolygon {
 | 
			
		||||
    private static singleton: RasterLayerPolygon | "error"
 | 
			
		||||
    readonly type: "Feature" = "Feature"
 | 
			
		||||
    readonly type: "Feature" = "Feature" as const
 | 
			
		||||
    readonly geometry: Polygon = BBox.global.asGeometry()
 | 
			
		||||
    readonly id = "bing"
 | 
			
		||||
    readonly properties: RasterLayerProperties
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,6 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
			
		||||
  import DynamicIcon from "./DynamicIcon.svelte"
 | 
			
		||||
  import DynamicMarker from "./DynamicMarker.svelte"
 | 
			
		||||
  import Marker from "./Marker.svelte"
 | 
			
		||||
  import { ImmutableStore } from "../../Logic/UIEventSource"
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,121 +61,109 @@
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
{#if icon}
 | 
			
		||||
  {#if icon === "pin"}
 | 
			
		||||
    <Pin {color} class={clss} />
 | 
			
		||||
  {:else if icon === "square"}
 | 
			
		||||
    <Square {color} class={clss} />
 | 
			
		||||
  {:else if icon === "square_rounded"}
 | 
			
		||||
    <Square_rounded {color} class={clss} />
 | 
			
		||||
  {#if icon === "addSmall"}
 | 
			
		||||
    <AddSmall {color} class={clss} />
 | 
			
		||||
  {:else if icon === "airport"}
 | 
			
		||||
    <Airport {color} class={clss} />
 | 
			
		||||
  {:else if icon === "brick_wall_round"}
 | 
			
		||||
    <Brick_wall_round {color} class={clss} />
 | 
			
		||||
  {:else if icon === "brick_wall_square"}
 | 
			
		||||
    <Brick_wall_square {color} class={clss} />
 | 
			
		||||
  {:else if icon === "bug"}
 | 
			
		||||
    <Bug {color} class={clss} />
 | 
			
		||||
  {:else if icon === "circle"}
 | 
			
		||||
    <Circle {color} class={clss} />
 | 
			
		||||
  {:else if icon === "building_office_2"}
 | 
			
		||||
    <BuildingOffice2 class={clss} {color} />
 | 
			
		||||
  {:else if icon === "building_storefront"}
 | 
			
		||||
    <BuildingStorefront {color} class={clss} />
 | 
			
		||||
  {:else if icon === "checkmark"}
 | 
			
		||||
    <Checkmark {color} class={clss} />
 | 
			
		||||
  {:else if icon === "circle"}
 | 
			
		||||
    <Circle {color} class={clss} />
 | 
			
		||||
  {:else if icon === "clock"}
 | 
			
		||||
    <Clock {color} class={clss} />
 | 
			
		||||
  {:else if icon === "close"}
 | 
			
		||||
    <Close {color} class={clss} />
 | 
			
		||||
  {:else if icon === "computer"}
 | 
			
		||||
    <DesktopComputerIcon class={"m-0 " + clss} {color} />
 | 
			
		||||
  {:else if icon === "confirm"}
 | 
			
		||||
    <Confirm class={clss} {color} />
 | 
			
		||||
  {:else if icon === "cross_bottom_right"}
 | 
			
		||||
    <Cross_bottom_right {color} class={"m-0 " + clss} />
 | 
			
		||||
  {:else if icon === "crosshair"}
 | 
			
		||||
    <Crosshair {color} class={clss} />
 | 
			
		||||
  {:else if icon === "direction" || icon === "direction_gradient"}
 | 
			
		||||
    <Direction_gradient class={clss} {color} />
 | 
			
		||||
  {:else if icon === "gear"}
 | 
			
		||||
    <Gear {color} class={clss} />
 | 
			
		||||
  {:else if icon === "globe_alt"}
 | 
			
		||||
    <GlobeAltIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "gps_arrow"}
 | 
			
		||||
    <Gps_arrow {color} class={clss} />
 | 
			
		||||
  {:else if icon === "heart"}
 | 
			
		||||
    <HeartIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "heart_outline"}
 | 
			
		||||
    <HeartOutlineIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "help"}
 | 
			
		||||
    <Help {color} class={clss} />
 | 
			
		||||
  {:else if icon === "home"}
 | 
			
		||||
    <Home {color} class={clss} />
 | 
			
		||||
  {:else if icon === "house"}
 | 
			
		||||
    <HomeIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "invalid"}
 | 
			
		||||
    <Invalid {color} class={clss} />
 | 
			
		||||
  {:else if icon === "location"}
 | 
			
		||||
    <Location {color} class={clss} />
 | 
			
		||||
  {:else if icon === "key"}
 | 
			
		||||
    <Key class={clss} {color} />
 | 
			
		||||
  {:else if icon === "link"}
 | 
			
		||||
    <LinkIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "location_empty"}
 | 
			
		||||
    <Location_empty {color} class={clss} />
 | 
			
		||||
  {:else if icon === "location"}
 | 
			
		||||
    <Location {color} class={clss} />
 | 
			
		||||
  {:else if icon === "location_locked"}
 | 
			
		||||
    <Location_locked {color} class={clss} />
 | 
			
		||||
  {:else if icon === "lock"}
 | 
			
		||||
    <LockClosed class={clss} {color} />
 | 
			
		||||
  {:else if icon === "mastodon"}
 | 
			
		||||
    <Mastodon {color} class={clss} />
 | 
			
		||||
  {:else if icon === "note"}
 | 
			
		||||
    <Note {color} class={clss} />
 | 
			
		||||
  {:else if icon === "not_found"}
 | 
			
		||||
    <Not_found class={twMerge(clss, "no-image-background")} {color} />
 | 
			
		||||
  {:else if icon === "party"}
 | 
			
		||||
    <Party {color} class={clss} />
 | 
			
		||||
  {:else if icon === "pencil"}
 | 
			
		||||
    <PencilIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "pin"}
 | 
			
		||||
    <Pin {color} class={clss} />
 | 
			
		||||
  {:else if icon === "popout"}
 | 
			
		||||
    <LinkIcon style="--svg-color: {color}" />
 | 
			
		||||
  {:else if icon === "relocation"}
 | 
			
		||||
    <Relocation class={clss} {color} />
 | 
			
		||||
  {:else if icon === "resolved"}
 | 
			
		||||
    <Resolved {color} class={clss} />
 | 
			
		||||
  {:else if icon === "ring"}
 | 
			
		||||
    <Ring {color} class={clss} />
 | 
			
		||||
  {:else if icon === "scissors"}
 | 
			
		||||
    <Scissors {color} class={clss} />
 | 
			
		||||
  {:else if icon === "snap"}
 | 
			
		||||
    <Snap class={clss} />
 | 
			
		||||
  {:else if icon === "square_rounded"}
 | 
			
		||||
    <Square_rounded {color} class={clss} />
 | 
			
		||||
  {:else if icon === "square"}
 | 
			
		||||
    <Square {color} class={clss} />
 | 
			
		||||
  {:else if icon === "teardrop"}
 | 
			
		||||
    <Teardrop {color} class={clss} />
 | 
			
		||||
  {:else if icon === "teardrop_with_hole_green"}
 | 
			
		||||
    <Teardrop_with_hole_green {color} class={clss} />
 | 
			
		||||
  {:else if icon === "triangle"}
 | 
			
		||||
    <Triangle {color} class={clss} />
 | 
			
		||||
  {:else if icon === "brick_wall_square"}
 | 
			
		||||
    <Brick_wall_square {color} class={clss} />
 | 
			
		||||
  {:else if icon === "brick_wall_round"}
 | 
			
		||||
    <Brick_wall_round {color} class={clss} />
 | 
			
		||||
  {:else if icon === "gps_arrow"}
 | 
			
		||||
    <Gps_arrow {color} class={clss} />
 | 
			
		||||
  {:else if icon === "checkmark"}
 | 
			
		||||
    <Checkmark {color} class={clss} />
 | 
			
		||||
  {:else if icon === "help"}
 | 
			
		||||
    <Help {color} class={clss} />
 | 
			
		||||
  {:else if icon === "close"}
 | 
			
		||||
    <Close {color} class={clss} />
 | 
			
		||||
  {:else if icon === "invalid"}
 | 
			
		||||
    <Invalid {color} class={clss} />
 | 
			
		||||
  {:else if icon === "heart"}
 | 
			
		||||
    <HeartIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "heart_outline"}
 | 
			
		||||
    <HeartOutlineIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "confirm"}
 | 
			
		||||
    <Confirm class={clss} {color} />
 | 
			
		||||
  {:else if icon === "direction" || icon === "direction_gradient"}
 | 
			
		||||
    <Direction_gradient class={clss} {color} />
 | 
			
		||||
  {:else if icon === "not_found"}
 | 
			
		||||
    <Not_found class={twMerge(clss, "no-image-background")} {color} />
 | 
			
		||||
  {:else if icon === "mastodon"}
 | 
			
		||||
    <Mastodon {color} class={clss} />
 | 
			
		||||
  {:else if icon === "party"}
 | 
			
		||||
    <Party {color} class={clss} />
 | 
			
		||||
  {:else if icon === "cross_bottom_right"}
 | 
			
		||||
    <Cross_bottom_right {color} class={"m-0 " + clss} />
 | 
			
		||||
  {:else if icon === "addSmall"}
 | 
			
		||||
    <AddSmall {color} class={clss} />
 | 
			
		||||
  {:else if icon === "gear"}
 | 
			
		||||
    <Gear {color} class={clss} />
 | 
			
		||||
  {:else if icon === "link"}
 | 
			
		||||
    <LinkIcon style="--svg-color: {color}" class={twMerge(clss, "apply-fill")} />
 | 
			
		||||
  {:else if icon === "popout"}
 | 
			
		||||
    <LinkIcon style="--svg-color: {color}" />
 | 
			
		||||
  {:else if icon === "wifi"}
 | 
			
		||||
    <WifiIcon class={"m-0 " + clss} {color} />
 | 
			
		||||
  {:else if icon === "computer"}
 | 
			
		||||
    <DesktopComputerIcon class={"m-0 " + clss} {color} />
 | 
			
		||||
  {:else if icon === "relocation"}
 | 
			
		||||
    <Relocation class={clss} {color} />
 | 
			
		||||
  {:else if icon === "pencil"}
 | 
			
		||||
    <PencilIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "user_circle"}
 | 
			
		||||
    <UserCircleIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "lock"}
 | 
			
		||||
    <LockClosed class={clss} {color} />
 | 
			
		||||
  {:else if icon === "key"}
 | 
			
		||||
    <Key class={clss} {color} />
 | 
			
		||||
  {:else if icon === "globe_alt"}
 | 
			
		||||
    <GlobeAltIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "building_office_2"}
 | 
			
		||||
    <BuildingOffice2 class={clss} {color} />
 | 
			
		||||
  {:else if icon === "house"}
 | 
			
		||||
    <HomeIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "train"}
 | 
			
		||||
    <Train {color} class={clss} />
 | 
			
		||||
  {:else if icon === "airport"}
 | 
			
		||||
    <Airport {color} class={clss} />
 | 
			
		||||
  {:else if icon === "building_storefront"}
 | 
			
		||||
    <BuildingStorefront {color} class={clss} />
 | 
			
		||||
  {:else if icon === "snap"}
 | 
			
		||||
    <Snap class={clss} />
 | 
			
		||||
  {:else if Utils.isEmoji(icon)}
 | 
			
		||||
    <span style={`font-size: ${emojiHeight}; line-height: ${emojiHeight}`}>
 | 
			
		||||
      {icon}
 | 
			
		||||
    </span>
 | 
			
		||||
  {:else}
 | 
			
		||||
    <img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" />
 | 
			
		||||
  {:else if icon === "triangle"}
 | 
			
		||||
    <Triangle {color} class={clss} />
 | 
			
		||||
  {:else if icon === "user_circle"}
 | 
			
		||||
    <UserCircleIcon class={clss} {color} />
 | 
			
		||||
  {:else if icon === "wifi"}
 | 
			
		||||
    <WifiIcon class={"m-0 " + clss} {color} />
 | 
			
		||||
  {:else if Utils.isEmoji(icon)}<span style={`font-size: ${emojiHeight}; line-height: ${emojiHeight}`}>  {icon}</span>
 | 
			
		||||
  {:else}<img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" />
 | 
			
		||||
  {/if}
 | 
			
		||||
{/if}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,7 +65,7 @@
 | 
			
		|||
    _map.on("load", function () {
 | 
			
		||||
      _map.resize()
 | 
			
		||||
      const canvas = _map.getCanvas()
 | 
			
		||||
      canvas.addEventListener("webglcontextlost", (e) => {
 | 
			
		||||
      canvas.addEventListener("webglcontextlost", () => {
 | 
			
		||||
        try {
 | 
			
		||||
          _map?.remove()
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,6 @@
 | 
			
		|||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
  import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
			
		||||
  import { GeoOperations } from "../../Logic/GeoOperations"
 | 
			
		||||
  import type { Feature, LineString } from "geojson"
 | 
			
		||||
  import { Utils } from "../../Utils"
 | 
			
		||||
  import { Translation } from "../i18n/Translation"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,7 @@
 | 
			
		|||
    <button
 | 
			
		||||
      class="primary"
 | 
			
		||||
      class:disabled={$selectedLanguages.length === 0}
 | 
			
		||||
      on:click={(_) => applySelectedLanguages()}
 | 
			
		||||
      on:click={() => applySelectedLanguages()}
 | 
			
		||||
    >
 | 
			
		||||
      <Tr t={Translations.t.general.save} />
 | 
			
		||||
    </button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,14 +35,13 @@ class MultiApplyExecutor {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        if (p.autoapply) {
 | 
			
		||||
            const self = this
 | 
			
		||||
            const relevantValues = p.tagsSource.map((tags) => {
 | 
			
		||||
                const currentValues = p.keysToApply.map((key) => tags[key])
 | 
			
		||||
                // By stringifying, we have a very clear ping when they changec
 | 
			
		||||
                return JSON.stringify(currentValues)
 | 
			
		||||
            })
 | 
			
		||||
            relevantValues.addCallbackD((_) => {
 | 
			
		||||
                self.applyTaggingOnOtherFeatures()
 | 
			
		||||
            relevantValues.addCallbackD(() => {
 | 
			
		||||
                this.applyTaggingOnOtherFeatures()
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,12 +12,7 @@
 | 
			
		|||
  import type { SpecialVisualizationState } from "../../SpecialVisualization"
 | 
			
		||||
  import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
 | 
			
		||||
  import TagRenderingQuestion from "./TagRenderingQuestion.svelte"
 | 
			
		||||
  import type { UploadableTag } from "../../../Logic/Tags/TagUtils"
 | 
			
		||||
  import { writable } from "svelte/store"
 | 
			
		||||
  import Translations from "../../i18n/Translations"
 | 
			
		||||
  import { twJoin } from "tailwind-merge"
 | 
			
		||||
  import Tr from "../../Base/Tr.svelte"
 | 
			
		||||
  import { TrashIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
			
		||||
  import type { UploadableTag } from "../../../Logic/Tags/TagTypes"
 | 
			
		||||
  import Loading from "../../Base/Loading.svelte"
 | 
			
		||||
 | 
			
		||||
  export let config: TagRenderingConfig
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,18 +3,16 @@
 | 
			
		|||
  import Tr from "./Base/Tr.svelte"
 | 
			
		||||
  import { EyeIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
			
		||||
  import Translations from "./i18n/Translations"
 | 
			
		||||
  import { Utils } from "../Utils"
 | 
			
		||||
  import Add from "../assets/svg/Add.svelte"
 | 
			
		||||
  import LanguagePicker from "./InputElement/LanguagePicker.svelte"
 | 
			
		||||
  import type { SpecialVisualizationState } from "./SpecialVisualization"
 | 
			
		||||
  import { OsmConnection } from "../Logic/Osm/OsmConnection"
 | 
			
		||||
  import UserRelatedState from "../Logic/State/UserRelatedState"
 | 
			
		||||
  import Title from "./Popup/Title.svelte"
 | 
			
		||||
  import TitledPanel from "./Base/TitledPanel.svelte"
 | 
			
		||||
  import Back from "../assets/svg/Back.svelte"
 | 
			
		||||
 | 
			
		||||
  const osmConnection = new OsmConnection()
 | 
			
		||||
  let state: SpecialVisualizationState = {
 | 
			
		||||
  let state: Partial<SpecialVisualizationState> = {
 | 
			
		||||
    osmConnection,
 | 
			
		||||
    userRelatedState: new UserRelatedState(osmConnection),
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@
 | 
			
		|||
      reader.readAsText(files[0], "UTF-8")
 | 
			
		||||
 | 
			
		||||
      // here we tell the reader what to do when it's done reading...
 | 
			
		||||
      const content = await new Promise<string>((resolve, reject) => {
 | 
			
		||||
      const content = await new Promise<string>(resolve => {
 | 
			
		||||
        reader.onload = (readerEvent) => {
 | 
			
		||||
          resolve(<string>readerEvent.target.result)
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
{#if score !== undefined}
 | 
			
		||||
  <div class="flex" on:mouseout>
 | 
			
		||||
  <div class="flex" on:mouseout on:blur>
 | 
			
		||||
    {#each cutoffs as cutoff, i}
 | 
			
		||||
      <StarElement {readonly} {score} {i} {cutoff} {starSize} on:hover on:click />
 | 
			
		||||
    {/each}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,8 +26,8 @@
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    check()
 | 
			
		||||
    recheckSignal.addCallback((_) => check())
 | 
			
		||||
    checkSignal.addCallback((_) => {
 | 
			
		||||
    recheckSignal.addCallback(() => check())
 | 
			
		||||
    checkSignal.addCallback(() => {
 | 
			
		||||
      if (autoCheckAgain.data) {
 | 
			
		||||
        check()
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import EditLayerState from "./EditLayerState"
 | 
			
		||||
  import type { ConfigMeta } from "./configMeta"
 | 
			
		||||
  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
  import TranslationInput from "../InputElement/Helpers/TranslationInput.svelte"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
import Hash from "../../Logic/Web/Hash"
 | 
			
		||||
 | 
			
		||||
export default class StudioHashSetter {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@
 | 
			
		|||
  import { TagUtils } from "../../../Logic/Tags/TagUtils"
 | 
			
		||||
  import TagInfoStats from "../TagInfoStats.svelte"
 | 
			
		||||
  import { Translation } from "../../i18n/Translation"
 | 
			
		||||
  import InformationCircle from "@babeard/svelte-heroicons/outline/InformationCircle"
 | 
			
		||||
  import QuestionMarkCircle from "@babeard/svelte-heroicons/outline/QuestionMarkCircle"
 | 
			
		||||
 | 
			
		||||
  export let tag: UIEventSource<string> = new UIEventSource<string>(undefined)
 | 
			
		||||
| 
						 | 
				
			
			@ -20,8 +19,6 @@
 | 
			
		|||
   */
 | 
			
		||||
  export let silent: boolean = false
 | 
			
		||||
 | 
			
		||||
  export let selected: UIEventSource<boolean> = new UIEventSource<boolean>(false)
 | 
			
		||||
 | 
			
		||||
  let feedbackGlobal = tag.map((tag) => {
 | 
			
		||||
    if (!tag) {
 | 
			
		||||
      return undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -76,14 +73,14 @@
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onDestroy(valueValue.addCallbackAndRun(setTag))
 | 
			
		||||
  onDestroy(keyValue.addCallbackAndRun(setTag))
 | 
			
		||||
  onDestroy(valueValue.addCallbackAndRun(() => setTag()))
 | 
			
		||||
  onDestroy(keyValue.addCallbackAndRun(() => setTag()))
 | 
			
		||||
 | 
			
		||||
  $: {
 | 
			
		||||
    setTag(mode)
 | 
			
		||||
    setTag()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function setTag(_) {
 | 
			
		||||
  function setTag() {
 | 
			
		||||
    const k = keyValue.data
 | 
			
		||||
    const v = valueValue.data ?? ""
 | 
			
		||||
    if (k === undefined || k === "") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import EditLayerState from "./EditLayerState"
 | 
			
		||||
  import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
 | 
			
		||||
 | 
			
		||||
  export let state: EditLayerState
 | 
			
		||||
  export let path: (number | string)[]
 | 
			
		||||
 | 
			
		||||
  let schema: TagRenderingConfig
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
XYZ
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@
 | 
			
		|||
  import Hash from "../Logic/Web/Hash"
 | 
			
		||||
  import Searchbar from "./Base/Searchbar.svelte"
 | 
			
		||||
  import ChevronRight from "@babeard/svelte-heroicons/mini/ChevronRight"
 | 
			
		||||
  import { Drawer, Popover } from "flowbite-svelte"
 | 
			
		||||
  import { Drawer } from "flowbite-svelte"
 | 
			
		||||
  import { linear } from "svelte/easing"
 | 
			
		||||
  import DefaultIcon from "./Map/DefaultIcon.svelte"
 | 
			
		||||
  import Loading from "./Base/Loading.svelte"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import { createEventDispatcher } from "svelte"
 | 
			
		||||
  import WalkthroughStep from "./WalkthroughStep.svelte"
 | 
			
		||||
  import FromHtml from "../Base/FromHtml.svelte"
 | 
			
		||||
  import Markdown from "../Base/Markdown.svelte"
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata"
 | 
			
		||||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import { FixedUiElement } from "../Base/FixedUiElement"
 | 
			
		||||
  import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
  import Wikidatapreview from "./Wikidatapreview.svelte"
 | 
			
		||||
  import Tr from "../Base/Tr.svelte"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,4 +33,4 @@ async function main() {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main().then((_) => {})
 | 
			
		||||
main().then(() => {})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
            "variables-before-functions"
 | 
			
		||||
        ],
 | 
			
		||||
        "no-arg": true,
 | 
			
		||||
        "no-any": false,
 | 
			
		||||
        "no-bitwise": true,
 | 
			
		||||
        "no-console": false,
 | 
			
		||||
        "no-construct": true,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue