forked from MapComplete/MapComplete
		
	Merge branch 'develop' into Robin-patch-1
This commit is contained in:
		
						commit
						904b628a81
					
				
					 22 changed files with 660 additions and 385 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -9,6 +9,15 @@
 | 
			
		|||
    "nl": "Wijzigingen gemaakt met MapComplete",
 | 
			
		||||
    "ko": "MapComplete로 이루어진 변경 사항"
 | 
			
		||||
  },
 | 
			
		||||
  "shortDescription": {
 | 
			
		||||
    "en": "Shows changes made by MapComplete",
 | 
			
		||||
    "de": "Zeigt die von MapComplete vorgenommenen Änderungen an",
 | 
			
		||||
    "cs": "Zobrazuje změny provedené nástrojem MapComplete",
 | 
			
		||||
    "es": "Muestra los cambios realizados por MapComplete",
 | 
			
		||||
    "fr": "Afficher les modifications faites avec MapComplete",
 | 
			
		||||
    "nl": "Toont wijzigingen gemaakt met MapComplete",
 | 
			
		||||
    "ko": "MapComplete를 통해 이루어진 변경 사항을 표시합니다"
 | 
			
		||||
  },
 | 
			
		||||
  "description": {
 | 
			
		||||
    "en": "This maps shows all the changes made with MapComplete",
 | 
			
		||||
    "de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen",
 | 
			
		||||
| 
						 | 
				
			
			@ -19,17 +28,11 @@
 | 
			
		|||
    "nl": "Deze kaarten tonen alle wijzigingen die zijn gemaakt met MapComplete",
 | 
			
		||||
    "ko": "이 지도는 MapComplete를 사용하여 이루어진 모든 변경 사항을 표시합니다"
 | 
			
		||||
  },
 | 
			
		||||
  "shortDescription": {
 | 
			
		||||
    "en": "Shows changes made by MapComplete",
 | 
			
		||||
    "de": "Zeigt die von MapComplete vorgenommenen Änderungen an",
 | 
			
		||||
    "cs": "Zobrazuje změny provedené nástrojem MapComplete",
 | 
			
		||||
    "es": "Muestra los cambios realizados por MapComplete",
 | 
			
		||||
    "fr": "Afficher les modifications faites avec MapComplete",
 | 
			
		||||
    "nl": "Toont wijzigingen gemaakt met MapComplete",
 | 
			
		||||
    "ko": "MapComplete를 통해 이루어진 변경 사항을 표시합니다"
 | 
			
		||||
  },
 | 
			
		||||
  "icon": "./assets/svg/logo.svg",
 | 
			
		||||
  "hideFromOverview": true,
 | 
			
		||||
  "startLat": 0,
 | 
			
		||||
  "startLon": 0,
 | 
			
		||||
  "startZoom": 1,
 | 
			
		||||
  "layers": [
 | 
			
		||||
    {
 | 
			
		||||
      "id": "mapcomplete-changes",
 | 
			
		||||
| 
						 | 
				
			
			@ -182,19 +185,22 @@
 | 
			
		|||
        {
 | 
			
		||||
          "id": "platform",
 | 
			
		||||
          "question": {
 | 
			
		||||
            "en": "With what platform was the change made?"
 | 
			
		||||
            "en": "With what platform was the change made?",
 | 
			
		||||
            "cs": "S jakou platformou byly změny provedeny?"
 | 
			
		||||
          },
 | 
			
		||||
          "mappings": [
 | 
			
		||||
            {
 | 
			
		||||
              "if": "android=",
 | 
			
		||||
              "then": {
 | 
			
		||||
                "en": "Made on the web"
 | 
			
		||||
                "en": "Made on the web",
 | 
			
		||||
                "cs": "Vytvořeno na webu"
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              "if": "android=yes",
 | 
			
		||||
              "then": {
 | 
			
		||||
                "en": "Made with the android app"
 | 
			
		||||
                "en": "Made with the android app",
 | 
			
		||||
                "cs": "Vytvořeno s aplikací pro Android"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
| 
						 | 
				
			
			@ -851,19 +857,22 @@
 | 
			
		|||
          "options": [
 | 
			
		||||
            {
 | 
			
		||||
              "question": {
 | 
			
		||||
                "en": "All platforms"
 | 
			
		||||
                "en": "All platforms",
 | 
			
		||||
                "cs": "Všechny platformy"
 | 
			
		||||
              },
 | 
			
		||||
              "quesiton": "All platforms"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              "question": {
 | 
			
		||||
                "en": "Made with Android"
 | 
			
		||||
                "en": "Made with Android",
 | 
			
		||||
                "cs": "Vytvořeno s Androidem"
 | 
			
		||||
              },
 | 
			
		||||
              "osmTags": "android=yes"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              "question": {
 | 
			
		||||
                "en": "Made on the web"
 | 
			
		||||
                "en": "Made on the web",
 | 
			
		||||
                "cs": "Vytvořeno na webu"
 | 
			
		||||
              },
 | 
			
		||||
              "osmTags": "android="
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,9 @@
 | 
			
		|||
        "=presets": [],
 | 
			
		||||
        "source": {
 | 
			
		||||
          "=osmTags": {
 | 
			
		||||
            "or":[
 | 
			
		||||
              "leisure=summer_camp",
 | 
			
		||||
              {
 | 
			
		||||
                "and": [
 | 
			
		||||
                  "tourism=camp_site",
 | 
			
		||||
                  "scout!=no",
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +44,8 @@
 | 
			
		|||
                  }
 | 
			
		||||
                ]
 | 
			
		||||
              }
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -669,6 +669,29 @@
 | 
			
		|||
    "onwheels": {
 | 
			
		||||
        "description": "En aquest mapa, es mostren llocs públics accessibles per a cadira de rodes i es poden afegir fàcilment",
 | 
			
		||||
        "layers": {
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "No s'ha senyalitzat cap entrada"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Cap de les {_entrance_count} entrades té informació d'amplada encara"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} entrades encara no tenen informació d'amplada",
 | 
			
		||||
                                "before": "<h3>Entrades</h3>Aquest edifici té {_entrances_count} entrades:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "Una <a href='#{id}'>entrada </a> de {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -889,6 +889,29 @@
 | 
			
		|||
            "0": {
 | 
			
		||||
                "description": "Všechny objekty, které mají data vstupu mapována na vybavení namísto objektu vstupu"
 | 
			
		||||
            },
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "Nebyl označen žádný vchod"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Žádný z {_entrance_count} vchodů zatím nemá informace o šířce"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} vchody zatím nemají informace o šířce",
 | 
			
		||||
                                "before": "<h3>Vchody</h3>Tato budova má {_entrances_count} vchodů:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "<a href='#{id}'>vchod</a> {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -505,6 +505,29 @@
 | 
			
		|||
    "onwheels": {
 | 
			
		||||
        "description": "På dette kort vises steder, der er offentligt tilgængelige for kørestolsbrugere, og de kan nemt tilføjes",
 | 
			
		||||
        "layers": {
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "Der er ikke markeret nogen indgang"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Ingen af {_entrance_count}-indgangene har oplysninger om bredde endnu"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} indgange har endnu ikke oplysninger om bredde",
 | 
			
		||||
                                "before": "<h3>Indgange</h3>Denne bygning har {_entrances_count} indgange:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "En <a href='#{id}'>indgang</a> på {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -862,6 +862,29 @@
 | 
			
		|||
    "onwheels": {
 | 
			
		||||
        "description": "Auf dieser Karte können Sie öffentlich zugängliche Orte für Rollstuhlfahrer ansehen, bearbeiten oder hinzufügen",
 | 
			
		||||
        "layers": {
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "Es wurde kein Eingang markiert"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Keiner der {_entrance_count} Eingänge hat bisher Angaben zur Breite"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} Eingänge haben keine Angaben zur Breite",
 | 
			
		||||
                                "before": "<h3>Eingänge</h3>Das Gebäude hat {_entrances_count} Eingänge:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "Ein <a href='#{id}'>Eingang</a> von {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -889,6 +889,29 @@
 | 
			
		|||
            "0": {
 | 
			
		||||
                "description": "All objects which have entrance data mapped on the amenity instead of the entrance object"
 | 
			
		||||
            },
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "No entrance has been marked"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "None of the {_entrance_count} entrances have width information yet"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} entrances don't have width information yet",
 | 
			
		||||
                                "before": "<h3>Entrances</h3>This building has {_entrances_count} entrances:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "An <a href='#{id}'>entrance</a> of {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			@ -1377,6 +1400,10 @@
 | 
			
		|||
        "shortDescription": "A map with waste baskets",
 | 
			
		||||
        "title": "Waste Baskets"
 | 
			
		||||
    },
 | 
			
		||||
    "wayside_shrines": {
 | 
			
		||||
        "description": "This map shows shrines found on the side of roads and paths, and allows adding new ones",
 | 
			
		||||
        "title": "Wayside shrines"
 | 
			
		||||
    },
 | 
			
		||||
    "winter_service": {
 | 
			
		||||
        "description": "A map showing roads and whether they're cleared in winter",
 | 
			
		||||
        "layers": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -849,6 +849,29 @@
 | 
			
		|||
    "onwheels": {
 | 
			
		||||
        "description": "En este mapa, se muestran y se pueden agregar fácilmente lugares accesibles para sillas de ruedas",
 | 
			
		||||
        "layers": {
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "No se ha marcado ninguna entrada"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Ninguna de las {_entrance_count} entradas tiene información de ancho todavía"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} entradas aún no tienen información de ancho",
 | 
			
		||||
                                "before": "<h3>Entradas</h3>Este edificio tiene {_entrances_count} entradas:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "Una <a href='#{id}'>entrada</a> de {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -909,6 +909,29 @@
 | 
			
		|||
    "onwheels": {
 | 
			
		||||
        "description": "Op deze kaart kan je rolstoeltoegankelijke plaatsen vinden en toevoegen",
 | 
			
		||||
        "layers": {
 | 
			
		||||
            "16": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "tagRenderings+": {
 | 
			
		||||
                        "0": {
 | 
			
		||||
                            "mappings": {
 | 
			
		||||
                                "0": {
 | 
			
		||||
                                    "then": "Geen ingang is gemarkeerd"
 | 
			
		||||
                                },
 | 
			
		||||
                                "1": {
 | 
			
		||||
                                    "then": "Geen van de {_entrance_count} ingangen hebben al informatie over de breedte"
 | 
			
		||||
                                }
 | 
			
		||||
                            },
 | 
			
		||||
                            "render": {
 | 
			
		||||
                                "after": "{_entrances_count_without_width_count} ingangen hebben nog geen informatie over de breedte",
 | 
			
		||||
                                "before": "<h3>Ingangen</h3>Dit gebouw heeft {_entrances_count} ingangen:",
 | 
			
		||||
                                "special": {
 | 
			
		||||
                                    "tagrendering": "Een <a href='#{id}'>ingang</a> van {canonical(width)}"
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "20": {
 | 
			
		||||
                "override": {
 | 
			
		||||
                    "=title": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2006,6 +2006,10 @@ input[type="range"].range-lg::-moz-range-thumb {
 | 
			
		|||
  width: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-1\/4 {
 | 
			
		||||
  width: 25%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-10 {
 | 
			
		||||
  width: 2.5rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5565,6 +5569,12 @@ code {
 | 
			
		|||
  background-color: #b3b3b3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.frozen-glass {
 | 
			
		||||
  -webkit-backdrop-filter: blur(1px);
 | 
			
		||||
          backdrop-filter: blur(1px);
 | 
			
		||||
  background: rgba(100, 100, 100, 0.50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************** UTILITY ************************/
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -746,12 +746,14 @@ export default class TagRenderingConfig {
 | 
			
		|||
        if (freeformValue === "") {
 | 
			
		||||
            freeformValue = undefined
 | 
			
		||||
        }
 | 
			
		||||
        if (this.freeform?.postfixDistinguished) {
 | 
			
		||||
            const allValues = currentProperties[this.freeform.key].split(";").map((s) => s.trim())
 | 
			
		||||
        const pf = this.freeform?.postfixDistinguished
 | 
			
		||||
        if (pf) {
 | 
			
		||||
            const v = currentProperties[this.freeform.key] ?? ""
 | 
			
		||||
            const allValues = v.split(";").map((s) => s.trim())
 | 
			
		||||
            const perPostfix: Record<string, string> = {}
 | 
			
		||||
            for (const value of allValues) {
 | 
			
		||||
                const [v, postfix] = value.split("/")
 | 
			
		||||
                perPostfix[postfix.trim()] = v.trim()
 | 
			
		||||
                const [v, postfix] = value.split("/").map(s => s.trim())
 | 
			
		||||
                perPostfix[postfix ?? pf] = v.trim()
 | 
			
		||||
            }
 | 
			
		||||
            if (freeformValue === "" || freeformValue === undefined) {
 | 
			
		||||
                delete perPostfix[this.freeform.postfixDistinguished]
 | 
			
		||||
| 
						 | 
				
			
			@ -1042,7 +1044,8 @@ export default class TagRenderingConfig {
 | 
			
		|||
     */
 | 
			
		||||
    public markUnknown(layer: LayerConfig, currentProperties: Record<string, string>): UploadableTag[] {
 | 
			
		||||
        if (this.freeform?.postfixDistinguished) {
 | 
			
		||||
            const allValues = currentProperties[this.freeform.key].split(";").filter(
 | 
			
		||||
            const v = currentProperties[this.freeform.key] ?? ""
 | 
			
		||||
            const allValues = v.split(";").filter(
 | 
			
		||||
                part => part.split("/")[1]?.trim() !== this.freeform.postfixDistinguished
 | 
			
		||||
            )
 | 
			
		||||
            return [new Tag(this.freeform.key, allValues.join(";"))]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@
 | 
			
		|||
  placement="left"
 | 
			
		||||
  transitionType="fly"
 | 
			
		||||
  {transitionParams}
 | 
			
		||||
  bgColor="frozen-glass"
 | 
			
		||||
  divClass="overflow-y-auto z-50 "
 | 
			
		||||
  bind:hidden
 | 
			
		||||
>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
  let height = 0
 | 
			
		||||
  onMount(() => {
 | 
			
		||||
    let topbar = document.getElementById("top-bar")
 | 
			
		||||
    height = topbar.clientHeight
 | 
			
		||||
    height = topbar?.clientHeight ?? 0
 | 
			
		||||
  })
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,11 +22,13 @@
 | 
			
		|||
    defaultClass = shared
 | 
			
		||||
  }
 | 
			
		||||
  let dialogClass =
 | 
			
		||||
    "fixed top-0 start-0 end-0 h-modal inset-0 w-full p-4 flex class-marker-dialog " + zIndex
 | 
			
		||||
    "fixed top-0 start-0 end-0 h-modal inset-0 w-full p-4 flex border-none  " + zIndex
 | 
			
		||||
 | 
			
		||||
  export let backdropClass = "fixed inset-0 z-40 bg-gray-900 bg-opacity-50 dark:bg-opacity-80 frozen-glass"
 | 
			
		||||
  if (fullscreen) {
 | 
			
		||||
    dialogClass += " h-full-child"
 | 
			
		||||
  }
 | 
			
		||||
  let bodyClass = bodyPadding + " h-full space-y-4 flex-1 overflow-y-auto overscroll-contain"
 | 
			
		||||
  let bodyClass = bodyPadding + " h-full space-y-4 flex-1 overflow-y-auto overscroll-contain background-normal"
 | 
			
		||||
 | 
			
		||||
  let headerClass = "flex justify-between items-center p-2 px-4 md:px-5 rounded-t-lg"
 | 
			
		||||
  if (!$$slots.header) {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +50,7 @@
 | 
			
		|||
  {bodyClass}
 | 
			
		||||
  {dialogClass}
 | 
			
		||||
  {headerClass}
 | 
			
		||||
  {backdropClass}
 | 
			
		||||
  color="none"
 | 
			
		||||
>
 | 
			
		||||
  <svelte:fragment slot="header">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@
 | 
			
		|||
  import { MapLibreAdaptor } from "./Map/MapLibreAdaptor"
 | 
			
		||||
  import { Map as MlMap } from "maplibre-gl"
 | 
			
		||||
  import ShowDataLayer from "./Map/ShowDataLayer"
 | 
			
		||||
 | 
			
		||||
  import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource"
 | 
			
		||||
  import type { Feature } from "geojson"
 | 
			
		||||
  import Loading from "./Base/Loading.svelte"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,9 +23,16 @@
 | 
			
		|||
  import Page from "./Base/Page.svelte"
 | 
			
		||||
  import PreviouslySpiedUsers from "./History/PreviouslySpiedUsers.svelte"
 | 
			
		||||
  import { OsmConnection } from "../Logic/Osm/OsmConnection"
 | 
			
		||||
  import MagnifyingGlassCircle from "@babeard/svelte-heroicons/outline/MagnifyingGlassCircle"
 | 
			
		||||
  import Translations from "./i18n/Translations"
 | 
			
		||||
  import Tr from "./Base/Tr.svelte"
 | 
			
		||||
  import Searchbar from "../UI/Base/Searchbar.svelte"
 | 
			
		||||
  import CombinedSearcher from "../Logic/Search/CombinedSearcher"
 | 
			
		||||
  import CoordinateSearch from "../Logic/Search/CoordinateSearch"
 | 
			
		||||
  import OpenLocationCodeSearch from "../Logic/Search/OpenLocationCodeSearch"
 | 
			
		||||
  import PhotonSearch from "../Logic/Search/PhotonSearch"
 | 
			
		||||
  import GeocodeResults from "./Search/GeocodeResults.svelte"
 | 
			
		||||
  import MagnifyingGlassCircle from "@babeard/svelte-heroicons/mini/MagnifyingGlassCircle"
 | 
			
		||||
  import type { GeocodeResult } from "../Logic/Search/GeocodingProvider"
 | 
			
		||||
 | 
			
		||||
  console.log("Loading inspector GUI")
 | 
			
		||||
  let username = QueryParameters.GetQueryParameter("user", undefined, "Inspect this user")
 | 
			
		||||
| 
						 | 
				
			
			@ -37,16 +43,45 @@
 | 
			
		|||
  let lon = UIEventSource.asFloat(QueryParameters.GetQueryParameter("lon", "0"))
 | 
			
		||||
  let loadingData = false
 | 
			
		||||
  let selectedElement = new UIEventSource<Feature>(undefined)
 | 
			
		||||
  let searchvalue = new UIEventSource<string>("")
 | 
			
		||||
 | 
			
		||||
  let geocoder = new CombinedSearcher(
 | 
			
		||||
    new CoordinateSearch(),
 | 
			
		||||
    new OpenLocationCodeSearch(),
 | 
			
		||||
    new PhotonSearch(true, 2),
 | 
			
		||||
    new PhotonSearch()
 | 
			
		||||
  )
 | 
			
		||||
  let showSearchDrawer = new UIEventSource(true)
 | 
			
		||||
  let searchIsFocussed = new UIEventSource(false)
 | 
			
		||||
  let searchIsRunning = new UIEventSource(false)
 | 
			
		||||
  let maplibremap: MapLibreAdaptor = new MapLibreAdaptor(map, {
 | 
			
		||||
    zoom,
 | 
			
		||||
    location: new UIEventSource<{ lon: number; lat: number }>({ lat: lat.data, lon: lon.data }),
 | 
			
		||||
    location: new UIEventSource<{ lon: number; lat: number }>({ lat: lat.data, lon: lon.data })
 | 
			
		||||
  })
 | 
			
		||||
  maplibremap.location.stabilized(500).addCallbackAndRunD((l) => {
 | 
			
		||||
    lat.set(l.lat)
 | 
			
		||||
    lon.set(l.lon)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  let searchSuggestions = searchvalue.bindD(search => {
 | 
			
		||||
    searchIsRunning.set(true)
 | 
			
		||||
    try {
 | 
			
		||||
      return UIEventSource.FromPromise(geocoder.search(search))
 | 
			
		||||
    } finally {
 | 
			
		||||
      searchIsRunning.set(false)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  let state = {
 | 
			
		||||
    mapProperties: maplibremap,
 | 
			
		||||
    searchState: {
 | 
			
		||||
      searchTerm: searchvalue,
 | 
			
		||||
      suggestions: searchSuggestions,
 | 
			
		||||
      suggestionsSearchRunning: searchIsRunning,
 | 
			
		||||
      showSearchDrawer,
 | 
			
		||||
      applyGeocodeResult(geocodeResult: GeocodeResult) {
 | 
			
		||||
        maplibremap.location.set({ lon: geocodeResult.lon, lat: geocodeResult.lat })
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  let allLayers = HistoryUtils.personalTheme.layers
 | 
			
		||||
  let layersNoFixme = allLayers.filter((l) => l.id !== "fixme")
 | 
			
		||||
  let fixme = allLayers.find((l) => l.id === "fixme")
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +94,7 @@
 | 
			
		|||
      Utils.waitFor(200).then(() => {
 | 
			
		||||
        selectedElement.set(f)
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  let osmConnection = new OsmConnection()
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +126,7 @@
 | 
			
		|||
        inspectedData.push({
 | 
			
		||||
          label: undefined,
 | 
			
		||||
          visitedTime: new Date().toISOString(),
 | 
			
		||||
          name: user,
 | 
			
		||||
          name: user
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
      inspectedContributors.ping()
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +136,7 @@
 | 
			
		|||
    featuresStore.set([])
 | 
			
		||||
    const overpass = new Overpass(
 | 
			
		||||
      undefined,
 | 
			
		||||
      user.split(";").map((user) => 'nw(user_touched:"' + user + '");'),
 | 
			
		||||
      user.split(";").map((user) => "nw(user_touched:\"" + user + "\");"),
 | 
			
		||||
      Constants.defaultOverpassUrls[0]
 | 
			
		||||
    )
 | 
			
		||||
    if (!maplibremap.bounds.data) {
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +172,7 @@
 | 
			
		|||
    <h1 class="m-0 mx-2 flex-shrink-0">
 | 
			
		||||
      <Tr t={t.title} />
 | 
			
		||||
    </h1>
 | 
			
		||||
    <ValidatedInput type="string" value={username} on:submit={() => load()} />
 | 
			
		||||
    <ValidatedInput placeholder={t.previouslySpied.username} type="string" value={username} on:submit={() => load()} />
 | 
			
		||||
    {#if loadingData}
 | 
			
		||||
      <Loading />
 | 
			
		||||
    {:else}
 | 
			
		||||
| 
						 | 
				
			
			@ -207,8 +242,16 @@
 | 
			
		|||
      </Drawer>
 | 
			
		||||
    {/if}
 | 
			
		||||
 | 
			
		||||
    <div class="m-1 flex-grow overflow-hidden rounded-xl">
 | 
			
		||||
 | 
			
		||||
    <div class="relative m-1 flex-grow overflow-hidden rounded-xl">
 | 
			
		||||
      <MaplibreMap {map} mapProperties={maplibremap} autorecovery={true} />
 | 
			
		||||
      <div class="absolute right-0 top-0 w-1/4 p-4">
 | 
			
		||||
        <Searchbar isFocused={searchIsFocussed} value={searchvalue}
 | 
			
		||||
                   on:focus={() => state.searchState.showSearchDrawer.set(true)} />
 | 
			
		||||
        {#if $searchSuggestions?.length > 0 || $searchIsFocussed}
 | 
			
		||||
          <GeocodeResults {state} />
 | 
			
		||||
        {/if}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  {:else if mode === "table"}
 | 
			
		||||
    <div class="m-2 h-full overflow-y-auto">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -252,6 +252,8 @@
 | 
			
		|||
      } else if (selectedTags instanceof And) {
 | 
			
		||||
        // Add the extraTags to the existing And
 | 
			
		||||
        selectedTags = [...TagTypes.uploadableAnd(selectedTags), ...extraTagsArray]
 | 
			
		||||
      } else if (Array.isArray(selectedTags)) {
 | 
			
		||||
        // pass
 | 
			
		||||
      } else {
 | 
			
		||||
        console.error(
 | 
			
		||||
          "selectedTags is not of type Tag or And, it is a " + JSON.stringify(selectedTags)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,25 +1,33 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
  import { GeocodingUtils } from "../../Logic/Search/GeocodingProvider"
 | 
			
		||||
  import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
 | 
			
		||||
  import { GeocodingUtils } from "../../Logic/Search/GeocodingProvider"
 | 
			
		||||
  import { GeoOperations } from "../../Logic/GeoOperations"
 | 
			
		||||
  import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
			
		||||
  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
  import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
 | 
			
		||||
  import Icon from "../Map/Icon.svelte"
 | 
			
		||||
  import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
 | 
			
		||||
  import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
 | 
			
		||||
  import DefaultIcon from "../Map/DefaultIcon.svelte"
 | 
			
		||||
  import { WithSearchState } from "../../Models/ThemeViewState/WithSearchState"
 | 
			
		||||
  import type { MapProperties } from "../../Models/MapProperties"
 | 
			
		||||
  import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
 | 
			
		||||
  import FeaturePropertiesStore from "../../Logic/FeatureSource/Actors/FeaturePropertiesStore"
 | 
			
		||||
  import SearchState from "../../Logic/State/SearchState"
 | 
			
		||||
  import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
 | 
			
		||||
 | 
			
		||||
  export let entry: GeocodeResult
 | 
			
		||||
  export let state: WithSearchState
 | 
			
		||||
  export let state: {
 | 
			
		||||
    mapProperties: MapProperties,
 | 
			
		||||
    theme?: ThemeConfig,
 | 
			
		||||
    featureProperties?: FeaturePropertiesStore,
 | 
			
		||||
    searchState: Partial<SearchState>
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let layer: LayerConfig
 | 
			
		||||
  let tags: UIEventSource<Record<string, string>>
 | 
			
		||||
  let descriptionTr: TagRenderingConfig = undefined
 | 
			
		||||
  if (entry.feature?.properties?.id) {
 | 
			
		||||
    layer = state.theme.getMatchingLayer(entry.feature.properties)
 | 
			
		||||
    tags = state.featureProperties.getStore(entry.feature.properties.id)
 | 
			
		||||
    tags = state.featureProperties?.getStore(entry.feature.properties.id)
 | 
			
		||||
    descriptionTr = layer?.tagRenderings?.find((tr) => tr.labels.indexOf("description") >= 0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,29 +3,34 @@
 | 
			
		|||
   * Shows all the location-results
 | 
			
		||||
   */
 | 
			
		||||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import { Store } from "../../Logic/UIEventSource"
 | 
			
		||||
  import SidebarUnit from "../Base/SidebarUnit.svelte"
 | 
			
		||||
  import Loading from "../Base/Loading.svelte"
 | 
			
		||||
  import { default as GeocodeResultSvelte } from "./GeocodeResult.svelte"
 | 
			
		||||
  import Tr from "../Base/Tr.svelte"
 | 
			
		||||
  import DotMenu from "../Base/DotMenu.svelte"
 | 
			
		||||
  import { CogIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
			
		||||
  import { TrashIcon } from "@babeard/svelte-heroicons/mini"
 | 
			
		||||
  import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
			
		||||
  import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
 | 
			
		||||
  import { WithSearchState } from "../../Models/ThemeViewState/WithSearchState"
 | 
			
		||||
  import type { MapProperties } from "../../Models/MapProperties"
 | 
			
		||||
 | 
			
		||||
  export let state: WithSearchState
 | 
			
		||||
  export let state: {
 | 
			
		||||
    searchState: {
 | 
			
		||||
      searchTerm: UIEventSource<string>
 | 
			
		||||
      suggestions: Store<GeocodeResult[]>
 | 
			
		||||
      suggestionsSearchRunning: Store<boolean>
 | 
			
		||||
    }, mapProperties: MapProperties
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let searchTerm = state.searchState.searchTerm
 | 
			
		||||
  let results = state.searchState.suggestions
 | 
			
		||||
  let isSearching = state.searchState.suggestionsSearchRunning
 | 
			
		||||
  let recentlySeen: Store<GeocodeResult[]> = state.userRelatedState.recentlyVisitedSearch.value
 | 
			
		||||
  let isSearching = state.searchState.suggestionsSearchRunning ?? new ImmutableStore(false)
 | 
			
		||||
 | 
			
		||||
  const t = Translations.t.general.search
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if $searchTerm.length > 0}
 | 
			
		||||
  <SidebarUnit>
 | 
			
		||||
    <h3><Tr t={t.locations} /></h3>
 | 
			
		||||
    <h3>
 | 
			
		||||
      <Tr t={t.locations} />
 | 
			
		||||
    </h3>
 | 
			
		||||
 | 
			
		||||
    {#if $results?.length > 0}
 | 
			
		||||
      {#each $results as entry (entry)}
 | 
			
		||||
| 
						 | 
				
			
			@ -41,35 +46,12 @@
 | 
			
		|||
      </div>
 | 
			
		||||
    {/if}
 | 
			
		||||
 | 
			
		||||
    {#if !$isSearching && $results.length === 0}
 | 
			
		||||
    {#if !$isSearching && $results?.length === 0}
 | 
			
		||||
      <b class="flex justify-center p-4">
 | 
			
		||||
        <Tr t={t.nothingFor.Subs({ term: "<i>" + $searchTerm + "</i>" })} />
 | 
			
		||||
      </b>
 | 
			
		||||
    {/if}
 | 
			
		||||
  </SidebarUnit>
 | 
			
		||||
{:else if $recentlySeen?.length > 0}
 | 
			
		||||
  <SidebarUnit>
 | 
			
		||||
    <div class="flex justify-between">
 | 
			
		||||
      <h3 class="m-2">
 | 
			
		||||
        <Tr t={t.recents} />
 | 
			
		||||
      </h3>
 | 
			
		||||
      <DotMenu>
 | 
			
		||||
        <button
 | 
			
		||||
          on:click={() => {
 | 
			
		||||
            state.userRelatedState.recentlyVisitedSearch.clear()
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <TrashIcon />
 | 
			
		||||
          <Tr t={t.deleteSearchHistory} />
 | 
			
		||||
        </button>
 | 
			
		||||
        <button on:click={() => state.guistate.openUsersettings("sync-visited-locations")}>
 | 
			
		||||
          <CogIcon />
 | 
			
		||||
          <Tr t={t.editSearchSyncSettings} />
 | 
			
		||||
        </button>
 | 
			
		||||
      </DotMenu>
 | 
			
		||||
    </div>
 | 
			
		||||
    {#each $recentlySeen as entry (entry)}
 | 
			
		||||
      <GeocodeResultSvelte {entry} {state} on:select />
 | 
			
		||||
    {/each}
 | 
			
		||||
  </SidebarUnit>
 | 
			
		||||
{:else}
 | 
			
		||||
  <slot name="if-no-results" />
 | 
			
		||||
{/if}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,12 @@
 | 
			
		|||
  import Translations from "../i18n/Translations"
 | 
			
		||||
  import type { FilterSearchResult } from "../../Logic/Search/FilterSearch"
 | 
			
		||||
  import { WithSearchState } from "../../Models/ThemeViewState/WithSearchState"
 | 
			
		||||
  import { TrashIcon } from "@babeard/svelte-heroicons/mini"
 | 
			
		||||
  import { CogIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
			
		||||
  import SidebarUnit from "../Base/SidebarUnit.svelte"
 | 
			
		||||
  import DotMenu from "../Base/DotMenu.svelte"
 | 
			
		||||
  import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
 | 
			
		||||
  import { default as GeocodeResultSvelte } from "./GeocodeResult.svelte"
 | 
			
		||||
 | 
			
		||||
  export let state: WithSearchState
 | 
			
		||||
  let activeFilters: Store<(ActiveFilter & FilterSearchResult)[]> =
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +32,9 @@
 | 
			
		|||
          return r
 | 
			
		||||
        })
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
  let searchTerm = state.searchState.searchTerm
 | 
			
		||||
  let recentlySeen: Store<GeocodeResult[]> = state.userRelatedState.recentlyVisitedSearch.value
 | 
			
		||||
 | 
			
		||||
  let allowOtherThemes = state.featureSwitches.featureSwitchBackToThemeOverview
 | 
			
		||||
  let allowFilters = state.featureSwitches.featureSwitchFilter
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +55,38 @@
 | 
			
		|||
  {#if $allowFilters}
 | 
			
		||||
    <FilterResults {state} />
 | 
			
		||||
  {/if}
 | 
			
		||||
  <GeocodeResults {state} />
 | 
			
		||||
  <GeocodeResults {state}>
 | 
			
		||||
    <svelte:fragment slot="if-no-results">
 | 
			
		||||
 | 
			
		||||
      {#if $recentlySeen?.length > 0}
 | 
			
		||||
        <SidebarUnit>
 | 
			
		||||
          <div class="flex justify-between">
 | 
			
		||||
            <h3 class="m-2">
 | 
			
		||||
              <Tr t={Translations.t.general.search.recents} />
 | 
			
		||||
            </h3>
 | 
			
		||||
            <DotMenu>
 | 
			
		||||
              <button
 | 
			
		||||
                on:click={() => {
 | 
			
		||||
            state.userRelatedState.recentlyVisitedSearch.clear()
 | 
			
		||||
          }}
 | 
			
		||||
              >
 | 
			
		||||
                <TrashIcon />
 | 
			
		||||
                <Tr t={Translations.t.general.search.deleteSearchHistory} />
 | 
			
		||||
              </button>
 | 
			
		||||
              <button on:click={() => state.guistate.openUsersettings("sync-visited-locations")}>
 | 
			
		||||
                <CogIcon />
 | 
			
		||||
                <Tr t={Translations.t.general.search.editSearchSyncSettings} />
 | 
			
		||||
              </button>
 | 
			
		||||
            </DotMenu>
 | 
			
		||||
          </div>
 | 
			
		||||
          {#each $recentlySeen as entry (entry)}
 | 
			
		||||
            <GeocodeResultSvelte {entry} {state} on:select />
 | 
			
		||||
          {/each}
 | 
			
		||||
        </SidebarUnit>
 | 
			
		||||
      {/if}
 | 
			
		||||
    </svelte:fragment>
 | 
			
		||||
 | 
			
		||||
  </GeocodeResults>
 | 
			
		||||
 | 
			
		||||
  {#if $allowOtherThemes}
 | 
			
		||||
    <ThemeResults {state} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
{"properties":{"name":"Bing Maps Aerial","id":"Bing","url":"https://ecn.t2.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=15066&pr=odbl&n=f","type":"bing","category":"photo","min_zoom":1,"max_zoom":22},"type":"Feature","geometry":null}
 | 
			
		||||
{"properties":{"name":"Bing Maps Aerial","id":"Bing","url":"https://ecn.t2.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=15075&pr=odbl&n=f","type":"bing","category":"photo","min_zoom":1,"max_zoom":22},"type":"Feature","geometry":null}
 | 
			
		||||
| 
						 | 
				
			
			@ -465,6 +465,11 @@ code {
 | 
			
		|||
    background-color: #b3b3b3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.frozen-glass {
 | 
			
		||||
    backdrop-filter: blur(1px);
 | 
			
		||||
    background: rgba(100, 100, 100, 0.50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************** UTILITY ************************/
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue