forked from MapComplete/MapComplete
		
	Merge pull request #1592 from pietervdvn/RobinLinde-patch-1
Add some vending options
This commit is contained in:
		
						commit
						7d9192dd26
					
				
					 9 changed files with 864 additions and 631 deletions
				
			
		| 
						 | 
					@ -32,7 +32,9 @@
 | 
				
			||||||
    "mappings": [
 | 
					    "mappings": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "if": "name~*",
 | 
					        "if": "name~*",
 | 
				
			||||||
        "then": "Bicycle tube vending machine {name}"
 | 
					        "then": {
 | 
				
			||||||
 | 
					          "en": "Bicycle tube vending machine {name}"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					@ -70,8 +72,7 @@
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "tags": [
 | 
					      "tags": [
 | 
				
			||||||
        "amenity=vending_machine",
 | 
					        "amenity=vending_machine",
 | 
				
			||||||
        "vending=bicycle_tube",
 | 
					        "vending=bicycle_tube"
 | 
				
			||||||
        "vending:bicycle_tube=yes"
 | 
					 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
| 
						 | 
					@ -176,65 +177,62 @@
 | 
				
			||||||
      "id": "Still in use?"
 | 
					      "id": "Still in use?"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "question": "How much does a bicycle tube cost?",
 | 
					      "question": {
 | 
				
			||||||
      "render": "A bicycle tube costs {charge}",
 | 
					        "en": "How much does a bicycle tube cost?"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "render": {
 | 
				
			||||||
 | 
					        "en": "A bicycle tube costs {charge}"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "freeform": {
 | 
					      "freeform": {
 | 
				
			||||||
        "key": "charge"
 | 
					        "key": "charge"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "id": "bicycle_tube_vending_machine-charge"
 | 
					      "id": "bicycle_tube_vending_machine-charge"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "payment-options-split",
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "vending-machine-payment-methods",
 | 
					      "question": {
 | 
				
			||||||
      "question": "How can one pay at this tube vending machine?",
 | 
					        "en": "Which brand of tubes are sold here?"
 | 
				
			||||||
      "mappings": [
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "if": "payment:coins=yes",
 | 
					 | 
				
			||||||
          "ifnot": "payment:coins=no",
 | 
					 | 
				
			||||||
          "then": "Payment with coins is possible"
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "if": "payment:notes=yes",
 | 
					 | 
				
			||||||
          "ifnot": "payment:notes=no",
 | 
					 | 
				
			||||||
          "then": "Payment with notes is possible"
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          "if": "payment:cards=yes",
 | 
					 | 
				
			||||||
          "ifnot": "payment:cards=no",
 | 
					 | 
				
			||||||
          "then": "Payment with cards is possible"
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      "multiAnswer": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "question": "Which brand of tubes are sold here?",
 | 
					 | 
				
			||||||
      "freeform": {
 | 
					      "freeform": {
 | 
				
			||||||
        "key": "brand"
 | 
					        "key": "brand"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "render": "{brand} tubes are sold here",
 | 
					      "render": {
 | 
				
			||||||
 | 
					        "en": "{brand} tubes are sold here"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "mappings": [
 | 
					      "mappings": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "brand=Continental",
 | 
					          "if": "brand=Continental",
 | 
				
			||||||
          "then": "Continental tubes are sold here"
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Continental tubes are sold here"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "brand=Schwalbe",
 | 
					          "if": "brand=Schwalbe",
 | 
				
			||||||
          "then": "Schwalbe tubes are sold here"
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Schwalbe tubes are sold here"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "multiAnswer": true,
 | 
					      "multiAnswer": true,
 | 
				
			||||||
      "id": "bicycle_tube_vending_machine-brand"
 | 
					      "id": "bicycle_tube_vending_machine-brand"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "question": "Who maintains this vending machine?",
 | 
					      "question": {
 | 
				
			||||||
 | 
					        "en": "Who maintains this vending machine?"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "render": "This vending machine is maintained by {operator}",
 | 
					      "render": "This vending machine is maintained by {operator}",
 | 
				
			||||||
      "mappings": [
 | 
					      "mappings": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "operator=Schwalbe",
 | 
					          "if": "operator=Schwalbe",
 | 
				
			||||||
          "then": "Maintained by Schwalbe"
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Maintained by Schwalbe"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "operator=Continental",
 | 
					          "if": "operator=Continental",
 | 
				
			||||||
          "then": "Maintained by Continental"
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Maintained by Continental"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "freeform": {
 | 
					      "freeform": {
 | 
				
			||||||
| 
						 | 
					@ -243,33 +241,52 @@
 | 
				
			||||||
      "id": "bicycle_tube_vending_machine-operator"
 | 
					      "id": "bicycle_tube_vending_machine-operator"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "id": "bicycle_tube_vending_maching-other-items",
 | 
					      "id": "other-items-vending",
 | 
				
			||||||
      "question": "Are other bicycle bicycle accessories sold here?",
 | 
					      "question": {
 | 
				
			||||||
 | 
					        "en": "Are other biycle accessories sold here?"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "mappings": [
 | 
					      "mappings": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending:bicycle_light=yes",
 | 
					          "if": "vending=bicycle_tube",
 | 
				
			||||||
          "ifnot": "vending:bicycle_light=no",
 | 
					          "then": {
 | 
				
			||||||
          "then": "Bicycle lights are sold here"
 | 
					            "en": "Bicycle inner tubes are sold here",
 | 
				
			||||||
 | 
					            "nl": "Fietsbinnenbanden worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending:gloves=yes",
 | 
					          "if": "vending=bicycle_light",
 | 
				
			||||||
          "ifnot": "vending:gloves=no",
 | 
					          "then": {
 | 
				
			||||||
          "then": "Gloves are sold here"
 | 
					            "en": "Bicycle lights are sold here",
 | 
				
			||||||
 | 
					            "nl": "Fietslampjes worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending:bicycle_repair_kit=yes",
 | 
					          "if": "vending=gloves",
 | 
				
			||||||
          "ifnot": "vending:bicycle_repair_kit=no",
 | 
					          "then": {
 | 
				
			||||||
          "then": "Bicycle repair kits are sold here"
 | 
					            "en": "Gloves are sold here",
 | 
				
			||||||
 | 
					            "nl": "Handschoenen worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending:bicycle_pump=yes",
 | 
					          "if": "vending=bicycle_repair_kit",
 | 
				
			||||||
          "ifnot": "vending:bicycle_pump=no",
 | 
					          "then": {
 | 
				
			||||||
          "then": "Bicycle pumps are sold here"
 | 
					            "en": "Bicycle repair kits are sold here",
 | 
				
			||||||
 | 
					            "nl": "Fietsreparatiesets worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending:bicycle_lock=yes",
 | 
					          "if": "vending=bicycle_pump",
 | 
				
			||||||
          "ifnot": "vending:bicycle_lock=no",
 | 
					          "then": {
 | 
				
			||||||
          "then": "Bicycle locks are sold here"
 | 
					            "en": "Bicycle pumps are sold here",
 | 
				
			||||||
 | 
					            "nl": "Fietspompen worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=bicycle_lock",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Bicycle locks are sold here",
 | 
				
			||||||
 | 
					            "nl": "Fietssloten worden hier verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "multiAnswer": true
 | 
					      "multiAnswer": true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,6 +242,14 @@
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "icon": "./assets/layers/vending_machine/potato.svg"
 | 
					          "icon": "./assets/layers/vending_machine/potato.svg"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=meat",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Meat is sold",
 | 
				
			||||||
 | 
					            "nl": "Vlees wordt verkocht"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "icon": "./assets/layers/id_presets/temaki-meat.svg"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending=flowers",
 | 
					          "if": "vending=flowers",
 | 
				
			||||||
          "then": {
 | 
					          "then": {
 | 
				
			||||||
| 
						 | 
					@ -282,12 +290,39 @@
 | 
				
			||||||
          "icon": "./assets/themes/stations/public_transport_tickets.svg"
 | 
					          "icon": "./assets/themes/stations/public_transport_tickets.svg"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "if": "vending=meat",
 | 
					          "if": "vending=bicycle_light",
 | 
				
			||||||
          "then": {
 | 
					          "then": {
 | 
				
			||||||
            "en": "Meat products are being sold",
 | 
					            "en": "Bicycle lights are sold",
 | 
				
			||||||
            "nl": "Vleesproducten worden hier verkocht"
 | 
					            "nl": "Fietslampjes worden verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
          "icon": "./assets/layers/id_presets/temaki-meat.svg"
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=gloves",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Gloves are sold",
 | 
				
			||||||
 | 
					            "nl": "Handschoenen worden verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=bicycle_repair_kit",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Bicycle repair kits are sold",
 | 
				
			||||||
 | 
					            "nl": "Fietsreparatiesets worden verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=bicycle_pump",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Bicycle pumps are sold",
 | 
				
			||||||
 | 
					            "nl": "Fietspompen worden verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "vending=bicycle_lock",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "Bicycle locks are sold",
 | 
				
			||||||
 | 
					            "nl": "Fietssloten worden verkocht"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "multiAnswer": true
 | 
					      "multiAnswer": true
 | 
				
			||||||
| 
						 | 
					@ -453,6 +488,10 @@
 | 
				
			||||||
            "if": "vending=potatoes",
 | 
					            "if": "vending=potatoes",
 | 
				
			||||||
            "then": "circle:white;./assets/layers/vending_machine/potato.svg"
 | 
					            "then": "circle:white;./assets/layers/vending_machine/potato.svg"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "if": "vending=meat",
 | 
				
			||||||
 | 
					            "then": "./assets/layers/id_presets/temaki-meat.svg"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            "if": "vending=flowers",
 | 
					            "if": "vending=flowers",
 | 
				
			||||||
            "then": "circle:white;./assets/layers/id_presets/maki-florist.svg"
 | 
					            "then": "circle:white;./assets/layers/id_presets/maki-florist.svg"
 | 
				
			||||||
| 
						 | 
					@ -792,6 +831,14 @@
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "osmTags": "vending~i~.*potatoes.*"
 | 
					          "osmTags": "vending~i~.*potatoes.*"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "question": {
 | 
				
			||||||
 | 
					            "en": "Sale of meat",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van vlees",
 | 
				
			||||||
 | 
					            "de": "Verkauf von Fleisch"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "osmTags": "vending~i~.*meat.*"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "question": {
 | 
					          "question": {
 | 
				
			||||||
            "en": "Sale of flowers",
 | 
					            "en": "Sale of flowers",
 | 
				
			||||||
| 
						 | 
					@ -805,7 +852,7 @@
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "osmTags": "vending~i~.*parking_tickets.*",
 | 
					          "osmTags": "vending~i~.*parking_tickets.*",
 | 
				
			||||||
          "question": {
 | 
					          "question": {
 | 
				
			||||||
            "en": "Sale of parking"
 | 
					            "en": "Sale of parking tickets"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -821,9 +868,38 @@
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "osmTags": "vending=meat",
 | 
					          "osmTags": "vending=bicycle_light",
 | 
				
			||||||
          "question": {
 | 
					          "question": {
 | 
				
			||||||
            "en": "Sale of meat products"
 | 
					            "en": "Sale of bicycle lights",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van fietslampjes"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "osmTags": "vending=gloves",
 | 
				
			||||||
 | 
					          "question": {
 | 
				
			||||||
 | 
					            "en": "Sale of gloves",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van handschoenen"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "osmTags": "vending=bicycle_repair_kit",
 | 
				
			||||||
 | 
					          "question": {
 | 
				
			||||||
 | 
					            "en": "Sale of bicycle repair kits",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van fietsreparatiesets"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "osmTags": "vending=bicycle_pump",
 | 
				
			||||||
 | 
					          "question": {
 | 
				
			||||||
 | 
					            "en": "Sale of bicycle pumps",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van fietspompen"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "osmTags": "vending=bicycle_lock",
 | 
				
			||||||
 | 
					          "question": {
 | 
				
			||||||
 | 
					            "en": "Sale of bicycle locks",
 | 
				
			||||||
 | 
					            "nl": "Verkoop van fietssloten"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8073,7 +8073,7 @@
 | 
				
			||||||
                    "15": {
 | 
					                    "15": {
 | 
				
			||||||
                        "question": "Venda de patates"
 | 
					                        "question": "Venda de patates"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "17": {
 | 
				
			||||||
                        "question": "Venda de flors"
 | 
					                        "question": "Venda de flors"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -8154,16 +8154,16 @@
 | 
				
			||||||
                    "14": {
 | 
					                    "14": {
 | 
				
			||||||
                        "then": "Es venen papes"
 | 
					                        "then": "Es venen papes"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "15": {
 | 
					                    "16": {
 | 
				
			||||||
                        "then": "Es venen flors"
 | 
					                        "then": "Es venen flors"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "17": {
 | 
				
			||||||
                        "then": "Es venen tiquets d'aparcament"
 | 
					                        "then": "Es venen tiquets d'aparcament"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "17": {
 | 
					                    "18": {
 | 
				
			||||||
                        "then": "Es venen cèntims premsats"
 | 
					                        "then": "Es venen cèntims premsats"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "18": {
 | 
					                    "19": {
 | 
				
			||||||
                        "then": "Es venen bitllets de transport públic"
 | 
					                        "then": "Es venen bitllets de transport públic"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9762,6 +9762,9 @@
 | 
				
			||||||
                        "question": "Verkauf von Kartoffeln"
 | 
					                        "question": "Verkauf von Kartoffeln"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "16": {
 | 
				
			||||||
 | 
					                        "question": "Verkauf von Fleisch"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "17": {
 | 
				
			||||||
                        "question": "Verkauf von Blumen"
 | 
					                        "question": "Verkauf von Blumen"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -9842,13 +9845,13 @@
 | 
				
			||||||
                    "14": {
 | 
					                    "14": {
 | 
				
			||||||
                        "then": "Kartoffeln werden verkauft"
 | 
					                        "then": "Kartoffeln werden verkauft"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "15": {
 | 
					                    "16": {
 | 
				
			||||||
                        "then": "Blumen werden verkauft"
 | 
					                        "then": "Blumen werden verkauft"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "17": {
 | 
				
			||||||
                        "then": "Parkscheine werden verkauft"
 | 
					                        "then": "Parkscheine werden verkauft"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "18": {
 | 
					                    "19": {
 | 
				
			||||||
                        "then": "Fahrscheine werden verkauft"
 | 
					                        "then": "Fahrscheine werden verkauft"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1034,9 +1034,64 @@
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "Is this vending machine still operational?",
 | 
					                "question": "Is this vending machine still operational?",
 | 
				
			||||||
                "render": "The operational status is <i>{operational_status}</i>"
 | 
					                "render": "The operational status is <i>{operational_status}</i>"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "bicycle_tube_vending_machine-brand": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Continental tubes are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Schwalbe tubes are sold here"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Which brand of tubes are sold here?",
 | 
				
			||||||
 | 
					                "render": "{brand} tubes are sold here"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "bicycle_tube_vending_machine-charge": {
 | 
				
			||||||
 | 
					                "question": "How much does a bicycle tube cost?",
 | 
				
			||||||
 | 
					                "render": "A bicycle tube costs {charge}"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "bicycle_tube_vending_machine-operator": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Maintained by Schwalbe"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Maintained by Continental"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Who maintains this vending machine?"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "other-items-vending": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle inner tubes are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle lights are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "2": {
 | 
				
			||||||
 | 
					                        "then": "Gloves are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "3": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle repair kits are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "4": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle pumps are sold here"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "5": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle locks are sold here"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Are other biycle accessories sold here?"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "title": {
 | 
					        "title": {
 | 
				
			||||||
 | 
					            "mappings": {
 | 
				
			||||||
 | 
					                "0": {
 | 
				
			||||||
 | 
					                    "then": "Bicycle tube vending machine {name}"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            "render": "Bicycle tube vending machine"
 | 
					            "render": "Bicycle tube vending machine"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					@ -9900,19 +9955,34 @@
 | 
				
			||||||
                        "question": "Sale of potatoes"
 | 
					                        "question": "Sale of potatoes"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "16": {
 | 
				
			||||||
                        "question": "Sale of flowers"
 | 
					                        "question": "Sale of meat"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "17": {
 | 
					                    "17": {
 | 
				
			||||||
                        "question": "Sale of parking"
 | 
					                        "question": "Sale of flowers"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "18": {
 | 
					                    "18": {
 | 
				
			||||||
                        "question": "Sale of pressed pennies"
 | 
					                        "question": "Sale of parking tickets"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "19": {
 | 
					                    "19": {
 | 
				
			||||||
                        "question": "Sale of public transport tickets"
 | 
					                        "question": "Sale of pressed pennies"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "20": {
 | 
					                    "20": {
 | 
				
			||||||
                        "question": "Sale of meat products"
 | 
					                        "question": "Sale of public transport tickets"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "21": {
 | 
				
			||||||
 | 
					                        "question": "Sale of bicycle lights"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "22": {
 | 
				
			||||||
 | 
					                        "question": "Sale of gloves"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "23": {
 | 
				
			||||||
 | 
					                        "question": "Sale of bicycle repair kits"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "24": {
 | 
				
			||||||
 | 
					                        "question": "Sale of bicycle pumps"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "25": {
 | 
				
			||||||
 | 
					                        "question": "Sale of bicycle locks"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -9999,19 +10069,34 @@
 | 
				
			||||||
                        "then": "Potatoes are sold"
 | 
					                        "then": "Potatoes are sold"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "15": {
 | 
					                    "15": {
 | 
				
			||||||
                        "then": "Flowers are sold"
 | 
					                        "then": "Meat is sold"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "16": {
 | 
				
			||||||
                        "then": "Parking tickets are sold"
 | 
					                        "then": "Flowers are sold"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "17": {
 | 
					                    "17": {
 | 
				
			||||||
                        "then": "Pressed pennies are sold"
 | 
					                        "then": "Parking tickets are sold"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "18": {
 | 
					                    "18": {
 | 
				
			||||||
                        "then": "Public transport tickets are sold"
 | 
					                        "then": "Pressed pennies are sold"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "19": {
 | 
					                    "19": {
 | 
				
			||||||
                        "then": "Meat products are being sold"
 | 
					                        "then": "Public transport tickets are sold"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "20": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle lights are sold"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "21": {
 | 
				
			||||||
 | 
					                        "then": "Gloves are sold"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "22": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle repair kits are sold"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "23": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle pumps are sold"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "24": {
 | 
				
			||||||
 | 
					                        "then": "Bicycle locks are sold"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "What does this vending machine sell?",
 | 
					                "question": "What does this vending machine sell?",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6576,7 +6576,7 @@
 | 
				
			||||||
                    "15": {
 | 
					                    "15": {
 | 
				
			||||||
                        "question": "Vente de pommes de terre"
 | 
					                        "question": "Vente de pommes de terre"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "17": {
 | 
				
			||||||
                        "question": "Vente de fleurs"
 | 
					                        "question": "Vente de fleurs"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -6657,7 +6657,7 @@
 | 
				
			||||||
                    "14": {
 | 
					                    "14": {
 | 
				
			||||||
                        "then": "Vent des pommes de terre"
 | 
					                        "then": "Vent des pommes de terre"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "15": {
 | 
					                    "16": {
 | 
				
			||||||
                        "then": "Vent des fleurs"
 | 
					                        "then": "Vent des fleurs"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -930,6 +930,28 @@
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "Is deze verkoopsautomaat nog steeds werkende?",
 | 
					                "question": "Is deze verkoopsautomaat nog steeds werkende?",
 | 
				
			||||||
                "render": "Deze verkoopsautomaat is <i>{operational_status}</i>"
 | 
					                "render": "Deze verkoopsautomaat is <i>{operational_status}</i>"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "other-items-vending": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Fietsbinnenbanden worden hier verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Fietslampjes worden hier verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "2": {
 | 
				
			||||||
 | 
					                        "then": "Handschoenen worden hier verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "3": {
 | 
				
			||||||
 | 
					                        "then": "Fietsreparatiesets worden hier verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "4": {
 | 
				
			||||||
 | 
					                        "then": "Fietspompen worden hier verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "5": {
 | 
				
			||||||
 | 
					                        "then": "Fietssloten worden hier verkocht"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "title": {
 | 
					        "title": {
 | 
				
			||||||
| 
						 | 
					@ -9055,7 +9077,25 @@
 | 
				
			||||||
                        "question": "Verkoop van aardappelen"
 | 
					                        "question": "Verkoop van aardappelen"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "16": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van vlees"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "17": {
 | 
				
			||||||
                        "question": "Verkoop van bloemen"
 | 
					                        "question": "Verkoop van bloemen"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "21": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van fietslampjes"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "22": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van handschoenen"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "23": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van fietsreparatiesets"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "24": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van fietspompen"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "25": {
 | 
				
			||||||
 | 
					                        "question": "Verkoop van fietssloten"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -9136,16 +9176,31 @@
 | 
				
			||||||
                        "then": "Aardappelen worden verkocht"
 | 
					                        "then": "Aardappelen worden verkocht"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "15": {
 | 
					                    "15": {
 | 
				
			||||||
                        "then": "Bloemen worden verkocht"
 | 
					                        "then": "Vlees wordt verkocht"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "16": {
 | 
					                    "16": {
 | 
				
			||||||
 | 
					                        "then": "Bloemen worden verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "17": {
 | 
				
			||||||
                        "then": "Parkeerkaarten worden verkocht"
 | 
					                        "then": "Parkeerkaarten worden verkocht"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "18": {
 | 
					                    "19": {
 | 
				
			||||||
                        "then": "Openbaar vervoerkaartjes worden verkocht"
 | 
					                        "then": "Openbaar vervoerkaartjes worden verkocht"
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    "19": {
 | 
					                    "20": {
 | 
				
			||||||
                        "then": "Vleesproducten worden hier verkocht"
 | 
					                        "then": "Fietslampjes worden verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "21": {
 | 
				
			||||||
 | 
					                        "then": "Handschoenen worden verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "22": {
 | 
				
			||||||
 | 
					                        "then": "Fietsreparatiesets worden verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "23": {
 | 
				
			||||||
 | 
					                        "then": "Fietspompen worden verkocht"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "24": {
 | 
				
			||||||
 | 
					                        "then": "Fietssloten worden verkocht"
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "Wat verkoopt deze verkoopautomaat?",
 | 
					                "question": "Wat verkoopt deze verkoopautomaat?",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,63 +1,63 @@
 | 
				
			||||||
// @ts-ignore
 | 
					// @ts-ignore
 | 
				
			||||||
import { osmAuth } from "osm-auth";
 | 
					import { osmAuth } from "osm-auth"
 | 
				
			||||||
import { Store, Stores, UIEventSource } from "../UIEventSource";
 | 
					import { Store, Stores, UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import { OsmPreferences } from "./OsmPreferences";
 | 
					import { OsmPreferences } from "./OsmPreferences"
 | 
				
			||||||
import { Utils } from "../../Utils";
 | 
					import { Utils } from "../../Utils"
 | 
				
			||||||
import { LocalStorageSource } from "../Web/LocalStorageSource";
 | 
					import { LocalStorageSource } from "../Web/LocalStorageSource"
 | 
				
			||||||
import * as config from "../../../package.json";
 | 
					import * as config from "../../../package.json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class UserDetails {
 | 
					export default class UserDetails {
 | 
				
			||||||
  public loggedIn = false;
 | 
					    public loggedIn = false
 | 
				
			||||||
  public name = "Not logged in";
 | 
					    public name = "Not logged in"
 | 
				
			||||||
  public uid: number;
 | 
					    public uid: number
 | 
				
			||||||
  public csCount = 0;
 | 
					    public csCount = 0
 | 
				
			||||||
  public img?: string;
 | 
					    public img?: string
 | 
				
			||||||
  public unreadMessages = 0;
 | 
					    public unreadMessages = 0
 | 
				
			||||||
  public totalMessages: number = 0;
 | 
					    public totalMessages: number = 0
 | 
				
			||||||
  public home: { lon: number; lat: number };
 | 
					    public home: { lon: number; lat: number }
 | 
				
			||||||
  public backend: string;
 | 
					    public backend: string
 | 
				
			||||||
  public account_created: string;
 | 
					    public account_created: string
 | 
				
			||||||
  public tracesCount: number = 0;
 | 
					    public tracesCount: number = 0
 | 
				
			||||||
  public description: string;
 | 
					    public description: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(backend: string) {
 | 
					    constructor(backend: string) {
 | 
				
			||||||
    this.backend = backend;
 | 
					        this.backend = backend
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface AuthConfig {
 | 
					export interface AuthConfig {
 | 
				
			||||||
  "#"?: string; // optional comment
 | 
					    "#"?: string // optional comment
 | 
				
			||||||
  oauth_client_id: string;
 | 
					    oauth_client_id: string
 | 
				
			||||||
  oauth_secret: string;
 | 
					    oauth_secret: string
 | 
				
			||||||
  url: string;
 | 
					    url: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable"
 | 
					export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class OsmConnection {
 | 
					export class OsmConnection {
 | 
				
			||||||
    public static readonly oauth_configs: Record<string, AuthConfig> =
 | 
					    public static readonly oauth_configs: Record<string, AuthConfig> =
 | 
				
			||||||
    config.config.oauth_credentials;
 | 
					        config.config.oauth_credentials
 | 
				
			||||||
  public auth;
 | 
					    public auth
 | 
				
			||||||
  public userDetails: UIEventSource<UserDetails>;
 | 
					    public userDetails: UIEventSource<UserDetails>
 | 
				
			||||||
  public isLoggedIn: Store<boolean>;
 | 
					    public isLoggedIn: Store<boolean>
 | 
				
			||||||
    public gpxServiceIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
 | 
					    public gpxServiceIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
 | 
				
			||||||
        "unknown"
 | 
					        "unknown"
 | 
				
			||||||
  );
 | 
					    )
 | 
				
			||||||
    public apiIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
 | 
					    public apiIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
 | 
				
			||||||
        "unknown"
 | 
					        "unknown"
 | 
				
			||||||
  );
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public loadingStatus = new UIEventSource<"not-attempted" | "loading" | "error" | "logged-in">(
 | 
					    public loadingStatus = new UIEventSource<"not-attempted" | "loading" | "error" | "logged-in">(
 | 
				
			||||||
        "not-attempted"
 | 
					        "not-attempted"
 | 
				
			||||||
  );
 | 
					    )
 | 
				
			||||||
  public preferencesHandler: OsmPreferences;
 | 
					    public preferencesHandler: OsmPreferences
 | 
				
			||||||
  public readonly _oauth_config: AuthConfig;
 | 
					    public readonly _oauth_config: AuthConfig
 | 
				
			||||||
  private readonly _dryRun: Store<boolean>;
 | 
					    private readonly _dryRun: Store<boolean>
 | 
				
			||||||
  private fakeUser: boolean;
 | 
					    private fakeUser: boolean
 | 
				
			||||||
  private _onLoggedIn: ((userDetails: UserDetails) => void)[] = [];
 | 
					    private _onLoggedIn: ((userDetails: UserDetails) => void)[] = []
 | 
				
			||||||
  private readonly _iframeMode: Boolean | boolean;
 | 
					    private readonly _iframeMode: Boolean | boolean
 | 
				
			||||||
  private readonly _singlePage: boolean;
 | 
					    private readonly _singlePage: boolean
 | 
				
			||||||
  private isChecking = false;
 | 
					    private isChecking = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(options?: {
 | 
					    constructor(options?: {
 | 
				
			||||||
        dryRun?: Store<boolean>
 | 
					        dryRun?: Store<boolean>
 | 
				
			||||||
| 
						 | 
					@ -68,83 +68,80 @@ export class OsmConnection {
 | 
				
			||||||
        osmConfiguration?: "osm" | "osm-test"
 | 
					        osmConfiguration?: "osm" | "osm-test"
 | 
				
			||||||
        attemptLogin?: true | boolean
 | 
					        attemptLogin?: true | boolean
 | 
				
			||||||
    }) {
 | 
					    }) {
 | 
				
			||||||
    options = options ?? {};
 | 
					        options = options ?? {}
 | 
				
			||||||
    this.fakeUser = options.fakeUser ?? false;
 | 
					        this.fakeUser = options.fakeUser ?? false
 | 
				
			||||||
    this._singlePage = options.singlePage ?? true;
 | 
					        this._singlePage = options.singlePage ?? true
 | 
				
			||||||
        this._oauth_config =
 | 
					        this._oauth_config =
 | 
				
			||||||
            OsmConnection.oauth_configs[options.osmConfiguration ?? "osm"] ??
 | 
					            OsmConnection.oauth_configs[options.osmConfiguration ?? "osm"] ??
 | 
				
			||||||
      OsmConnection.oauth_configs.osm;
 | 
					            OsmConnection.oauth_configs.osm
 | 
				
			||||||
    console.debug("Using backend", this._oauth_config.url);
 | 
					        console.debug("Using backend", this._oauth_config.url)
 | 
				
			||||||
    this._iframeMode = Utils.runningFromConsole ? false : window !== window.top;
 | 
					        this._iframeMode = Utils.runningFromConsole ? false : window !== window.top
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check if there are settings available in environment variables, and if so, use those
 | 
					        // Check if there are settings available in environment variables, and if so, use those
 | 
				
			||||||
        if (
 | 
					        if (
 | 
				
			||||||
            import.meta.env.VITE_OSM_OAUTH_CLIENT_ID !== undefined &&
 | 
					            import.meta.env.VITE_OSM_OAUTH_CLIENT_ID !== undefined &&
 | 
				
			||||||
            import.meta.env.VITE_OSM_OAUTH_SECRET !== undefined
 | 
					            import.meta.env.VITE_OSM_OAUTH_SECRET !== undefined
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
      console.debug("Using environment variables for oauth config");
 | 
					            console.debug("Using environment variables for oauth config")
 | 
				
			||||||
      this._oauth_config = {
 | 
					            this._oauth_config.oauth_client_id = import.meta.env.VITE_OSM_OAUTH_CLIENT_ID
 | 
				
			||||||
        oauth_client_id: import.meta.env.VITE_OSM_OAUTH_CLIENT_ID,
 | 
					            this._oauth_config.oauth_secret = import.meta.env.VITE_OSM_OAUTH_SECRET
 | 
				
			||||||
        oauth_secret: import.meta.env.VITE_OSM_OAUTH_SECRET,
 | 
					 | 
				
			||||||
        url: "https://api.openstreetmap.org"
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.userDetails = new UIEventSource<UserDetails>(
 | 
					        this.userDetails = new UIEventSource<UserDetails>(
 | 
				
			||||||
            new UserDetails(this._oauth_config.url),
 | 
					            new UserDetails(this._oauth_config.url),
 | 
				
			||||||
            "userDetails"
 | 
					            "userDetails"
 | 
				
			||||||
    );
 | 
					        )
 | 
				
			||||||
        if (options.fakeUser) {
 | 
					        if (options.fakeUser) {
 | 
				
			||||||
      const ud = this.userDetails.data;
 | 
					            const ud = this.userDetails.data
 | 
				
			||||||
      ud.csCount = 5678;
 | 
					            ud.csCount = 5678
 | 
				
			||||||
      ud.loggedIn = true;
 | 
					            ud.loggedIn = true
 | 
				
			||||||
      ud.unreadMessages = 0;
 | 
					            ud.unreadMessages = 0
 | 
				
			||||||
      ud.name = "Fake user";
 | 
					            ud.name = "Fake user"
 | 
				
			||||||
      ud.totalMessages = 42;
 | 
					            ud.totalMessages = 42
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    const self = this;
 | 
					        const self = this
 | 
				
			||||||
    this.UpdateCapabilities();
 | 
					        this.UpdateCapabilities()
 | 
				
			||||||
        this.isLoggedIn = this.userDetails.map(
 | 
					        this.isLoggedIn = this.userDetails.map(
 | 
				
			||||||
            (user) =>
 | 
					            (user) =>
 | 
				
			||||||
                user.loggedIn &&
 | 
					                user.loggedIn &&
 | 
				
			||||||
                (self.apiIsOnline.data === "unknown" || self.apiIsOnline.data === "online"),
 | 
					                (self.apiIsOnline.data === "unknown" || self.apiIsOnline.data === "online"),
 | 
				
			||||||
            [this.apiIsOnline]
 | 
					            [this.apiIsOnline]
 | 
				
			||||||
    );
 | 
					        )
 | 
				
			||||||
        this.isLoggedIn.addCallback((isLoggedIn) => {
 | 
					        this.isLoggedIn.addCallback((isLoggedIn) => {
 | 
				
			||||||
            if (self.userDetails.data.loggedIn == false && isLoggedIn == true) {
 | 
					            if (self.userDetails.data.loggedIn == false && isLoggedIn == true) {
 | 
				
			||||||
                // We have an inconsistency: the userdetails say we _didn't_ log in, but this actor says we do
 | 
					                // We have an inconsistency: the userdetails say we _didn't_ log in, but this actor says we do
 | 
				
			||||||
                // This means someone attempted to toggle this; so we attempt to login!
 | 
					                // This means someone attempted to toggle this; so we attempt to login!
 | 
				
			||||||
        self.AttemptLogin();
 | 
					                self.AttemptLogin()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this._dryRun = options.dryRun ?? new UIEventSource<boolean>(false);
 | 
					        this._dryRun = options.dryRun ?? new UIEventSource<boolean>(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.updateAuthObject();
 | 
					        this.updateAuthObject()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.preferencesHandler = new OsmPreferences(
 | 
					        this.preferencesHandler = new OsmPreferences(
 | 
				
			||||||
            this.auth,
 | 
					            this.auth,
 | 
				
			||||||
            <any /*This is needed to make the tests work*/>this
 | 
					            <any /*This is needed to make the tests work*/>this
 | 
				
			||||||
    );
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (options.oauth_token?.data !== undefined) {
 | 
					        if (options.oauth_token?.data !== undefined) {
 | 
				
			||||||
      console.log(options.oauth_token.data);
 | 
					            console.log(options.oauth_token.data)
 | 
				
			||||||
      const self = this;
 | 
					            const self = this
 | 
				
			||||||
            this.auth.bootstrapToken(
 | 
					            this.auth.bootstrapToken(
 | 
				
			||||||
                options.oauth_token.data,
 | 
					                options.oauth_token.data,
 | 
				
			||||||
                (x) => {
 | 
					                (x) => {
 | 
				
			||||||
          console.log("Called back: ", x);
 | 
					                    console.log("Called back: ", x)
 | 
				
			||||||
          self.AttemptLogin();
 | 
					                    self.AttemptLogin()
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                this.auth
 | 
					                this.auth
 | 
				
			||||||
      );
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      options.oauth_token.setData(undefined);
 | 
					            options.oauth_token.setData(undefined)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.auth.authenticated() && options.attemptLogin !== false) {
 | 
					        if (this.auth.authenticated() && options.attemptLogin !== false) {
 | 
				
			||||||
      this.AttemptLogin(); // Also updates the user badge
 | 
					            this.AttemptLogin() // Also updates the user badge
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
      console.log("Not authenticated");
 | 
					            console.log("Not authenticated")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,25 +153,25 @@ export class OsmConnection {
 | 
				
			||||||
            prefix?: string
 | 
					            prefix?: string
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ): UIEventSource<string> {
 | 
					    ): UIEventSource<string> {
 | 
				
			||||||
    return this.preferencesHandler.GetPreference(key, defaultValue, options);
 | 
					        return this.preferencesHandler.GetPreference(key, defaultValue, options)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public GetLongPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource<string> {
 | 
					    public GetLongPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource<string> {
 | 
				
			||||||
    return this.preferencesHandler.GetLongPreference(key, prefix);
 | 
					        return this.preferencesHandler.GetLongPreference(key, prefix)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public OnLoggedIn(action: (userDetails: UserDetails) => void) {
 | 
					    public OnLoggedIn(action: (userDetails: UserDetails) => void) {
 | 
				
			||||||
    this._onLoggedIn.push(action);
 | 
					        this._onLoggedIn.push(action)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public LogOut() {
 | 
					    public LogOut() {
 | 
				
			||||||
    this.auth.logout();
 | 
					        this.auth.logout()
 | 
				
			||||||
    this.userDetails.data.loggedIn = false;
 | 
					        this.userDetails.data.loggedIn = false
 | 
				
			||||||
    this.userDetails.data.csCount = 0;
 | 
					        this.userDetails.data.csCount = 0
 | 
				
			||||||
    this.userDetails.data.name = "";
 | 
					        this.userDetails.data.name = ""
 | 
				
			||||||
    this.userDetails.ping();
 | 
					        this.userDetails.ping()
 | 
				
			||||||
    console.log("Logged out");
 | 
					        console.log("Logged out")
 | 
				
			||||||
    this.loadingStatus.setData("not-attempted");
 | 
					        this.loadingStatus.setData("not-attempted")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -183,95 +180,95 @@ export class OsmConnection {
 | 
				
			||||||
     * new OsmConnection().Backend() // => "https://www.openstreetmap.org"
 | 
					     * new OsmConnection().Backend() // => "https://www.openstreetmap.org"
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public Backend(): string {
 | 
					    public Backend(): string {
 | 
				
			||||||
    return this._oauth_config.url;
 | 
					        return this._oauth_config.url
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AttemptLogin() {
 | 
					    public AttemptLogin() {
 | 
				
			||||||
    this.UpdateCapabilities();
 | 
					        this.UpdateCapabilities()
 | 
				
			||||||
    this.loadingStatus.setData("loading");
 | 
					        this.loadingStatus.setData("loading")
 | 
				
			||||||
        if (this.fakeUser) {
 | 
					        if (this.fakeUser) {
 | 
				
			||||||
      this.loadingStatus.setData("logged-in");
 | 
					            this.loadingStatus.setData("logged-in")
 | 
				
			||||||
      console.log("AttemptLogin called, but ignored as fakeUser is set");
 | 
					            console.log("AttemptLogin called, but ignored as fakeUser is set")
 | 
				
			||||||
      return;
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    const self = this;
 | 
					        const self = this
 | 
				
			||||||
    console.log("Trying to log in...");
 | 
					        console.log("Trying to log in...")
 | 
				
			||||||
    this.updateAuthObject();
 | 
					        this.updateAuthObject()
 | 
				
			||||||
        LocalStorageSource.Get("location_before_login").setData(
 | 
					        LocalStorageSource.Get("location_before_login").setData(
 | 
				
			||||||
            Utils.runningFromConsole ? undefined : window.location.href
 | 
					            Utils.runningFromConsole ? undefined : window.location.href
 | 
				
			||||||
    );
 | 
					        )
 | 
				
			||||||
        this.auth.xhr(
 | 
					        this.auth.xhr(
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                method: "GET",
 | 
					                method: "GET",
 | 
				
			||||||
        path: "/api/0.6/user/details"
 | 
					                path: "/api/0.6/user/details",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
      function(err, details) {
 | 
					            function (err, details) {
 | 
				
			||||||
                if (err != null) {
 | 
					                if (err != null) {
 | 
				
			||||||
          console.log(err);
 | 
					                    console.log(err)
 | 
				
			||||||
          self.loadingStatus.setData("error");
 | 
					                    self.loadingStatus.setData("error")
 | 
				
			||||||
                    if (err.status == 401) {
 | 
					                    if (err.status == 401) {
 | 
				
			||||||
            console.log("Clearing tokens...");
 | 
					                        console.log("Clearing tokens...")
 | 
				
			||||||
                        // Not authorized - our token probably got revoked
 | 
					                        // Not authorized - our token probably got revoked
 | 
				
			||||||
            self.auth.logout();
 | 
					                        self.auth.logout()
 | 
				
			||||||
            self.LogOut();
 | 
					                        self.LogOut()
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
          return;
 | 
					                    return
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (details == null) {
 | 
					                if (details == null) {
 | 
				
			||||||
          self.loadingStatus.setData("error");
 | 
					                    self.loadingStatus.setData("error")
 | 
				
			||||||
          return;
 | 
					                    return
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.CheckForMessagesContinuously();
 | 
					                self.CheckForMessagesContinuously()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // details is an XML DOM of user details
 | 
					                // details is an XML DOM of user details
 | 
				
			||||||
        let userInfo = details.getElementsByTagName("user")[0];
 | 
					                let userInfo = details.getElementsByTagName("user")[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let data = self.userDetails.data;
 | 
					                let data = self.userDetails.data
 | 
				
			||||||
        data.loggedIn = true;
 | 
					                data.loggedIn = true
 | 
				
			||||||
        console.log("Login completed, userinfo is ", userInfo);
 | 
					                console.log("Login completed, userinfo is ", userInfo)
 | 
				
			||||||
        data.name = userInfo.getAttribute("display_name");
 | 
					                data.name = userInfo.getAttribute("display_name")
 | 
				
			||||||
        data.account_created = userInfo.getAttribute("account_created");
 | 
					                data.account_created = userInfo.getAttribute("account_created")
 | 
				
			||||||
        data.uid = Number(userInfo.getAttribute("id"));
 | 
					                data.uid = Number(userInfo.getAttribute("id"))
 | 
				
			||||||
                data.csCount = Number.parseInt(
 | 
					                data.csCount = Number.parseInt(
 | 
				
			||||||
                    userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? 0
 | 
					                    userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? 0
 | 
				
			||||||
        );
 | 
					                )
 | 
				
			||||||
                data.tracesCount = Number.parseInt(
 | 
					                data.tracesCount = Number.parseInt(
 | 
				
			||||||
                    userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? 0
 | 
					                    userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? 0
 | 
				
			||||||
        );
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data.img = undefined;
 | 
					                data.img = undefined
 | 
				
			||||||
        const imgEl = userInfo.getElementsByTagName("img");
 | 
					                const imgEl = userInfo.getElementsByTagName("img")
 | 
				
			||||||
                if (imgEl !== undefined && imgEl[0] !== undefined) {
 | 
					                if (imgEl !== undefined && imgEl[0] !== undefined) {
 | 
				
			||||||
          data.img = imgEl[0].getAttribute("href");
 | 
					                    data.img = imgEl[0].getAttribute("href")
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const description = userInfo.getElementsByTagName("description");
 | 
					                const description = userInfo.getElementsByTagName("description")
 | 
				
			||||||
                if (description !== undefined && description[0] !== undefined) {
 | 
					                if (description !== undefined && description[0] !== undefined) {
 | 
				
			||||||
          data.description = description[0]?.innerHTML;
 | 
					                    data.description = description[0]?.innerHTML
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        const homeEl = userInfo.getElementsByTagName("home");
 | 
					                const homeEl = userInfo.getElementsByTagName("home")
 | 
				
			||||||
                if (homeEl !== undefined && homeEl[0] !== undefined) {
 | 
					                if (homeEl !== undefined && homeEl[0] !== undefined) {
 | 
				
			||||||
          const lat = parseFloat(homeEl[0].getAttribute("lat"));
 | 
					                    const lat = parseFloat(homeEl[0].getAttribute("lat"))
 | 
				
			||||||
          const lon = parseFloat(homeEl[0].getAttribute("lon"));
 | 
					                    const lon = parseFloat(homeEl[0].getAttribute("lon"))
 | 
				
			||||||
          data.home = { lat: lat, lon: lon };
 | 
					                    data.home = { lat: lat, lon: lon }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.loadingStatus.setData("logged-in");
 | 
					                self.loadingStatus.setData("logged-in")
 | 
				
			||||||
                const messages = userInfo
 | 
					                const messages = userInfo
 | 
				
			||||||
                    .getElementsByTagName("messages")[0]
 | 
					                    .getElementsByTagName("messages")[0]
 | 
				
			||||||
          .getElementsByTagName("received")[0];
 | 
					                    .getElementsByTagName("received")[0]
 | 
				
			||||||
        data.unreadMessages = parseInt(messages.getAttribute("unread"));
 | 
					                data.unreadMessages = parseInt(messages.getAttribute("unread"))
 | 
				
			||||||
        data.totalMessages = parseInt(messages.getAttribute("count"));
 | 
					                data.totalMessages = parseInt(messages.getAttribute("count"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.userDetails.ping();
 | 
					                self.userDetails.ping()
 | 
				
			||||||
                for (const action of self._onLoggedIn) {
 | 
					                for (const action of self._onLoggedIn) {
 | 
				
			||||||
          action(self.userDetails.data);
 | 
					                    action(self.userDetails.data)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        self._onLoggedIn = [];
 | 
					                self._onLoggedIn = []
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    );
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -290,20 +287,20 @@ export class OsmConnection {
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    method,
 | 
					                    method,
 | 
				
			||||||
                    options: {
 | 
					                    options: {
 | 
				
			||||||
            header
 | 
					                        header,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    content,
 | 
					                    content,
 | 
				
			||||||
          path: `/api/0.6/${path}`
 | 
					                    path: `/api/0.6/${path}`,
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
        function(err, response) {
 | 
					                function (err, response) {
 | 
				
			||||||
                    if (err !== null) {
 | 
					                    if (err !== null) {
 | 
				
			||||||
            error(err);
 | 
					                        error(err)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
            ok(response);
 | 
					                        ok(response)
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
      );
 | 
					            )
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async post(
 | 
					    public async post(
 | 
				
			||||||
| 
						 | 
					@ -311,7 +308,7 @@ export class OsmConnection {
 | 
				
			||||||
        content?: string,
 | 
					        content?: string,
 | 
				
			||||||
        header?: Record<string, string | number>
 | 
					        header?: Record<string, string | number>
 | 
				
			||||||
    ): Promise<any> {
 | 
					    ): Promise<any> {
 | 
				
			||||||
    return await this.interact(path, "POST", header, content);
 | 
					        return await this.interact(path, "POST", header, content)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async put(
 | 
					    public async put(
 | 
				
			||||||
| 
						 | 
					@ -319,60 +316,60 @@ export class OsmConnection {
 | 
				
			||||||
        content?: string,
 | 
					        content?: string,
 | 
				
			||||||
        header?: Record<string, string | number>
 | 
					        header?: Record<string, string | number>
 | 
				
			||||||
    ): Promise<any> {
 | 
					    ): Promise<any> {
 | 
				
			||||||
    return await this.interact(path, "PUT", header, content);
 | 
					        return await this.interact(path, "PUT", header, content)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async get(path: string, header?: Record<string, string | number>): Promise<any> {
 | 
					    public async get(path: string, header?: Record<string, string | number>): Promise<any> {
 | 
				
			||||||
    return await this.interact(path, "GET", header);
 | 
					        return await this.interact(path, "GET", header)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public closeNote(id: number | string, text?: string): Promise<void> {
 | 
					    public closeNote(id: number | string, text?: string): Promise<void> {
 | 
				
			||||||
    let textSuffix = "";
 | 
					        let textSuffix = ""
 | 
				
			||||||
        if ((text ?? "") !== "") {
 | 
					        if ((text ?? "") !== "") {
 | 
				
			||||||
      textSuffix = "?text=" + encodeURIComponent(text);
 | 
					            textSuffix = "?text=" + encodeURIComponent(text)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this._dryRun.data) {
 | 
					        if (this._dryRun.data) {
 | 
				
			||||||
      console.warn("Dryrun enabled - not actually closing note ", id, " with text ", text);
 | 
					            console.warn("Dryrun enabled - not actually closing note ", id, " with text ", text)
 | 
				
			||||||
            return new Promise((ok) => {
 | 
					            return new Promise((ok) => {
 | 
				
			||||||
        ok();
 | 
					                ok()
 | 
				
			||||||
      });
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    return this.post(`notes/${id}/close${textSuffix}`);
 | 
					        return this.post(`notes/${id}/close${textSuffix}`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public reopenNote(id: number | string, text?: string): Promise<void> {
 | 
					    public reopenNote(id: number | string, text?: string): Promise<void> {
 | 
				
			||||||
        if (this._dryRun.data) {
 | 
					        if (this._dryRun.data) {
 | 
				
			||||||
      console.warn("Dryrun enabled - not actually reopening note ", id, " with text ", text);
 | 
					            console.warn("Dryrun enabled - not actually reopening note ", id, " with text ", text)
 | 
				
			||||||
            return new Promise((ok) => {
 | 
					            return new Promise((ok) => {
 | 
				
			||||||
        ok();
 | 
					                ok()
 | 
				
			||||||
      });
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    let textSuffix = "";
 | 
					        let textSuffix = ""
 | 
				
			||||||
        if ((text ?? "") !== "") {
 | 
					        if ((text ?? "") !== "") {
 | 
				
			||||||
      textSuffix = "?text=" + encodeURIComponent(text);
 | 
					            textSuffix = "?text=" + encodeURIComponent(text)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    return this.post(`notes/${id}/reopen${textSuffix}`);
 | 
					        return this.post(`notes/${id}/reopen${textSuffix}`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async openNote(lat: number, lon: number, text: string): Promise<{ id: number }> {
 | 
					    public async openNote(lat: number, lon: number, text: string): Promise<{ id: number }> {
 | 
				
			||||||
        if (this._dryRun.data) {
 | 
					        if (this._dryRun.data) {
 | 
				
			||||||
      console.warn("Dryrun enabled - not actually opening note with text ", text);
 | 
					            console.warn("Dryrun enabled - not actually opening note with text ", text)
 | 
				
			||||||
            return new Promise<{ id: number }>((ok) => {
 | 
					            return new Promise<{ id: number }>((ok) => {
 | 
				
			||||||
                window.setTimeout(
 | 
					                window.setTimeout(
 | 
				
			||||||
                    () => ok({ id: Math.floor(Math.random() * 1000) }),
 | 
					                    () => ok({ id: Math.floor(Math.random() * 1000) }),
 | 
				
			||||||
                    Math.random() * 5000
 | 
					                    Math.random() * 5000
 | 
				
			||||||
        );
 | 
					                )
 | 
				
			||||||
      });
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // Lat and lon must be strings for the API to accept it
 | 
					        // Lat and lon must be strings for the API to accept it
 | 
				
			||||||
        const content = `lat=${lat}&lon=${lon}&text=${encodeURIComponent(text)}`
 | 
					        const content = `lat=${lat}&lon=${lon}&text=${encodeURIComponent(text)}`
 | 
				
			||||||
        const response = await this.post("notes.json", content, {
 | 
					        const response = await this.post("notes.json", content, {
 | 
				
			||||||
      "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
 | 
					            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    const parsed = JSON.parse(response);
 | 
					        const parsed = JSON.parse(response)
 | 
				
			||||||
    const id = parsed.properties;
 | 
					        const id = parsed.properties
 | 
				
			||||||
    console.log("OPENED NOTE", id);
 | 
					        console.log("OPENED NOTE", id)
 | 
				
			||||||
    return id;
 | 
					        return id
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async uploadGpxTrack(
 | 
					    public async uploadGpxTrack(
 | 
				
			||||||
| 
						 | 
					@ -390,61 +387,61 @@ export class OsmConnection {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ): Promise<{ id: number }> {
 | 
					    ): Promise<{ id: number }> {
 | 
				
			||||||
        if (this._dryRun.data) {
 | 
					        if (this._dryRun.data) {
 | 
				
			||||||
      console.warn("Dryrun enabled - not actually uploading GPX ", gpx);
 | 
					            console.warn("Dryrun enabled - not actually uploading GPX ", gpx)
 | 
				
			||||||
            return new Promise<{ id: number }>((ok, error) => {
 | 
					            return new Promise<{ id: number }>((ok, error) => {
 | 
				
			||||||
                window.setTimeout(
 | 
					                window.setTimeout(
 | 
				
			||||||
                    () => ok({ id: Math.floor(Math.random() * 1000) }),
 | 
					                    () => ok({ id: Math.floor(Math.random() * 1000) }),
 | 
				
			||||||
                    Math.random() * 5000
 | 
					                    Math.random() * 5000
 | 
				
			||||||
        );
 | 
					                )
 | 
				
			||||||
      });
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const contents = {
 | 
					        const contents = {
 | 
				
			||||||
            file: gpx,
 | 
					            file: gpx,
 | 
				
			||||||
            description: options.description ?? "",
 | 
					            description: options.description ?? "",
 | 
				
			||||||
            tags: options.labels?.join(",") ?? "",
 | 
					            tags: options.labels?.join(",") ?? "",
 | 
				
			||||||
      visibility: options.visibility
 | 
					            visibility: options.visibility,
 | 
				
			||||||
    };
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const extras = {
 | 
					        const extras = {
 | 
				
			||||||
            file:
 | 
					            file:
 | 
				
			||||||
        "; filename=\"" +
 | 
					                '; filename="' +
 | 
				
			||||||
                (options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) +
 | 
					                (options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) +
 | 
				
			||||||
        "\"\r\nContent-Type: application/gpx+xml"
 | 
					                '"\r\nContent-Type: application/gpx+xml',
 | 
				
			||||||
    };
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const boundary = "987654";
 | 
					        const boundary = "987654"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let body = "";
 | 
					        let body = ""
 | 
				
			||||||
        for (const key in contents) {
 | 
					        for (const key in contents) {
 | 
				
			||||||
      body += "--" + boundary + "\r\n";
 | 
					            body += "--" + boundary + "\r\n"
 | 
				
			||||||
      body += "Content-Disposition: form-data; name=\"" + key + "\"";
 | 
					            body += 'Content-Disposition: form-data; name="' + key + '"'
 | 
				
			||||||
            if (extras[key] !== undefined) {
 | 
					            if (extras[key] !== undefined) {
 | 
				
			||||||
        body += extras[key];
 | 
					                body += extras[key]
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
      body += "\r\n\r\n";
 | 
					            body += "\r\n\r\n"
 | 
				
			||||||
      body += contents[key] + "\r\n";
 | 
					            body += contents[key] + "\r\n"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    body += "--" + boundary + "--\r\n";
 | 
					        body += "--" + boundary + "--\r\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const response = await this.post("gpx/create", body, {
 | 
					        const response = await this.post("gpx/create", body, {
 | 
				
			||||||
            "Content-Type": "multipart/form-data; boundary=" + boundary,
 | 
					            "Content-Type": "multipart/form-data; boundary=" + boundary,
 | 
				
			||||||
      "Content-Length": body.length
 | 
					            "Content-Length": body.length,
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    const parsed = JSON.parse(response);
 | 
					        const parsed = JSON.parse(response)
 | 
				
			||||||
    console.log("Uploaded GPX track", parsed);
 | 
					        console.log("Uploaded GPX track", parsed)
 | 
				
			||||||
    return { id: parsed };
 | 
					        return { id: parsed }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public addCommentToNote(id: number | string, text: string): Promise<void> {
 | 
					    public addCommentToNote(id: number | string, text: string): Promise<void> {
 | 
				
			||||||
        if (this._dryRun.data) {
 | 
					        if (this._dryRun.data) {
 | 
				
			||||||
      console.warn("Dryrun enabled - not actually adding comment ", text, "to  note ", id);
 | 
					            console.warn("Dryrun enabled - not actually adding comment ", text, "to  note ", id)
 | 
				
			||||||
            return new Promise((ok) => {
 | 
					            return new Promise((ok) => {
 | 
				
			||||||
        ok();
 | 
					                ok()
 | 
				
			||||||
      });
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ((text ?? "") === "") {
 | 
					        if ((text ?? "") === "") {
 | 
				
			||||||
      throw "Invalid text!";
 | 
					            throw "Invalid text!"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new Promise((ok, error) => {
 | 
					        return new Promise((ok, error) => {
 | 
				
			||||||
| 
						 | 
					@ -452,50 +449,50 @@ export class OsmConnection {
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    method: "POST",
 | 
					                    method: "POST",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          path: `/api/0.6/notes/${id}/comment?text=${encodeURIComponent(text)}`
 | 
					                    path: `/api/0.6/notes/${id}/comment?text=${encodeURIComponent(text)}`,
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
        function(err, _) {
 | 
					                function (err, _) {
 | 
				
			||||||
                    if (err !== null) {
 | 
					                    if (err !== null) {
 | 
				
			||||||
            error(err);
 | 
					                        error(err)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
            ok();
 | 
					                        ok()
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
      );
 | 
					            )
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * To be called by land.html
 | 
					     * To be called by land.html
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public finishLogin(callback: (previousURL: string) => void) {
 | 
					    public finishLogin(callback: (previousURL: string) => void) {
 | 
				
			||||||
    this.auth.authenticate(function() {
 | 
					        this.auth.authenticate(function () {
 | 
				
			||||||
            // Fully authed at this point
 | 
					            // Fully authed at this point
 | 
				
			||||||
      console.log("Authentication successful!");
 | 
					            console.log("Authentication successful!")
 | 
				
			||||||
      const previousLocation = LocalStorageSource.Get("location_before_login");
 | 
					            const previousLocation = LocalStorageSource.Get("location_before_login")
 | 
				
			||||||
      callback(previousLocation.data);
 | 
					            callback(previousLocation.data)
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private updateAuthObject() {
 | 
					    private updateAuthObject() {
 | 
				
			||||||
    let pwaStandAloneMode = false;
 | 
					        let pwaStandAloneMode = false
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (Utils.runningFromConsole) {
 | 
					            if (Utils.runningFromConsole) {
 | 
				
			||||||
        pwaStandAloneMode = true;
 | 
					                pwaStandAloneMode = true
 | 
				
			||||||
            } else if (
 | 
					            } else if (
 | 
				
			||||||
                window.matchMedia("(display-mode: standalone)").matches ||
 | 
					                window.matchMedia("(display-mode: standalone)").matches ||
 | 
				
			||||||
                window.matchMedia("(display-mode: fullscreen)").matches
 | 
					                window.matchMedia("(display-mode: fullscreen)").matches
 | 
				
			||||||
            ) {
 | 
					            ) {
 | 
				
			||||||
        pwaStandAloneMode = true;
 | 
					                pwaStandAloneMode = true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            console.warn(
 | 
					            console.warn(
 | 
				
			||||||
                "Detecting standalone mode failed",
 | 
					                "Detecting standalone mode failed",
 | 
				
			||||||
                e,
 | 
					                e,
 | 
				
			||||||
                ". Assuming in browser and not worrying furhter"
 | 
					                ". Assuming in browser and not worrying furhter"
 | 
				
			||||||
      );
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    const standalone = this._iframeMode || pwaStandAloneMode || !this._singlePage;
 | 
					        const standalone = this._iframeMode || pwaStandAloneMode || !this._singlePage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway...
 | 
					        // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway...
 | 
				
			||||||
        // Same for an iframe...
 | 
					        // Same for an iframe...
 | 
				
			||||||
| 
						 | 
					@ -508,46 +505,46 @@ export class OsmConnection {
 | 
				
			||||||
                ? "https://mapcomplete.org/land.html"
 | 
					                ? "https://mapcomplete.org/land.html"
 | 
				
			||||||
                : window.location.protocol + "//" + window.location.host + "/land.html",
 | 
					                : window.location.protocol + "//" + window.location.host + "/land.html",
 | 
				
			||||||
            singlepage: !standalone,
 | 
					            singlepage: !standalone,
 | 
				
			||||||
      auto: true
 | 
					            auto: true,
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private CheckForMessagesContinuously() {
 | 
					    private CheckForMessagesContinuously() {
 | 
				
			||||||
    const self = this;
 | 
					        const self = this
 | 
				
			||||||
        if (this.isChecking) {
 | 
					        if (this.isChecking) {
 | 
				
			||||||
      return;
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    this.isChecking = true;
 | 
					        this.isChecking = true
 | 
				
			||||||
        Stores.Chronic(5 * 60 * 1000).addCallback((_) => {
 | 
					        Stores.Chronic(5 * 60 * 1000).addCallback((_) => {
 | 
				
			||||||
            if (self.isLoggedIn.data) {
 | 
					            if (self.isLoggedIn.data) {
 | 
				
			||||||
        console.log("Checking for messages");
 | 
					                console.log("Checking for messages")
 | 
				
			||||||
        self.AttemptLogin();
 | 
					                self.AttemptLogin()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private UpdateCapabilities(): void {
 | 
					    private UpdateCapabilities(): void {
 | 
				
			||||||
    const self = this;
 | 
					        const self = this
 | 
				
			||||||
        this.FetchCapabilities().then(({ api, gpx }) => {
 | 
					        this.FetchCapabilities().then(({ api, gpx }) => {
 | 
				
			||||||
      self.apiIsOnline.setData(api);
 | 
					            self.apiIsOnline.setData(api)
 | 
				
			||||||
      self.gpxServiceIsOnline.setData(gpx);
 | 
					            self.gpxServiceIsOnline.setData(gpx)
 | 
				
			||||||
    });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private async FetchCapabilities(): Promise<{ api: OsmServiceState; gpx: OsmServiceState }> {
 | 
					    private async FetchCapabilities(): Promise<{ api: OsmServiceState; gpx: OsmServiceState }> {
 | 
				
			||||||
        if (Utils.runningFromConsole) {
 | 
					        if (Utils.runningFromConsole) {
 | 
				
			||||||
      return { api: "online", gpx: "online" };
 | 
					            return { api: "online", gpx: "online" }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    const result = await Utils.downloadAdvanced(this.Backend() + "/api/0.6/capabilities");
 | 
					        const result = await Utils.downloadAdvanced(this.Backend() + "/api/0.6/capabilities")
 | 
				
			||||||
        if (result["content"] === undefined) {
 | 
					        if (result["content"] === undefined) {
 | 
				
			||||||
      console.log("Something went wrong:", result);
 | 
					            console.log("Something went wrong:", result)
 | 
				
			||||||
      return { api: "unreachable", gpx: "unreachable" };
 | 
					            return { api: "unreachable", gpx: "unreachable" }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    const xmlRaw = result["content"];
 | 
					        const xmlRaw = result["content"]
 | 
				
			||||||
    const parsed = new DOMParser().parseFromString(xmlRaw, "text/xml");
 | 
					        const parsed = new DOMParser().parseFromString(xmlRaw, "text/xml")
 | 
				
			||||||
    const statusEl = parsed.getElementsByTagName("status")[0];
 | 
					        const statusEl = parsed.getElementsByTagName("status")[0]
 | 
				
			||||||
    const api = <OsmServiceState>statusEl.getAttribute("api");
 | 
					        const api = <OsmServiceState>statusEl.getAttribute("api")
 | 
				
			||||||
    const gpx = <OsmServiceState>statusEl.getAttribute("gpx");
 | 
					        const gpx = <OsmServiceState>statusEl.getAttribute("gpx")
 | 
				
			||||||
    return { api, gpx };
 | 
					        return { api, gpx }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,44 +1,45 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
  import NextButton from "../Base/NextButton.svelte";
 | 
					  import NextButton from "../Base/NextButton.svelte"
 | 
				
			||||||
  import Geosearch from "./Geosearch.svelte";
 | 
					  import Geosearch from "./Geosearch.svelte"
 | 
				
			||||||
  import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
  import ThemeViewState from "../../Models/ThemeViewState";
 | 
					  import ThemeViewState from "../../Models/ThemeViewState"
 | 
				
			||||||
  import { Store, UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid";
 | 
					  import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
				
			||||||
  import { twJoin } from "tailwind-merge";
 | 
					  import { twJoin } from "tailwind-merge"
 | 
				
			||||||
  import { Utils } from "../../Utils";
 | 
					  import { Utils } from "../../Utils"
 | 
				
			||||||
  import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState";
 | 
					  import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * The theme introduction panel
 | 
					   * The theme introduction panel
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let state: ThemeViewState;
 | 
					  export let state: ThemeViewState
 | 
				
			||||||
  let layout = state.layout;
 | 
					  let layout = state.layout
 | 
				
			||||||
  let selectedElement = state.selectedElement;
 | 
					  let selectedElement = state.selectedElement
 | 
				
			||||||
  let selectedLayer = state.selectedLayer;
 | 
					  let selectedLayer = state.selectedLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined);
 | 
					  let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined)
 | 
				
			||||||
  let searchEnabled = false;
 | 
					  let searchEnabled = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let geopermission: Store<GeolocationPermissionState> = state.geolocation.geolocationState.permission;
 | 
					  let geopermission: Store<GeolocationPermissionState> =
 | 
				
			||||||
  let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation;
 | 
					    state.geolocation.geolocationState.permission
 | 
				
			||||||
 | 
					  let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  geopermission.addCallback(perm => console.log(">>>> Permission", perm));
 | 
					  geopermission.addCallback((perm) => console.log(">>>> Permission", perm))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function jumpToCurrentLocation() {
 | 
					  function jumpToCurrentLocation() {
 | 
				
			||||||
    const glstate = state.geolocation.geolocationState;
 | 
					    const glstate = state.geolocation.geolocationState
 | 
				
			||||||
    if (glstate.currentGPSLocation.data !== undefined) {
 | 
					    if (glstate.currentGPSLocation.data !== undefined) {
 | 
				
			||||||
      const c: GeolocationCoordinates = glstate.currentGPSLocation.data;
 | 
					      const c: GeolocationCoordinates = glstate.currentGPSLocation.data
 | 
				
			||||||
      state.guistate.themeIsOpened.setData(false);
 | 
					      state.guistate.themeIsOpened.setData(false)
 | 
				
			||||||
      const coor = { lon: c.longitude, lat: c.latitude };
 | 
					      const coor = { lon: c.longitude, lat: c.latitude }
 | 
				
			||||||
      state.mapProperties.location.setData(coor);
 | 
					      state.mapProperties.location.setData(coor)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (glstate.permission.data !== "granted") {
 | 
					    if (glstate.permission.data !== "granted") {
 | 
				
			||||||
      glstate.requestPermission();
 | 
					      glstate.requestPermission()
 | 
				
			||||||
      return;
 | 
					      return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -69,13 +70,13 @@
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
        <!-- No geolocation granted - we don't show the button -->
 | 
					        <!-- No geolocation granted - we don't show the button -->
 | 
				
			||||||
      {:else if $geopermission === "requested"}
 | 
					      {:else if $geopermission === "requested"}
 | 
				
			||||||
        <button class="flex w-full items-center gap-x-2 disabled" on:click={jumpToCurrentLocation}>
 | 
					        <button class="disabled flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}>
 | 
				
			||||||
          <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
 | 
					          <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
 | 
				
			||||||
          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
					          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
				
			||||||
          <Tr t={Translations.t.general.waitingForGeopermission} />
 | 
					          <Tr t={Translations.t.general.waitingForGeopermission} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      {:else if $geopermission === "denied"}
 | 
					      {:else if $geopermission === "denied"}
 | 
				
			||||||
        <button class="flex w-full items-center gap-x-2 disabled">
 | 
					        <button class="disabled flex w-full items-center gap-x-2">
 | 
				
			||||||
          <ToSvelte construct={Svg.location_refused_svg().SetClass("w-8 h-8")} />
 | 
					          <ToSvelte construct={Svg.location_refused_svg().SetClass("w-8 h-8")} />
 | 
				
			||||||
          <Tr t={Translations.t.general.geopermissionDenied} />
 | 
					          <Tr t={Translations.t.general.geopermissionDenied} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
| 
						 | 
					@ -84,7 +85,6 @@
 | 
				
			||||||
          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
					          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
				
			||||||
          <Tr t={Translations.t.general.waitingForLocation} />
 | 
					          <Tr t={Translations.t.general.waitingForLocation} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
 | 
					 | 
				
			||||||
      {/if}
 | 
					      {/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div class=".button low-interaction m-1 flex w-full items-center gap-x-2 rounded border p-2">
 | 
					      <div class=".button low-interaction m-1 flex w-full items-center gap-x-2 rounded border p-2">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue