diff --git a/web/src/lib/components/base/multi_select.svelte b/web/src/lib/components/base/multi_select.svelte index 2adffb93..19ab5e69 100644 --- a/web/src/lib/components/base/multi_select.svelte +++ b/web/src/lib/components/base/multi_select.svelte @@ -39,7 +39,7 @@ {/if} diff --git a/web/src/lib/components/user_search.svelte b/web/src/lib/components/user_search.svelte new file mode 100644 index 00000000..2e052073 --- /dev/null +++ b/web/src/lib/components/user_search.svelte @@ -0,0 +1,67 @@ + + + updateUsers(e.detail)} + on:click={(e) => onClick(e)} + placeholder={`${$_("username")}...`} + items={searchItems} + {clearAfterSelect} + {label} + bind:value +> + avatar + diff --git a/web/src/lib/i18n/locales/de.json b/web/src/lib/i18n/locales/de.json index 88eebc09..36c22729 100644 --- a/web/src/lib/i18n/locales/de.json +++ b/web/src/lib/i18n/locales/de.json @@ -18,10 +18,12 @@ "already-account": "Du hast bereits ein Konto?", "altitude": "Höhe", "api-documentation": "API Dokumentation", + "author": "", "avatar": "Avatar", "average-speed": "Durchschn. Geschwindigkeit", "basic-info": "Basisinformation", "before": "Vor", + "by": "", "can": "kann", "cancel": "Abbrechen", "card": "{n, plural, =1 {Karte} other {Karten}}", @@ -93,6 +95,7 @@ "file-format": "Dateiformat", "file-too-big": "", "filter-categories": "Kategorien filtern", + "filter-difficulty": "", "focus-map-on": "Karte fokussieren auf", "french": "Französisch", "german": "Deutsch", @@ -182,6 +185,7 @@ "share": "Teilen", "share-this-list": "Diese Liste teilen", "share-this-trail": "Diese Route teilen", + "shared": "", "shared-by": "Geteilt von", "shared-with": "Geteilt mit", "show-in-overview": "In der Übersicht anzeigen", diff --git a/web/src/lib/i18n/locales/en.json b/web/src/lib/i18n/locales/en.json index bc8e28d1..260a040a 100644 --- a/web/src/lib/i18n/locales/en.json +++ b/web/src/lib/i18n/locales/en.json @@ -18,10 +18,12 @@ "already-account": "Already have an account?", "altitude": "Altitude", "api-documentation": "API Documentation", + "author": "Author", "avatar": "Avatar", "average-speed": "Avg. Speed", "basic-info": "Basic Info", "before": "Before", + "by": "by", "can": "can", "cancel": "Cancel", "card": "{n, plural, =1 {Card} other {Cards}}", @@ -93,6 +95,7 @@ "file-format": "File format", "file-too-big": "File {file} is too big (max. {size})", "filter-categories": "Filter categories", + "filter-difficulty": "Filter difficulty", "focus-map-on": "Focus map on", "french": "French", "german": "German", @@ -182,6 +185,7 @@ "share": "Share", "share-this-list": "Share this list", "share-this-trail": "Share this trail", + "shared": "Shared", "shared-by": "Shared by", "shared-with": "Shared with", "show-in-overview": "Show in overview", diff --git a/web/src/lib/i18n/locales/fr.json b/web/src/lib/i18n/locales/fr.json index 70653fa0..cc7733cb 100644 --- a/web/src/lib/i18n/locales/fr.json +++ b/web/src/lib/i18n/locales/fr.json @@ -18,10 +18,12 @@ "already-account": "Déjà un compte ?", "altitude": "Altitude", "api-documentation": "Documentation API", + "author": "", "avatar": "Avatar", "average-speed": "", "basic-info": "Informations de base", "before": "", + "by": "", "can": "", "cancel": "Annuler", "card": "{n, plural, =1 {Carte} other {Cartes}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Français", "german": "Allemand", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "Voir dans l'aperçu", diff --git a/web/src/lib/i18n/locales/hu.json b/web/src/lib/i18n/locales/hu.json index c4a038b9..9ee0898a 100644 --- a/web/src/lib/i18n/locales/hu.json +++ b/web/src/lib/i18n/locales/hu.json @@ -18,10 +18,12 @@ "already-account": "Már rendelkezik fiókkal?", "altitude": "Magasság", "api-documentation": "API Dokumentáció", + "author": "", "avatar": "Avatar", "average-speed": "", "basic-info": "Alap információk", "before": "", + "by": "", "can": "", "cancel": "Mégsem", "card": "{n, plural, =1 {Kártya} other {Kártyák}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Francia", "german": "Német", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "Áttekintés", diff --git a/web/src/lib/i18n/locales/it.json b/web/src/lib/i18n/locales/it.json index 7e036762..543bcbfe 100644 --- a/web/src/lib/i18n/locales/it.json +++ b/web/src/lib/i18n/locales/it.json @@ -18,10 +18,12 @@ "already-account": "Hai già un account?", "altitude": "Altitudine", "api-documentation": "Documentazione API", + "author": "", "avatar": "Avatar", "average-speed": "", "basic-info": "Informazioni di base", "before": "", + "by": "", "can": "può", "cancel": "Annulla", "card": "{n, plural, =1 {Carta} other {Carte}}", @@ -93,6 +95,7 @@ "file-format": "Formato del file", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Francese", "german": "Tedesco", @@ -182,6 +185,7 @@ "share": "Condividi", "share-this-list": "", "share-this-trail": "Condividi questo percorso", + "shared": "", "shared-by": "Condiviso da", "shared-with": "Condiviso con", "show-in-overview": "Mostra nella panoramica", diff --git a/web/src/lib/i18n/locales/nl.json b/web/src/lib/i18n/locales/nl.json index 8fd4288f..97768296 100644 --- a/web/src/lib/i18n/locales/nl.json +++ b/web/src/lib/i18n/locales/nl.json @@ -18,10 +18,12 @@ "already-account": "Heb je al een account?", "altitude": "Hoogte", "api-documentation": "API-documentatie", + "author": "", "avatar": "Profielfoto", "average-speed": "", "basic-info": "Algemene informatie", "before": "", + "by": "", "can": "", "cancel": "Annuleren", "card": "{n, plural, =1 {kaart} other {kaarten}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Frans", "german": "Duits", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "Tonen op overzicht", diff --git a/web/src/lib/i18n/locales/pl.json b/web/src/lib/i18n/locales/pl.json index 12e468f4..ca032509 100644 --- a/web/src/lib/i18n/locales/pl.json +++ b/web/src/lib/i18n/locales/pl.json @@ -18,10 +18,12 @@ "already-account": "Czy masz już konto?", "altitude": "Wysokość", "api-documentation": "Dokumentacja API", + "author": "", "avatar": "Awatar", "average-speed": "", "basic-info": "Podstawowe informacje", "before": "", + "by": "", "can": "", "cancel": "Anuluj", "card": "{n, plural, =1 {Karta} other {Karty}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Francuski", "german": "Niemiecki", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "Pokaż w przeglądzie", diff --git a/web/src/lib/i18n/locales/pt.json b/web/src/lib/i18n/locales/pt.json index e91e2dcb..7edd13ea 100644 --- a/web/src/lib/i18n/locales/pt.json +++ b/web/src/lib/i18n/locales/pt.json @@ -18,10 +18,12 @@ "already-account": "Já tem uma conta?", "altitude": "Altitude", "api-documentation": "Documentação da API", + "author": "", "avatar": "Avatar", "average-speed": "", "basic-info": "Informações básicas", "before": "", + "by": "", "can": "", "cancel": "Cancelar", "card": "{n, plural, =1 {Cartão} other {cartãos}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "Francês", "german": "Alemão", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "Mostrar na vista geral", diff --git a/web/src/lib/i18n/locales/zh.json b/web/src/lib/i18n/locales/zh.json index 70f4cc4b..fbe7eb3a 100644 --- a/web/src/lib/i18n/locales/zh.json +++ b/web/src/lib/i18n/locales/zh.json @@ -18,10 +18,12 @@ "already-account": "已注册账户?", "altitude": "海拔", "api-documentation": "API 文档", + "author": "", "avatar": "头像", "average-speed": "", "basic-info": "基本信息", "before": "", + "by": "", "can": "", "cancel": "取消", "card": "{n, plural, =1 {卡片} other {卡片}}", @@ -93,6 +95,7 @@ "file-format": "", "file-too-big": "", "filter-categories": "", + "filter-difficulty": "", "focus-map-on": "", "french": "法语", "german": "德语", @@ -182,6 +185,7 @@ "share": "", "share-this-list": "", "share-this-trail": "", + "shared": "", "shared-by": "", "shared-with": "", "show-in-overview": "详情中展示", diff --git a/web/src/lib/models/trail.ts b/web/src/lib/models/trail.ts index f735bd1f..e11fdccf 100644 --- a/web/src/lib/models/trail.ts +++ b/web/src/lib/models/trail.ts @@ -2,6 +2,7 @@ import type { Category } from "./category"; import type { Comment } from "./comment"; import type { SummitLog } from "./summit_log"; import type { TrailShare } from "./trail_share"; +import type { UserAnonymous } from "./user"; import type { Waypoint } from "./waypoint"; class Trail { @@ -28,6 +29,7 @@ class Trail { category?: Category; waypoints: Waypoint[] summit_logs: SummitLog[] + author?: UserAnonymous comments_via_trail: Comment[] gpx_data?: string trail_share_via_trail?: TrailShare[] @@ -97,6 +99,9 @@ interface TrailFilter { q: string, category: string[], difficulty: ("easy" | "moderate" | "difficult")[] + author?: string; + public?: boolean; + shared?: boolean; near: { lat?: number, lon?: number, @@ -138,4 +143,4 @@ interface TrailBoundingBox { export { Trail }; -export type { TrailFilter, TrailFilterValues, TrailBoundingBox }; \ No newline at end of file + export type { TrailBoundingBox, TrailFilter, TrailFilterValues }; diff --git a/web/src/lib/models/user.ts b/web/src/lib/models/user.ts index 383a4c08..4759f081 100644 --- a/web/src/lib/models/user.ts +++ b/web/src/lib/models/user.ts @@ -8,4 +8,10 @@ export type User = { avatar?: string; language?: string; created?: string; +} + +export type UserAnonymous = { + id: string, + username?: string, + avatar?: string; } \ No newline at end of file diff --git a/web/src/lib/stores/trail_store.ts b/web/src/lib/stores/trail_store.ts index c2f235bc..da516a41 100644 --- a/web/src/lib/stores/trail_store.ts +++ b/web/src/lib/stores/trail_store.ts @@ -401,7 +401,35 @@ function buildFilterText(filter: TrailFilter, includeGeo: boolean): string { filterText += ` AND elevation_loss <= ${Math.ceil(filter.elevationLossMax)}` } - filterText += ` AND difficulty IN [${filter.difficulty.join(",")}]` + if (filter.difficulty.length > 0) { + filterText += ` AND difficulty IN [${filter.difficulty.join(",")}]` + } + + if (filter.author?.length) { + filterText += ` AND author = ${filter.author}` + } + + if (filter.public !== undefined || filter.shared !== undefined) { + filterText += " AND (" + if (filter.public !== undefined) { + filterText += `(public = ${filter.public}` + + if (!filter.author?.length || filter.author == pb.authStore.model?.id) { + filterText += ` OR author = ${pb.authStore.model?.id}` + } + filterText += ")" + } + + if (filter.shared !== undefined) { + if (filter.shared === true) { + filterText += ` OR shares = ${pb.authStore.model?.id}` + } else { + filterText += ` AND NOT shares = ${pb.authStore.model?.id}` + + } + } + filterText += ")" + } if (filter.startDate) { filterText += ` AND date >= ${new Date(filter.startDate).getTime() / 1000}` diff --git a/web/src/lib/stores/user_store.ts b/web/src/lib/stores/user_store.ts index aeee51b9..7bc9dbe9 100644 --- a/web/src/lib/stores/user_store.ts +++ b/web/src/lib/stores/user_store.ts @@ -20,9 +20,9 @@ export async function users_create(user: User) { return createdUser; } -export async function users_search(q: string) { +export async function users_search(q: string, includeSelf: boolean = true) { let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({ - "filter": `username~"${q}"&&id!="${pb.authStore.model?.id}"`, + "filter": `username~"${q}"${includeSelf ? '' : '&&id!="${pb.authStore.model?.id}"'}`, }), { method: 'GET', }) diff --git a/web/src/routes/api/v1/trail/+server.ts b/web/src/routes/api/v1/trail/+server.ts index 01564ee1..3e6d1ce7 100644 --- a/web/src/routes/api/v1/trail/+server.ts +++ b/web/src/routes/api/v1/trail/+server.ts @@ -21,8 +21,18 @@ export async function GET(event: RequestEvent) { .getList(parseInt(page), parseInt(perPage), { expand: expand ?? "", sort: sort ?? "", filter: filter ?? "" }) } + for (const t of r.items) { + if (!t.author || !pb.authStore.model) { + continue; + } + if(!t.expand) { + t.expand = {} as any + } + t.expand.author = await pb.collection("users_anonymous").getOne(t.author); + } return json(r) } catch (e: any) { + console.error(e) throw error(e.status, e); } } diff --git a/web/src/routes/api/v1/trail/[id]/+server.ts b/web/src/routes/api/v1/trail/[id]/+server.ts index f79d4bbc..66b5d86c 100644 --- a/web/src/routes/api/v1/trail/[id]/+server.ts +++ b/web/src/routes/api/v1/trail/[id]/+server.ts @@ -9,14 +9,22 @@ export async function GET(event: RequestEvent) { const r = await pb.collection('trails') .getOne(event.params.id as string, { expand: expand ?? "" }) + + if (pb.authStore.model) { + if (!r.expand) { + r.expand = {} as any + } + r.expand.author = await pb.collection("users_anonymous").getOne(r.author!); + } + // remove time from dates r.date = r.date?.substring(0, 10) ?? "" for (const log of r.expand?.summit_logs ?? []) { log.date = log.date.substring(0, 10) } return json(r) - } catch (e: any) { - throw error(e.status || 500, e); + } catch (e: any) { + throw error(e.status || 500, e); } } diff --git a/web/src/routes/map/+page.ts b/web/src/routes/map/+page.ts index 324d8ef1..5228f819 100644 --- a/web/src/routes/map/+page.ts +++ b/web/src/routes/map/+page.ts @@ -11,6 +11,9 @@ export const load: ServerLoad = async ({ params, locals, fetch }) => { q: "", category: [], difficulty: ["easy", "moderate", "difficult"], + author: "", + public: true, + shared: true, near: { radius: 2000, }, diff --git a/web/src/routes/trails/+page.server.ts b/web/src/routes/trails/+page.server.ts index 23b3d81b..33030b6c 100644 --- a/web/src/routes/trails/+page.server.ts +++ b/web/src/routes/trails/+page.server.ts @@ -10,6 +10,9 @@ export const load: ServerLoad = async ({ params, locals, url, fetch }) => { q: "", category: [], difficulty: ["easy", "moderate", "difficult"], + author: "", + public: true, + shared: true, near: { radius: 2000, }, diff --git a/web/static/models/mountain.glb b/web/static/models/mountain.glb new file mode 100644 index 00000000..adda48a6 Binary files /dev/null and b/web/static/models/mountain.glb differ