trail save fix

This commit is contained in:
Christian Beutel
2025-02-14 13:22:20 +01:00
parent a2ad4a4800
commit bd8bae2ac9
43 changed files with 164 additions and 105 deletions

View File

@@ -1,37 +1,33 @@
<script lang="ts"> <script lang="ts">
import { toast } from "$lib/stores/toast_store"; import { closeToast, toastStore } from "$lib/stores/toast_store.svelte";
import { fade } from "svelte/transition"; import { fade } from "svelte/transition";
function closeToast() {
toast.set(null);
}
</script> </script>
{#if $toast} {#each toastStore.toasts as t, i}
<div <div
class="fixed px-4 py-3 shadow-xl rounded-xl border bottom-4 right-4 bg-white text-gray-500 flex items-center max-w-md" class="fixed px-4 py-3 shadow-xl rounded-xl border right-4 bg-white text-gray-500 flex items-center max-w-md"
style="z-index: 1001;" style="z-index: 1001; bottom: {16 + i * 72}px"
in:fade={{ duration: 250 }} in:fade={{ duration: 250 }}
out:fade={{ duration: 250 }} out:fade={{ duration: 250 }}
> >
<i <i
class="fa fa-{$toast.icon} p-3 mr-2 rounded-lg" class="fa fa-{t.icon} p-3 mr-2 rounded-lg"
class:success-toast={$toast.type == "success"} class:success-toast={t.type == "success"}
class:error-toast={$toast.type == "error"} class:error-toast={t.type == "error"}
></i> ></i>
<p class="mr-4"> <p class="mr-4">
{$toast.text} {t.text}
</p> </p>
<button <button
type="button" type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white ml-6" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white ml-6"
onclick={closeToast} onclick={() => closeToast(t)}
> >
<i class="fa fa-close"></i> <i class="fa fa-close"></i>
<span class="sr-only">Close modal</span> <span class="sr-only">Close modal</span>
</button> </button>
</div> </div>
{/if} {/each}
<style> <style>
.success-toast { .success-toast {

View File

@@ -5,7 +5,7 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import TextField from "../base/text_field.svelte"; import TextField from "../base/text_field.svelte";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
let modal: Modal; let modal: Modal;

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { getFileURL, readAsDataURLAsync } from "$lib/util/file_util"; import { getFileURL, readAsDataURLAsync } from "$lib/util/file_util";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import PhotoCard from "../photo_card.svelte"; import PhotoCard from "../photo_card.svelte";

View File

@@ -7,7 +7,7 @@
lists_index, lists_index,
lists_remove_trail, lists_remove_trail,
} from "$lib/stores/list_store"; } from "$lib/stores/list_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { trails_delete } from "$lib/stores/trail_store"; import { trails_delete } from "$lib/stores/trail_store";
import { trail2gpx } from "$lib/util/gpx_util"; import { trail2gpx } from "$lib/util/gpx_util";
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON"; import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";

View File

@@ -25,7 +25,7 @@
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg"; import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
import { pb } from "$lib/pocketbase"; import { pb } from "$lib/pocketbase";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import * as M from "maplibre-gl"; import * as M from "maplibre-gl";
import "photoswipe/style.css"; import "photoswipe/style.css";
import { onMount } from "svelte"; import { onMount } from "svelte";

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { User } from "$lib/models/user"; import type { User } from "$lib/models/user";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { users_search } from "$lib/stores/user_store"; import { users_search } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util"; import { getFileURL } from "$lib/util/file_util";
import Search, { type SearchItem } from "./base/search.svelte"; import Search, { type SearchItem } from "./base/search.svelte";

View File

@@ -3,7 +3,7 @@
import { WaypointCreateSchema } from "$lib/models/api/waypoint_schema"; import { WaypointCreateSchema } from "$lib/models/api/waypoint_schema";
import { convertDMSToDD } from "$lib/models/gpx/utils"; import { convertDMSToDD } from "$lib/models/gpx/utils";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { waypoint } from "$lib/stores/waypoint_store"; import { waypoint } from "$lib/stores/waypoint_store";
import { cloneDeep } from "$lib/util/deep_util"; import { cloneDeep } from "$lib/util/deep_util";
import { icons } from "$lib/util/icon_util"; import { icons } from "$lib/util/icon_util";

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Kommentar} other {Kommentare}}", "comment": "{n, plural, =1 {Kommentar} other {Kommentare}}",
"completed": "Abgeschlossen", "completed": "Abgeschlossen",
"completed-a-trail": "hat eine Route abgeschlossen", "completed-a-trail": "hat eine Route abgeschlossen",
"completed-tours": "",
"completion-status": "Abschlussstatus", "completion-status": "Abschlussstatus",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"confirm-deletion": "Löschen bestätigen", "confirm-deletion": "Löschen bestätigen",
@@ -226,6 +227,7 @@
"photos": "Fotos", "photos": "Fotos",
"pick-a-trail": "Route auswählen", "pick-a-trail": "Route auswählen",
"planned-a-trail": "hat eine Route geplant", "planned-a-trail": "hat eine Route geplant",
"planned-tours": "",
"polish": "Polnisch", "polish": "Polnisch",
"portuguese": "Portugiesisch", "portuguese": "Portugiesisch",
"print": "Drucken", "print": "Drucken",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Comment} other {Comments}}", "comment": "{n, plural, =1 {Comment} other {Comments}}",
"completed": "Completed", "completed": "Completed",
"completed-a-trail": "completed a trail", "completed-a-trail": "completed a trail",
"completed-tours": "Completed tours",
"completion-status": "Completion Status", "completion-status": "Completion Status",
"confirm": "Confirm", "confirm": "Confirm",
"confirm-deletion": "Confirm Deletion", "confirm-deletion": "Confirm Deletion",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Invalid Date", "invalid-date": "Invalid Date",
"invalid-username": "Invalid username", "invalid-username": "Invalid username",
"italian": "Italian", "italian": "Italian",
@@ -226,6 +227,7 @@
"photos": "Photos", "photos": "Photos",
"pick-a-trail": "Pick a trail", "pick-a-trail": "Pick a trail",
"planned-a-trail": "planned a trail", "planned-a-trail": "planned a trail",
"planned-tours": "Planned tours",
"polish": "Polish", "polish": "Polish",
"portuguese": "Portuguese", "portuguese": "Portuguese",
"print": "Print", "print": "Print",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, one {}=1 {Comentario} other {Comentarios}}", "comment": "{n, plural, one {}=1 {Comentario} other {Comentarios}}",
"completed": "Completado", "completed": "Completado",
"completed-a-trail": "ruta completada", "completed-a-trail": "ruta completada",
"completed-tours": "",
"completion-status": "Estado de avance", "completion-status": "Estado de avance",
"confirm": "Confirmar", "confirm": "Confirmar",
"confirm-deletion": "Confirmar Borrado", "confirm-deletion": "Confirmar Borrado",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Fecha no válida", "invalid-date": "Fecha no válida",
"invalid-username": "Usuario no válido", "invalid-username": "Usuario no válido",
"italian": "Italiano", "italian": "Italiano",
@@ -226,6 +227,7 @@
"photos": "Fotos", "photos": "Fotos",
"pick-a-trail": "Escoge una ruta", "pick-a-trail": "Escoge una ruta",
"planned-a-trail": "planificada una ruta", "planned-a-trail": "planificada una ruta",
"planned-tours": "",
"polish": "Polaco", "polish": "Polaco",
"portuguese": "Portugués", "portuguese": "Portugués",
"print": "Imprimir", "print": "Imprimir",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Commentaire} other {Commentaires}}", "comment": "{n, plural, =1 {Commentaire} other {Commentaires}}",
"completed": "Terminé", "completed": "Terminé",
"completed-a-trail": "a terminé un parcours", "completed-a-trail": "a terminé un parcours",
"completed-tours": "",
"completion-status": "Statut", "completion-status": "Statut",
"confirm": "Confirmer", "confirm": "Confirmer",
"confirm-deletion": "Confirmer la suppression", "confirm-deletion": "Confirmer la suppression",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Date invalide", "invalid-date": "Date invalide",
"invalid-username": "Nom d'utilisateur invalide", "invalid-username": "Nom d'utilisateur invalide",
"italian": "Italien", "italian": "Italien",
@@ -226,6 +227,7 @@
"photos": "Photos", "photos": "Photos",
"pick-a-trail": "Choisir un itinéraire", "pick-a-trail": "Choisir un itinéraire",
"planned-a-trail": "a plannifié un itinéraire", "planned-a-trail": "a plannifié un itinéraire",
"planned-tours": "",
"polish": "polonais", "polish": "polonais",
"portuguese": "Portugais", "portuguese": "Portugais",
"print": "Imprimer", "print": "Imprimer",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Megjegyzés} other {Megjegyzés}}", "comment": "{n, plural, =1 {Megjegyzés} other {Megjegyzés}}",
"completed": "Teljesítve", "completed": "Teljesítve",
"completed-a-trail": "completed a trail", "completed-a-trail": "completed a trail",
"completed-tours": "",
"completion-status": "Befejezés állapota", "completion-status": "Befejezés állapota",
"confirm": "Confirm", "confirm": "Confirm",
"confirm-deletion": "Confirm Deletion", "confirm-deletion": "Confirm Deletion",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Érvénytelen dátum", "invalid-date": "Érvénytelen dátum",
"invalid-username": "Érvénytelen felhasználó", "invalid-username": "Érvénytelen felhasználó",
"italian": "Olasz", "italian": "Olasz",
@@ -226,6 +227,7 @@
"photos": "Képek", "photos": "Képek",
"pick-a-trail": "Válasszon útvonalat", "pick-a-trail": "Válasszon útvonalat",
"planned-a-trail": "planned a trail", "planned-a-trail": "planned a trail",
"planned-tours": "",
"polish": "Lengyel", "polish": "Lengyel",
"portuguese": "Portugál", "portuguese": "Portugál",
"print": "Print", "print": "Print",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Commento} other {Commenti}}", "comment": "{n, plural, =1 {Commento} other {Commenti}}",
"completed": "Completato", "completed": "Completato",
"completed-a-trail": "percorso completato", "completed-a-trail": "percorso completato",
"completed-tours": "",
"completion-status": "Stato di completamento", "completion-status": "Stato di completamento",
"confirm": "Confermare", "confirm": "Confermare",
"confirm-deletion": "Conferma eliminazione", "confirm-deletion": "Conferma eliminazione",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Data non valida", "invalid-date": "Data non valida",
"invalid-username": "Nome utente non valido", "invalid-username": "Nome utente non valido",
"italian": "Italiano", "italian": "Italiano",
@@ -226,6 +227,7 @@
"photos": "Foto", "photos": "Foto",
"pick-a-trail": "Scegli un percorso", "pick-a-trail": "Scegli un percorso",
"planned-a-trail": "percorso pianificato", "planned-a-trail": "percorso pianificato",
"planned-tours": "",
"polish": "Polacco", "polish": "Polacco",
"portuguese": "Portoghese", "portuguese": "Portoghese",
"print": "Stampa", "print": "Stampa",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Opmerking} other {Opmerkingen}}", "comment": "{n, plural, =1 {Opmerking} other {Opmerkingen}}",
"completed": "Voltooid", "completed": "Voltooid",
"completed-a-trail": "completed a trail", "completed-a-trail": "completed a trail",
"completed-tours": "",
"completion-status": "Voltooiingsstatus", "completion-status": "Voltooiingsstatus",
"confirm": "Confirm", "confirm": "Confirm",
"confirm-deletion": "Confirm Deletion", "confirm-deletion": "Confirm Deletion",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Ongeldige datum", "invalid-date": "Ongeldige datum",
"invalid-username": "Ongeldige gebruikersnaam", "invalid-username": "Ongeldige gebruikersnaam",
"italian": "Italiaans", "italian": "Italiaans",
@@ -226,6 +227,7 @@
"photos": "Foto's", "photos": "Foto's",
"pick-a-trail": "Kies een wandelroute", "pick-a-trail": "Kies een wandelroute",
"planned-a-trail": "planned a trail", "planned-a-trail": "planned a trail",
"planned-tours": "",
"polish": "Pools", "polish": "Pools",
"portuguese": "Portugees", "portuguese": "Portugees",
"print": "Afdrukken", "print": "Afdrukken",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Komentarz} other {Komentarze}}", "comment": "{n, plural, =1 {Komentarz} other {Komentarze}}",
"completed": "Zakończono", "completed": "Zakończono",
"completed-a-trail": "ukończono szlak", "completed-a-trail": "ukończono szlak",
"completed-tours": "",
"completion-status": "Stan ukończenia", "completion-status": "Stan ukończenia",
"confirm": "Potwierdź", "confirm": "Potwierdź",
"confirm-deletion": "Potwierdź usunięcie", "confirm-deletion": "Potwierdź usunięcie",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Nieprawidłowa data", "invalid-date": "Nieprawidłowa data",
"invalid-username": "Błędna nazwa użytkownika", "invalid-username": "Błędna nazwa użytkownika",
"italian": "Włoski", "italian": "Włoski",
@@ -226,6 +227,7 @@
"photos": "Zdjęcia", "photos": "Zdjęcia",
"pick-a-trail": "Wybierz szlak", "pick-a-trail": "Wybierz szlak",
"planned-a-trail": "zaplanowano szlak", "planned-a-trail": "zaplanowano szlak",
"planned-tours": "",
"polish": "Polski", "polish": "Polski",
"portuguese": "Portugalski", "portuguese": "Portugalski",
"print": "Drukuj", "print": "Drukuj",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {Comentário} other {Comentários}}", "comment": "{n, plural, =1 {Comentário} other {Comentários}}",
"completed": "Completada", "completed": "Completada",
"completed-a-trail": "completed a trail", "completed-a-trail": "completed a trail",
"completed-tours": "",
"completion-status": "Estado de conclusão", "completion-status": "Estado de conclusão",
"confirm": "Confirmar", "confirm": "Confirmar",
"confirm-deletion": "Confirmar eliminação", "confirm-deletion": "Confirmar eliminação",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "Data inválida", "invalid-date": "Data inválida",
"invalid-username": "Nome de usuário inválido", "invalid-username": "Nome de usuário inválido",
"italian": "Italiano", "italian": "Italiano",
@@ -226,6 +227,7 @@
"photos": "Fotos", "photos": "Fotos",
"pick-a-trail": "Escolha uma trilha", "pick-a-trail": "Escolha uma trilha",
"planned-a-trail": "planned a trail", "planned-a-trail": "planned a trail",
"planned-tours": "",
"polish": "Polonês", "polish": "Polonês",
"portuguese": "Português", "portuguese": "Português",
"print": "Imprimir", "print": "Imprimir",

View File

@@ -43,6 +43,7 @@
"comment": "{n, plural, =1 {评论} other {评论}}", "comment": "{n, plural, =1 {评论} other {评论}}",
"completed": "已完成", "completed": "已完成",
"completed-a-trail": "completed a trail", "completed-a-trail": "completed a trail",
"completed-tours": "",
"completion-status": "完成状态", "completion-status": "完成状态",
"confirm": "确认", "confirm": "确认",
"confirm-deletion": "确认删除", "confirm-deletion": "确认删除",
@@ -148,8 +149,8 @@
"integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.", "integration-description-komoot": "Syncs your komoot tours with wanderer in regular intervals.",
"integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.", "integration-description-strava": "Syncs your strava routes & activities with wanderer in regular intervals.",
"integration-disabled": "integration disabled", "integration-disabled": "integration disabled",
"integrations": "Integrations",
"integration-enabled": "integration enabled", "integration-enabled": "integration enabled",
"integrations": "Integrations",
"invalid-date": "无效日期", "invalid-date": "无效日期",
"invalid-username": "无效用户名", "invalid-username": "无效用户名",
"italian": "意大利语", "italian": "意大利语",
@@ -226,6 +227,7 @@
"photos": "图片", "photos": "图片",
"pick-a-trail": "选择一个路线", "pick-a-trail": "选择一个路线",
"planned-a-trail": "planned a trail", "planned-a-trail": "planned a trail",
"planned-tours": "",
"polish": "波兰语", "polish": "波兰语",
"portuguese": "葡萄牙语", "portuguese": "葡萄牙语",
"print": "打印", "print": "打印",

View File

@@ -12,7 +12,9 @@ const StravaSchema = z.object({
const KomootSchema = z.object({ const KomootSchema = z.object({
email: z.string().email(), email: z.string().email(),
password: z.string(), password: z.string(),
active: z.boolean() completed: z.boolean(),
planned: z.boolean(),
active: z.boolean(),
}) })
const IntegrationCreateSchema = z.object({ const IntegrationCreateSchema = z.object({

View File

@@ -16,6 +16,8 @@ export interface StravaIntegration extends BaseIntegration {
export interface KomootIntegration extends BaseIntegration { export interface KomootIntegration extends BaseIntegration {
email: string, email: string,
password: string, password: string,
completed: boolean,
planned: boolean
} }

View File

@@ -150,7 +150,6 @@ export async function searchLocationReverse(lat: number, lon: number) {
function getLocationDescription(address: Address) { function getLocationDescription(address: Address) {
let description = "" let description = ""
console.log(address);
if (address.country) { if (address.country) {
description += address.country; description += address.country;

View File

@@ -0,0 +1,31 @@
import cryptoRandomString from "crypto-random-string";
export type Toast = {
id?: string;
type: "info" | "success" | "warning" | "error"
icon: string;
text: string;
}
class ToastStore {
toasts: Toast[] = $state([]);
}
export const toastStore = new ToastStore()
export function show_toast(newToast: Toast, duration: number = 3000) {
newToast.id = cryptoRandomString({ length: 15 })
toastStore.toasts.push(newToast);
setTimeout(() => {
closeToast(newToast)
}, duration);
}
export function closeToast(toast: Toast) {
const toastIndex = toastStore.toasts.findIndex(t => t.id == toast.id)
console.log(toastIndex);
toastStore.toasts.splice(toastIndex, 1)
}

View File

@@ -1,17 +0,0 @@
import { writable, type Writable } from "svelte/store";
export type Toast = {
type: "info" | "success" | "warning" | "error"
icon: string;
text: string;
}
export const toast: Writable<Toast | null> = writable();
export function show_toast(newToast: Toast, duration: number = 3000) {
toast.set(newToast);
setTimeout(() => toast.set(null), duration);
}

View File

@@ -304,7 +304,10 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
throw new APIError(r.status, response.message, response.detail) throw new APIError(r.status, response.message, response.detail)
} }
const response: Trail = await r.json();
model.photos = response.photos
model.gpx = response.gpx
trail.set(model); trail.set(model);

View File

@@ -35,7 +35,7 @@ export async function gpx2trail(gpxString: string, fallbackName?: string) {
wp.id = cryptoRandomString({ length: 15 }); wp.id = cryptoRandomString({ length: 15 });
wp.name = wpt.name ?? "" wp.name = wpt.name ?? ""
wp.description = wpt.desc; wp.description = wpt.desc;
trail.expand!.waypoints.push(wp); trail.expand!.waypoints?.push(wp);
} }
const totals = gpx.features const totals = gpx.features
@@ -158,7 +158,7 @@ export async function fromFIT(fitData: ArrayBuffer) {
return new Promise<string>((resolve, reject) => easyFit.parse(fitData, function (error, data) { return new Promise<string>((resolve, reject) => easyFit.parse(fitData, function (error, data) {
if (error) { if (error) {
console.log(error); console.error(error);
reject(error) reject(error)
} }

View File

@@ -73,8 +73,6 @@ export class ElevationProfileControl implements IControl {
} }
toggleTheme(options: ElevationProfileControlOptions) { toggleTheme(options: ElevationProfileControlOptions) {
console.log(options);
this.settings = { ...this.settings, ...options }; this.settings = { ...this.settings, ...options };
this.elevationProfileChart?.toggleTheme(this.settings) this.elevationProfileChart?.toggleTheme(this.settings)
} }

View File

@@ -0,0 +1,14 @@
import { pb } from "$lib/pocketbase";
import { handleError } from "$lib/util/api_util";
import { json } from "@sveltejs/kit";
export async function GET() {
try {
const r = await pb.send("/integration/komoot/login", {
method: "GET",
});
return json(r);
} catch (e: any) {
throw handleError(e)
}
}

View File

@@ -7,7 +7,7 @@ export async function POST(event: RequestEvent) {
const r = await event.locals.ms.index(event.params.index as string).search(data.q, data.options); const r = await event.locals.ms.index(event.params.index as string).search(data.q, data.options);
return json(r); return json(r);
} catch (e: any) { } catch (e: any) {
console.log(e); console.error(e);
throw error(e.httpStatus, e) throw error(e.httpStatus, e)
} }

View File

@@ -16,17 +16,7 @@ export async function GET(event: RequestEvent) {
} }
// remove time from dates // remove time from dates
r.date = r.date?.substring(0, 10) ?? "" await enrichRecord(r);
for (const log of r.expand?.summit_logs ?? []) {
log.date = log.date.substring(0, 10)
if (!log.expand) {
log.expand = {} as any
}
if (log.author) {
log.expand!.author = await pb.collection("users_anonymous").getOne(log.author);
}
}
// sort waypoints by distance // sort waypoints by distance
r.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0)) r.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0))
@@ -36,10 +26,10 @@ export async function GET(event: RequestEvent) {
} }
} }
export async function POST(event: RequestEvent) { export async function POST(event: RequestEvent) {
try { try {
const r = await update<Trail>(event, TrailUpdateSchema, Collection.trails) const r = await update<Trail>(event, TrailUpdateSchema, Collection.trails)
await enrichRecord(r)
return json(r); return json(r);
} catch (e: any) { } catch (e: any) {
throw handleError(e) throw handleError(e)
@@ -54,3 +44,19 @@ export async function DELETE(event: RequestEvent) {
throw handleError(e) throw handleError(e)
} }
} }
async function enrichRecord(r: Trail) {
r.date = r.date?.substring(0, 10) ?? "";
for (const log of r.expand?.summit_logs ?? []) {
log.date = log.date.substring(0, 10);
if (!log.expand) {
log.expand = {} as any;
}
if (log.author) {
log.expand!.author = await pb.collection("users_anonymous").getOne(log.author);
}
}
}

View File

@@ -50,7 +50,7 @@ export async function PUT(event: RequestEvent) {
const fileName = (data.get("name") as string | null)?.length ? data.get("name") as string : "file" const fileName = (data.get("name") as string | null)?.length ? data.get("name") as string : "file"
log._gpx = new File([gpxFile], fileName); log._gpx = new File([gpxFile], fileName);
trail.expand!.summit_logs.push(log); trail.expand!.summit_logs?.push(log);
try { try {

View File

@@ -6,7 +6,7 @@
import LogoTextTwoLineDark from "$lib/components/logo/logo_text_two_line_dark.svelte"; import LogoTextTwoLineDark from "$lib/components/logo/logo_text_two_line_dark.svelte";
import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte"; import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { users_confirm_reset } from "$lib/stores/user_store"; import { users_confirm_reset } from "$lib/stores/user_store";
import { validator } from "@felte/validator-zod"; import { validator } from "@felte/validator-zod";
import { createForm } from "felte"; import { createForm } from "felte";

View File

@@ -5,7 +5,7 @@
import LogoTextTwoLineDark from "$lib/components/logo/logo_text_two_line_dark.svelte"; import LogoTextTwoLineDark from "$lib/components/logo/logo_text_two_line_dark.svelte";
import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte"; import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { users_reset_password } from "$lib/stores/user_store"; import { users_reset_password } from "$lib/stores/user_store";
import { validator } from "@felte/validator-zod"; import { validator } from "@felte/validator-zod";
import { createForm } from "felte"; import { createForm } from "felte";

View File

@@ -21,7 +21,7 @@
import { TrailShare } from "$lib/models/trail_share.js"; import { TrailShare } from "$lib/models/trail_share.js";
import { lists_create, lists_update } from "$lib/stores/list_store.js"; import { lists_create, lists_update } from "$lib/stores/list_store.js";
import { theme } from "$lib/stores/theme_store.js"; import { theme } from "$lib/stores/theme_store.js";
import { show_toast } from "$lib/stores/toast_store.js"; import { show_toast } from "$lib/stores/toast_store.svelte.js";
import { import {
trail_share_create, trail_share_create,
trail_share_index, trail_share_index,

View File

@@ -7,7 +7,7 @@
import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte"; import LogoTextTwoLineLight from "$lib/components/logo/logo_text_two_line_light.svelte";
import type { User } from "$lib/models/user"; import type { User } from "$lib/models/user";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { login } from "$lib/stores/user_store"; import { login } from "$lib/stores/user_store";
import { APIError } from "$lib/util/api_util"; import { APIError } from "$lib/util/api_util";
import { validator } from "@felte/validator-zod"; import { validator } from "@felte/validator-zod";

View File

@@ -8,7 +8,7 @@
import LogoText from "$lib/components/logo/logo_text.svelte"; import LogoText from "$lib/components/logo/logo_text.svelte";
import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte"; import MapWithElevationMaplibre from "$lib/components/trail/map_with_elevation_maplibre.svelte";
import type { Settings } from "$lib/models/settings"; import type { Settings } from "$lib/models/settings";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { trail } from "$lib/stores/trail_store"; import { trail } from "$lib/stores/trail_store";
import { import {
formatDistance, formatDistance,

View File

@@ -11,7 +11,7 @@ export const load: Load = async ({ params, fetch }) => {
message: e.status == 404 ? 'Not found' : e.message message: e.status == 404 ? 'Not found' : e.message
}); });
} }
console.log(e); console.error(e);
} }
}; };

View File

@@ -9,7 +9,7 @@
import type { User } from "$lib/models/user"; import type { User } from "$lib/models/user";
import { settings_update } from "$lib/stores/settings_store"; import { settings_update } from "$lib/stores/settings_store";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { login, users_create } from "$lib/stores/user_store"; import { login, users_create } from "$lib/stores/user_store";
import { validator } from "@felte/validator-zod"; import { validator } from "@felte/validator-zod";
import { createForm } from "felte"; import { createForm } from "felte";

View File

@@ -4,7 +4,7 @@
import ConfirmModal from "$lib/components/confirm_modal.svelte"; import ConfirmModal from "$lib/components/confirm_modal.svelte";
import EmailModal from "$lib/components/settings/email_modal.svelte"; import EmailModal from "$lib/components/settings/email_modal.svelte";
import PasswordModal from "$lib/components/settings/password_modal.svelte"; import PasswordModal from "$lib/components/settings/password_modal.svelte";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { import {
currentUser, currentUser,
logout, logout,

View File

@@ -5,7 +5,7 @@
import { } from "$lib/components/settings/upload_dialog.svelte"; import { } from "$lib/components/settings/upload_dialog.svelte";
import TrailExportModal from "$lib/components/trail/trail_export_modal.svelte"; import TrailExportModal from "$lib/components/trail/trail_export_modal.svelte";
import { theme } from "$lib/stores/theme_store"; import { theme } from "$lib/stores/theme_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte";
import { fetchGPX, trails_index, trails_upload } from "$lib/stores/trail_store"; import { fetchGPX, trails_index, trails_upload } from "$lib/stores/trail_store";
import { processUploadQueue, uploadStore, type Upload } from "$lib/stores/upload_store.svelte"; import { processUploadQueue, uploadStore, type Upload } from "$lib/stores/upload_store.svelte";
import { getFileURL, saveAs } from "$lib/util/file_util"; import { getFileURL, saveAs } from "$lib/util/file_util";

View File

@@ -14,7 +14,7 @@
integrations_create, integrations_create,
integrations_update, integrations_update,
} from "$lib/stores/integration_store.js"; } from "$lib/stores/integration_store.js";
import { show_toast } from "$lib/stores/toast_store.js"; import { show_toast } from "$lib/stores/toast_store.svelte.js";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
let { data } = $props(); let { data } = $props();
@@ -102,9 +102,7 @@
} }
show_toast({ show_toast({
text: text: "strava " + $_("integration-disabled"),
"strava " +
$_("integration-disabled"),
icon: "check", icon: "check",
type: "success", type: "success",
}); });
@@ -117,9 +115,13 @@
} }
if (value) { if (value) {
try { try {
await pb.send("/integration/komoot/login", { const r = await fetch("/api/v1/integration/komoot/login", {
method: "GET", method: "GET",
}); });
if (!r.ok) {
throw Error();
}
} catch (e) { } catch (e) {
komootToggleValue = false; komootToggleValue = false;
show_toast({ show_toast({
@@ -127,6 +129,7 @@
icon: "close", icon: "close",
type: "error", type: "error",
}); });
return;
} }
integration.komoot.active = true; integration.komoot.active = true;
} else { } else {
@@ -140,6 +143,7 @@
icon: "close", icon: "close",
type: "error", type: "error",
}); });
return;
} }
show_toast({ show_toast({

View File

@@ -6,7 +6,7 @@
import Textarea from "$lib/components/base/textarea.svelte"; import Textarea from "$lib/components/base/textarea.svelte";
import type { Category } from "$lib/models/category.js"; import type { Category } from "$lib/models/category.js";
import { settings_update } from "$lib/stores/settings_store"; import { settings_update } from "$lib/stores/settings_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte.js";
import { currentUser, users_update } from "$lib/stores/user_store"; import { currentUser, users_update } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util"; import { getFileURL } from "$lib/util/file_util";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";

View File

@@ -28,7 +28,7 @@
lists_remove_trail, lists_remove_trail,
} from "$lib/stores/list_store"; } from "$lib/stores/list_store";
import { summitLog } from "$lib/stores/summit_log_store"; import { summitLog } from "$lib/stores/summit_log_store";
import { show_toast } from "$lib/stores/toast_store"; import { show_toast } from "$lib/stores/toast_store.svelte.js";
import { import {
trail, trail,
trails_create, trails_create,
@@ -106,12 +106,12 @@
expand: z expand: z
.object({ .object({
gpx_data: z.string().optional(), gpx_data: z.string().optional(),
summit_logs: z.array(SummitLogCreateSchema), summit_logs: z.array(SummitLogCreateSchema).optional(),
waypoints: z.array( waypoints: z.array(
WaypointCreateSchema.extend({ WaypointCreateSchema.extend({
marker: z.any().optional(), marker: z.any().optional(),
}), }),
), ).optional(),
}) })
.optional(), .optional(),
}); });
@@ -188,12 +188,13 @@
); );
form.id = createdTrail.id; form.id = createdTrail.id;
} else { } else {
await trails_update( const updatedTrail = await trails_update(
$trail, $trail,
form as Trail, form as Trail,
photoFiles, photoFiles,
gpxFile, gpxFile,
); );
setFields(updatedTrail)
} }
listAddEnabled = true; listAddEnabled = true;
@@ -294,7 +295,7 @@
type: selectedFile.type, type: selectedFile.type,
}); });
$formData.expand!.summit_logs.push(log); $formData.expand!.summit_logs?.push(log);
if (parseResult.gpx.rte?.length && !parseResult.gpx.trk) { if (parseResult.gpx.rte?.length && !parseResult.gpx.trk) {
parseResult.gpx.trk = [ parseResult.gpx.trk = [
@@ -328,7 +329,7 @@
} }
function clearWaypoints() { function clearWaypoints() {
for (const waypoint of $formData.expand!.waypoints) { for (const waypoint of $formData.expand!.waypoints ?? []) {
waypoint.marker?.remove(); waypoint.marker?.remove();
} }
$formData.expand!.waypoints = []; $formData.expand!.waypoints = [];
@@ -395,23 +396,23 @@
} }
function deleteWaypoint(index: number) { function deleteWaypoint(index: number) {
$formData.expand!.waypoints.splice(index, 1); $formData.expand!.waypoints?.splice(index, 1);
$formData.waypoints.splice(index, 1); $formData.waypoints.splice(index, 1);
$formData.expand!.waypoints = $formData.expand!.waypoints; $formData.expand!.waypoints = $formData.expand!.waypoints;
// updateTrailOnMap(); // updateTrailOnMap();
} }
function saveWaypoint(savedWaypoint: Waypoint) { function saveWaypoint(savedWaypoint: Waypoint) {
let editedWaypointIndex = $formData.expand!.waypoints.findIndex( let editedWaypointIndex = $formData.expand!.waypoints?.findIndex(
(s) => s.id == savedWaypoint.id, (s) => s.id == savedWaypoint.id,
); ) ?? -1;
if (editedWaypointIndex >= 0) { if (editedWaypointIndex >= 0) {
$formData.expand!.waypoints[editedWaypointIndex] = savedWaypoint; $formData.expand!.waypoints![editedWaypointIndex] = savedWaypoint;
} else { } else {
savedWaypoint.id = cryptoRandomString({ length: 15 }); savedWaypoint.id = cryptoRandomString({ length: 15 });
$formData.expand!.waypoints = [ $formData.expand!.waypoints = [
...$formData.expand!.waypoints, ...$formData.expand!.waypoints ?? [],
savedWaypoint, savedWaypoint,
]; ];
@@ -421,17 +422,17 @@
function moveMarker(marker: M.Marker, wpId?: string) { function moveMarker(marker: M.Marker, wpId?: string) {
const position = marker.getLngLat(); const position = marker.getLngLat();
const editableWaypointIndex = $formData.expand!.waypoints.findIndex( const editableWaypointIndex = $formData.expand!.waypoints?.findIndex(
(w) => w.id == wpId, (w) => w.id == wpId,
); ) ?? -1;
const editableWaypoint = const editableWaypoint =
$formData.expand!.waypoints[editableWaypointIndex]; $formData.expand!.waypoints![editableWaypointIndex];
if (!editableWaypoint) { if (!editableWaypoint) {
return; return;
} }
editableWaypoint.lat = position.lat; editableWaypoint.lat = position.lat;
editableWaypoint.lon = position.lng; editableWaypoint.lon = position.lng;
$formData.expand!.waypoints = [...$formData.expand!.waypoints]; $formData.expand!.waypoints = [...$formData.expand!.waypoints ?? []];
// updateTrailOnMap(); // updateTrailOnMap();
} }
@@ -441,16 +442,16 @@
} }
function saveSummitLog(log: SummitLog) { function saveSummitLog(log: SummitLog) {
let editedSummitLogIndex = $formData.expand!.summit_logs.findIndex( let editedSummitLogIndex = $formData.expand!.summit_logs?.findIndex(
(s) => s.id == log.id, (s) => s.id == log.id,
); );
if (editedSummitLogIndex >= 0) { if (editedSummitLogIndex ?? 0 >= 0) {
$formData.expand!.summit_logs[editedSummitLogIndex] = log; $formData.expand!.summit_logs![editedSummitLogIndex!] = log;
} else { } else {
log.id = cryptoRandomString({ length: 15 }); log.id = cryptoRandomString({ length: 15 });
$formData.expand!.summit_logs = [ $formData.expand!.summit_logs = [
...$formData.expand!.summit_logs, ...$formData.expand!.summit_logs ?? [],
log, log,
]; ];
} }
@@ -465,7 +466,7 @@
summitLog.set(currentSummitLog); summitLog.set(currentSummitLog);
summitLogModal.openModal(); summitLogModal.openModal();
} else if (item.value === "delete") { } else if (item.value === "delete") {
$formData.expand!.summit_logs.splice(index, 1); $formData.expand!.summit_logs?.splice(index, 1);
$formData.summit_logs.splice(index, 1); $formData.summit_logs.splice(index, 1);
$formData.expand!.summit_logs = $formData.expand!.summit_logs; $formData.expand!.summit_logs = $formData.expand!.summit_logs;
} }

View File

@@ -13,7 +13,7 @@ export const load: Load = async ({ params, fetch }) => {
message: e.status == 404 ? 'Not found' : e.message message: e.status == 404 ? 'Not found' : e.message
}); });
} }
console.log(e); console.error(e);
} }
}; };

View File

@@ -16,7 +16,7 @@ setup('create user', async ({ page }) => {
} catch (e) { } catch (e) {
if (e instanceof Error && e.message.includes("No resource with given identifier found")) { if (e instanceof Error && e.message.includes("No resource with given identifier found")) {
console.log("Already logged in!") console.error("Already logged in!")
} else { } else {
throw e throw e
} }