diff --git a/backend/server/adventures/views/stats_view.py b/backend/server/adventures/views/stats_view.py index 23733a5..37d9f07 100644 --- a/backend/server/adventures/views/stats_view.py +++ b/backend/server/adventures/views/stats_view.py @@ -2,29 +2,42 @@ from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.decorators import action +from django.shortcuts import get_object_or_404 from worldtravel.models import City, Region, Country, VisitedCity, VisitedRegion from adventures.models import Adventure, Collection +from users.serializers import CustomUserDetailsSerializer as PublicUserSerializer +from django.contrib.auth import get_user_model + +User = get_user_model() class StatsViewSet(viewsets.ViewSet): """ A simple ViewSet for listing the stats of a user. """ - permission_classes = [IsAuthenticated] + @action(detail=False, methods=['get'], url_path='counts/(?P[^/.]+)') + def counts(self, request, username): + if request.user.username == username: + user = get_object_or_404(User, username=username) + else: + user = get_object_or_404(User, username=username, public_profile=True) + serializer = PublicUserSerializer(user) + + # remove the email address from the response + user.email = None - @action(detail=False, methods=['get']) - def counts(self, request): + # get the counts for the user adventure_count = Adventure.objects.filter( - user_id=request.user.id).count() + user_id=user.id).count() trips_count = Collection.objects.filter( - user_id=request.user.id).count() + user_id=user.id).count() visited_city_count = VisitedCity.objects.filter( - user_id=request.user.id).count() + user_id=user.id).count() total_cities = City.objects.count() visited_region_count = VisitedRegion.objects.filter( - user_id=request.user.id).count() + user_id=user.id).count() total_regions = Region.objects.count() visited_country_count = VisitedRegion.objects.filter( - user_id=request.user.id).values('region__country').distinct().count() + user_id=user.id).values('region__country').distinct().count() total_countries = Country.objects.count() return Response({ 'adventure_count': adventure_count, diff --git a/backend/server/users/views.py b/backend/server/users/views.py index e741a69..0d0fca1 100644 --- a/backend/server/users/views.py +++ b/backend/server/users/views.py @@ -82,7 +82,6 @@ class PublicUserDetailView(APIView): operation_description="Get public user information." ) def get(self, request, username): - print(request.user) if request.user.username == username: user = get_object_or_404(User, username=username) else: diff --git a/frontend/src/lib/components/AdventureModal.svelte b/frontend/src/lib/components/AdventureModal.svelte index a0aa8f8..28cd752 100644 --- a/frontend/src/lib/components/AdventureModal.svelte +++ b/frontend/src/lib/components/AdventureModal.svelte @@ -10,7 +10,6 @@ ReverseGeocode } from '$lib/types'; import { onMount } from 'svelte'; - import { enhance } from '$app/forms'; import { addToast } from '$lib/toasts'; import { deserialize } from '$app/forms'; import { t } from 'svelte-i18n'; @@ -1257,7 +1256,7 @@ it would also work to just use on:click on the MapLibre component itself. --> {#if immichIntegration} { url = e.detail; fetchImage(); diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 6115fe0..c01123e 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -234,7 +234,8 @@ "images": "Bilder", "primary": "Primär", "upload": "Hochladen", - "view_attachment": "Anhang anzeigen" + "view_attachment": "Anhang anzeigen", + "of": "von" }, "home": { "desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit", @@ -302,7 +303,11 @@ "both_passwords_required": "Beide Passwörter sind erforderlich", "new_password": "Neues Passwort", "reset_failed": "Passwort konnte nicht zurückgesetzt werden", - "or_3rd_party": "Oder melden Sie sich bei einem Drittanbieter an" + "or_3rd_party": "Oder melden Sie sich bei einem Drittanbieter an", + "no_public_adventures": "Keine öffentlichen Abenteuer gefunden", + "no_public_collections": "Keine öffentlichen Sammlungen gefunden", + "user_adventures": "Benutzerabenteuer", + "user_collections": "Benutzersammlungen" }, "users": { "no_users_found": "Keine Benutzer mit öffentlichen Profilen gefunden." diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 0a9f943..4c4e645 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -165,6 +165,7 @@ "delete_collection_success": "Collection deleted successfully!", "delete_collection_warning": "Are you sure you want to delete this collection? This will also delete all of the linked adventures. This action cannot be undone.", "cancel": "Cancel", + "of": "of", "delete_collection": "Delete Collection", "delete_adventure": "Delete Adventure", "adventure_delete_success": "Adventure deleted successfully!", diff --git a/frontend/src/locales/es.json b/frontend/src/locales/es.json index 0f00856..6b98c34 100644 --- a/frontend/src/locales/es.json +++ b/frontend/src/locales/es.json @@ -281,7 +281,8 @@ "primary": "Primario", "upload": "Subir", "view_attachment": "Ver archivo adjunto", - "attachment_name": "Nombre del archivo adjunto" + "attachment_name": "Nombre del archivo adjunto", + "of": "de" }, "worldtravel": { "all": "Todo", @@ -326,7 +327,11 @@ "both_passwords_required": "Se requieren ambas contraseñas", "new_password": "Nueva contraseña", "reset_failed": "No se pudo restablecer la contraseña", - "or_3rd_party": "O inicie sesión con un servicio de terceros" + "or_3rd_party": "O inicie sesión con un servicio de terceros", + "no_public_adventures": "No se encontraron aventuras públicas", + "no_public_collections": "No se encontraron colecciones públicas", + "user_adventures": "Aventuras de usuario", + "user_collections": "Colecciones de usuarios" }, "users": { "no_users_found": "No se encontraron usuarios con perfiles públicos." diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index e99f79d..8d6df46 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -234,7 +234,8 @@ "images": "Images", "primary": "Primaire", "upload": "Télécharger", - "view_attachment": "Voir la pièce jointe" + "view_attachment": "Voir la pièce jointe", + "of": "de" }, "home": { "desc_1": "Découvrez, planifiez et explorez en toute simplicité", @@ -302,7 +303,11 @@ "both_passwords_required": "Les deux mots de passe sont requis", "new_password": "Nouveau mot de passe", "reset_failed": "Échec de la réinitialisation du mot de passe", - "or_3rd_party": "Ou connectez-vous avec un service tiers" + "or_3rd_party": "Ou connectez-vous avec un service tiers", + "no_public_adventures": "Aucune aventure publique trouvée", + "no_public_collections": "Aucune collection publique trouvée", + "user_adventures": "Aventures utilisateur", + "user_collections": "Collections d'utilisateurs" }, "users": { "no_users_found": "Aucun utilisateur trouvé avec des profils publics." diff --git a/frontend/src/locales/it.json b/frontend/src/locales/it.json index 12877dc..ad0f0c1 100644 --- a/frontend/src/locales/it.json +++ b/frontend/src/locales/it.json @@ -234,7 +234,8 @@ "images": "Immagini", "primary": "Primario", "upload": "Caricamento", - "view_attachment": "Visualizza allegato" + "view_attachment": "Visualizza allegato", + "of": "Di" }, "home": { "desc_1": "Scopri, pianifica ed esplora con facilità", @@ -302,7 +303,11 @@ "both_passwords_required": "Sono necessarie entrambe le password", "new_password": "Nuova parola d'ordine", "reset_failed": "Impossibile reimpostare la password", - "or_3rd_party": "Oppure accedi con un servizio di terze parti" + "or_3rd_party": "Oppure accedi con un servizio di terze parti", + "no_public_adventures": "Nessuna avventura pubblica trovata", + "no_public_collections": "Nessuna collezione pubblica trovata", + "user_adventures": "Avventure utente", + "user_collections": "Collezioni utente" }, "users": { "no_users_found": "Nessun utente trovato con profili pubblici." diff --git a/frontend/src/locales/nl.json b/frontend/src/locales/nl.json index cdb1c5d..9e6619f 100644 --- a/frontend/src/locales/nl.json +++ b/frontend/src/locales/nl.json @@ -234,7 +234,8 @@ "images": "Afbeeldingen", "primary": "Primair", "upload": "Uploaden", - "view_attachment": "Bijlage bekijken" + "view_attachment": "Bijlage bekijken", + "of": "van" }, "home": { "desc_1": "Ontdek, plan en verken met gemak", @@ -302,7 +303,11 @@ "both_passwords_required": "Beide wachtwoorden zijn vereist", "new_password": "Nieuw wachtwoord", "reset_failed": "Kan het wachtwoord niet opnieuw instellen", - "or_3rd_party": "Of log in met een service van derden" + "or_3rd_party": "Of log in met een service van derden", + "no_public_adventures": "Geen openbare avonturen gevonden", + "no_public_collections": "Geen openbare collecties gevonden", + "user_adventures": "Gebruikersavonturen", + "user_collections": "Gebruikerscollecties" }, "users": { "no_users_found": "Er zijn geen gebruikers gevonden met openbare profielen." diff --git a/frontend/src/locales/pl.json b/frontend/src/locales/pl.json index 31134d5..982d8d8 100644 --- a/frontend/src/locales/pl.json +++ b/frontend/src/locales/pl.json @@ -281,7 +281,8 @@ "images": "Obrazy", "primary": "Podstawowy", "upload": "Wgrywać", - "view_attachment": "Zobacz załącznik" + "view_attachment": "Zobacz załącznik", + "of": "z" }, "worldtravel": { "country_list": "Lista krajów", @@ -326,7 +327,11 @@ "both_passwords_required": "Obydwa hasła są wymagane", "new_password": "Nowe hasło", "reset_failed": "Nie udało się zresetować hasła", - "or_3rd_party": "Lub zaloguj się za pomocą usługi strony trzeciej" + "or_3rd_party": "Lub zaloguj się za pomocą usługi strony trzeciej", + "no_public_adventures": "Nie znaleziono publicznych przygód", + "no_public_collections": "Nie znaleziono publicznych kolekcji", + "user_adventures": "Przygody użytkowników", + "user_collections": "Kolekcje użytkowników" }, "users": { "no_users_found": "Nie znaleziono użytkowników z publicznymi profilami." diff --git a/frontend/src/locales/sv.json b/frontend/src/locales/sv.json index 919c6d9..a2373ca 100644 --- a/frontend/src/locales/sv.json +++ b/frontend/src/locales/sv.json @@ -234,7 +234,8 @@ "images": "Bilder", "primary": "Primär", "upload": "Ladda upp", - "view_attachment": "Visa bilaga" + "view_attachment": "Visa bilaga", + "of": "av" }, "home": { "desc_1": "Upptäck, planera och utforska med lätthet", @@ -326,7 +327,11 @@ "both_passwords_required": "Båda lösenorden krävs", "new_password": "Nytt lösenord", "reset_failed": "Det gick inte att återställa lösenordet", - "or_3rd_party": "Eller logga in med en tredjepartstjänst" + "or_3rd_party": "Eller logga in med en tredjepartstjänst", + "no_public_adventures": "Inga offentliga äventyr hittades", + "no_public_collections": "Inga offentliga samlingar hittades", + "user_adventures": "Användaräventyr", + "user_collections": "Användarsamlingar" }, "users": { "no_users_found": "Inga användare hittades med offentliga profiler." diff --git a/frontend/src/locales/zh.json b/frontend/src/locales/zh.json index 7270e3b..1ecb246 100644 --- a/frontend/src/locales/zh.json +++ b/frontend/src/locales/zh.json @@ -234,7 +234,8 @@ "images": "图片", "primary": "基本的", "upload": "上传", - "view_attachment": "查看附件" + "view_attachment": "查看附件", + "of": "的" }, "home": { "desc_1": "轻松发现、规划和探索", @@ -302,7 +303,11 @@ "both_passwords_required": "两个密码都需要", "new_password": "新密码", "reset_failed": "重置密码失败", - "or_3rd_party": "或者使用第三方服务登录" + "or_3rd_party": "或者使用第三方服务登录", + "no_public_adventures": "找不到公共冒险", + "no_public_collections": "找不到公共收藏", + "user_adventures": "用户冒险", + "user_collections": "用户收集" }, "worldtravel": { "all": "全部", diff --git a/frontend/src/routes/profile/[uuid]/+page.server.ts b/frontend/src/routes/profile/[uuid]/+page.server.ts index c1abfce..f98f782 100644 --- a/frontend/src/routes/profile/[uuid]/+page.server.ts +++ b/frontend/src/routes/profile/[uuid]/+page.server.ts @@ -1,31 +1,29 @@ import { redirect, error } from '@sveltejs/kit'; import type { PageServerLoad, RequestEvent } from '../../$types'; +import { t } from 'svelte-i18n'; const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL']; export const load: PageServerLoad = async (event: RequestEvent) => { const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000'; - let uuid = event.params.uuid as string; + // @ts-ignore + let username = event.params.uuid as string; - if (!uuid) { + if (!username) { return error(404, 'Not found'); } // let sessionId = event.cookies.get('sessionid'); - // let stats = null; + let stats = null; - // let res = await event.fetch(`${endpoint}/api/stats/counts/`, { - // headers: { - // Cookie: `sessionid=${sessionId}` - // } - // }); - // if (!res.ok) { - // console.error('Failed to fetch user stats'); - // } else { - // stats = await res.json(); - // } + let res = await event.fetch(`${endpoint}/api/stats/counts/${username}`, {}); + if (!res.ok) { + console.error('Failed to fetch user stats'); + } else { + stats = await res.json(); + } - let userData = await event.fetch(`${endpoint}/auth/user/${uuid}/`); + let userData = await event.fetch(`${endpoint}/auth/user/${username}/`); if (!userData.ok) { return error(404, 'Not found'); } @@ -35,6 +33,7 @@ export const load: PageServerLoad = async (event: RequestEvent) => { return { user: data.user, adventures: data.adventures, - collections: data.collections + collections: data.collections, + stats: stats }; }; diff --git a/frontend/src/routes/profile/[uuid]/+page.svelte b/frontend/src/routes/profile/[uuid]/+page.svelte index d2d784d..02d82c9 100644 --- a/frontend/src/routes/profile/[uuid]/+page.svelte +++ b/frontend/src/routes/profile/[uuid]/+page.svelte @@ -5,26 +5,21 @@ import type { Adventure, Collection, User } from '$lib/types.js'; import { t } from 'svelte-i18n'; - // let stats: { - // visited_country_count: number; - // total_regions: number; - // trips_count: number; - // adventure_count: number; - // visited_region_count: number; - // total_countries: number; - // visited_city_count: number; - // total_cities: number; - // } | null; + let stats: { + visited_country_count: number; + total_regions: number; + trips_count: number; + adventure_count: number; + visited_region_count: number; + total_countries: number; + visited_city_count: number; + total_cities: number; + } | null; const user: User = data.user; const adventures: Adventure[] = data.adventures; const collections: Collection[] = data.collections; - - // console.log(user); - // console.log(adventures); - // console.log(collections); - - // stats = data.stats || null; + stats = data.stats || null;
@@ -83,7 +78,7 @@ - + {/if}