makes profiles public

This commit is contained in:
Christian Beutel
2024-11-16 15:13:22 +01:00
parent 2e8d7f5e82
commit dcc8da83e7
19 changed files with 364 additions and 41 deletions

View File

@@ -78,7 +78,7 @@
function handleDropdownClick(item: { text: string; value: any }) {
if (item.value == "profile") {
goto("/profile");
goto(`/profile/${$currentUser?.id}`);
} else if (item.value == "logout") {
logout();
window.location.href = "/";
@@ -128,7 +128,7 @@
<div class="basis-full"></div>
<hr class="border-input-border" />
<div class="flex gap-4 items-center justify-between m-4">
<a href="/profile">
<a href="/profile/{$currentUser.id}">
<img
class="rounded-full w-10 aspect-square"
src={getFileURL($currentUser, $currentUser.avatar) ||
@@ -136,7 +136,7 @@
alt="avatar"
/>
</a>
<a href="/profile">
<a href="/profile/{$currentUser.id}">
<p class="text-sm">{$currentUser.username}</p>
<p class="text-sm text-gray-500">
{$currentUser.email}

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type { List } from "$lib/models/list";
import type { Trail } from "$lib/models/trail";
import type { User } from "$lib/models/user";
import type { User, UserAnonymous } from "$lib/models/user";
import { pb } from "$lib/pocketbase";
import { users_show } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util";
@@ -18,7 +18,7 @@
let loading: boolean = false;
let infoLoaded: boolean = false;
let subjectIsOwned: boolean = subject.author == pb.authStore.model?.id;
let author: User;
let author: UserAnonymous;
async function fetchInfo() {
if (!infoLoaded) {

View File

@@ -14,6 +14,7 @@
export let summitLogs: SummitLog[] = [];
export let showCategory: boolean = false;
export let showTrail: boolean = false;
export let showAuthor: boolean = false;
let openMapModal: () => void;
let closeMapModal: () => void;
@@ -27,9 +28,7 @@
let currentText: string = "";
onMount(async () => {
});
onMount(async () => {});
async function openMap(log: SummitLog) {
if (!log.expand.gpx_data) {
@@ -72,6 +71,11 @@
</th>
{/if}
<th>{$_("description")}</th>
{#if showAuthor}
<th>
{$_("author", { values: { n: 1 } })}
</th>
{/if}
</tr>
</thead>
<tbody>
@@ -83,6 +87,7 @@
on:text={(e) => openText(e.detail)}
{showCategory}
{showTrail}
{showAuthor}
></SummitLogTableRow>
{/each}
</tbody>

View File

@@ -11,11 +11,13 @@
import type { Map } from "leaflet";
import { createEventDispatcher, onMount } from "svelte";
import { _ } from "svelte-i18n";
import { getFileURL } from "$lib/util/file_util";
export let index: number;
export let log: SummitLog;
export let showCategory: boolean = false;
export let showTrail: boolean = false;
export let showAuthor: boolean = false;
let map: Map;
@@ -64,13 +66,10 @@
}
function colCount() {
if (showCategory && showTrail) {
return 9;
} else if (showCategory || showTrail) {
return 8;
}
return 7;
return [showCategory, showTrail, showAuthor].reduce(
(b, v) => (v ? b + 1 : b),
7,
);
}
</script>
@@ -130,6 +129,26 @@
>
{/if}
</td>
{#if showAuthor && log.expand.author}
<td>
<p
class="tooltip flex justify-center"
data-title={log.expand.author.username}
>
<a href="/profile/{log.expand.author.id}">
<img
class="rounded-full w-7 aspect-square"
src={getFileURL(
log.expand?.author,
log.expand?.author.avatar,
) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${log.expand?.author.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
</a>
</p>
</td>
{/if}
</tr>
<tr>
<td colspan={colCount()}> <hr class="border-input-border" /> </td>

View File

@@ -172,7 +172,7 @@
class="trail-info-panel mx-auto {mode == 'list'
? ''
: 'border border-input-border rounded-3xl'} h-full"
style="max-width: min(100%, 64rem);"
style="max-width: min(100%, 76rem);"
>
<div class="trail-info-panel-header">
<section class="relative h-80">
@@ -239,7 +239,7 @@
`https://api.dicebear.com/7.x/initials/svg?seed=${trail.expand.author.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
{trail.expand.author.username}
<a class="underline" href="/profile/{trail.expand.author.id}">{trail.expand.author.username}</a>
</p>
{/if}
<div class="flex flex-wrap gap-x-8 gap-y-2 mt-4 mr-8">
@@ -357,8 +357,8 @@
</div>
{/if}
{#if activeTab == 3}
<div class="overflow-x-scroll">
<SummitLogTable summitLogs={trail.expand.summit_logs}
<div class="overflow-x-auto">
<SummitLogTable summitLogs={trail.expand.summit_logs} showAuthor
></SummitLogTable>
</div>
{/if}

View File

@@ -1,4 +1,5 @@
import type { Trail } from "./trail";
import type { UserAnonymous } from "./user";
class SummitLog {
id?: string;
@@ -15,6 +16,7 @@ class SummitLog {
expand: {
gpx_data?: string;
trails_via_summit_logs?: Trail[];
author?: UserAnonymous
}
constructor(date: string, params?: { id?: string, text?: string, distance?: number, elevation_loss?: number, elevation_gain?: number, duration?: number }) {

View File

@@ -1,4 +1,4 @@
import type { User } from "./user";
import type { User, UserAnonymous } from "./user";
export class TrailShare {
id?: string;
@@ -6,7 +6,7 @@ export class TrailShare {
trail: string;
permission: "view" | "edit"
expand?: {
user: User
user: UserAnonymous
}
constructor(user: string, trail: string, permission: "view" | "edit") {

View File

@@ -14,4 +14,5 @@ export type UserAnonymous = {
id: string,
username?: string,
avatar?: string;
created?: string;
}

View File

@@ -7,8 +7,10 @@ import { fetchGPX } from "./trail_store";
export const summitLog: Writable<SummitLog> = writable(new SummitLog(new Date().toISOString().substring(0, 10)));
export const summitLogs: Writable<SummitLog[]> = writable([]);
export async function summit_logs_index(filter?: SummitLogFilter, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const filterText = filter ? buildFilterText(filter) : "";
export async function summit_logs_index(author: string, filter?: SummitLogFilter, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
let filterText = `author='${author}'`
filterText += filter ? "&&" + buildFilterText(filter) : "";
const r = await f('/api/v1/summit-log?' + new URLSearchParams({
filter: filterText,
@@ -35,7 +37,7 @@ export async function summit_logs_index(filter?: SummitLogFilter, f: (url: Reque
}
summitLogs.set(fetchedSummitLogs);
return fetchedSummitLogs;
}
@@ -117,15 +119,15 @@ function buildFilterText(filter: SummitLogFilter,): string {
let filterText: string = "";
if (filter.category.length > 0) {
filterText += `trails_via_summit_logs.category != null && '${filter.category.join(",")}' ~ trails_via_summit_logs.category`;
filterText += `trails_via_summit_logs.category!=null&&'${filter.category.join(",")}'~trails_via_summit_logs.category`;
}
if (filter.startDate) {
filterText += `${filter.category.length ? ' && ' : ''}date >= '${filter.startDate}'`
filterText += `${filter.category.length ? '&&' : ''}date>='${filter.startDate}'`
}
if (filter.endDate) {
filterText += `${filter.category.length || filter.startDate ? ' && ' : ''} date <= '${filter.endDate}'`
filterText += `${filter.category.length || filter.startDate ? '&&' : ''}date<='${filter.endDate}'`
}
return filterText;

View File

@@ -1,4 +1,4 @@
import type { User } from "$lib/models/user";
import type { User, UserAnonymous } from "$lib/models/user";
import { pb } from "$lib/pocketbase";
import { ClientResponseError, type AuthMethodsList } from "pocketbase";
import { writable, type Writable } from "svelte/store";
@@ -35,11 +35,11 @@ export async function users_search(q: string, includeSelf: boolean = true) {
}
}
export async function users_show(id: string) {
let r = await fetch(`/api/v1/user/anonymous/${id}`, {
export async function users_show(id: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
let r = await f(`/api/v1/user/anonymous/${id}`, {
method: 'GET',
})
const response = await r.json()
const response: UserAnonymous = await r.json()
if (r.ok) {
return response;

View File

@@ -11,6 +11,16 @@ export async function GET(event: RequestEvent) {
sort: "+date",
filter: filter
})
for (const t of r) {
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) {
throw error(e.status, e);

View File

@@ -7,6 +7,12 @@ export async function GET(event: RequestEvent) {
try {
const r = await pb.collection('summit_logs')
.getOne<SummitLog>(event.params.id as string)
if (!r.expand) {
r.expand = {} as any
}
r.expand.author = await pb.collection("users_anonymous").getOne(r.author!);
return json(r)
} catch (e: any) {
throw error(e.status, e);

View File

@@ -21,9 +21,15 @@ export async function GET(event: RequestEvent) {
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
}
log.expand.author = await pb.collection("users_anonymous").getOne(log.author!);
}
return json(r)
} catch (e: any) {
console.error(e)
throw error(e.status || 500, e);
}
}

View File

@@ -218,7 +218,7 @@
}
async function loadSummitLogs() {
const logs = await summit_logs_index(filter);
const logs = await summit_logs_index($page.params.id, filter);
summitLogs.set(logs);
}
</script>
@@ -230,21 +230,21 @@
<div
class="grid grid-cols-1 sm:grid-cols-[272px_minmax(0,_1fr)] md:grid-cols-[356px_minmax(0,_1fr)] gap-y-4 max-w-6xl mx-auto"
>
{#if $currentUser}
{#if data.user}
<div class="flex items-center gap-x-6 h-full px-4">
<img
class="rounded-full w-16 aspect-square overflow-hidden"
src={getFileURL($currentUser, $currentUser.avatar) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${$currentUser.username}&backgroundType=gradientLinear`}
src={getFileURL(data.user, data.user.avatar) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${data.user.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
<div>
<h4 class="text-2xl font-semibold col-start-2">
{$currentUser.username}
{data.user.username}
</h4>
<p class="text-sm">
<span class="text-gray-500">Joined:</span>
{new Date($currentUser.created ?? "").toLocaleDateString(
{new Date(data.user.created ?? "").toLocaleDateString(
undefined,
{
month: "2-digit",
@@ -420,7 +420,7 @@
<span class="text-gray-500 font-semibold text-lg"
><i class="fa fa-table mr-3"></i>{$_("all-activities")}</span
>
<div class=" overflow-x-scroll">
<div class=" overflow-x-auto">
<SummitLogTable summitLogs={$summitLogs} showCategory showTrail
></SummitLogTable>
</div>

View File

@@ -1,10 +1,15 @@
import type { SummitLogFilter } from "$lib/models/summit_log";
import { categories_index } from "$lib/stores/category_store";
import { summit_logs_index } from "$lib/stores/summit_log_store";
import { type ServerLoad } from "@sveltejs/kit";
import { users_show } from "$lib/stores/user_store";
import { error, type ServerLoad } from "@sveltejs/kit";
export const load: ServerLoad = async ({ params, locals, fetch }) => {
if(!params.id) {
error(404, "Not found")
}
const date = new Date()
date.setUTCHours(6)
const y = date.getFullYear()
@@ -19,7 +24,8 @@ export const load: ServerLoad = async ({ params, locals, fetch }) => {
endDate: lastDay.toISOString().slice(0, 10),
category: []
}
const logs = await summit_logs_index(filter, fetch);
const logs = await summit_logs_index(params.id, filter, fetch);
const user = await users_show(params.id, fetch);
return {filter}
return { filter, user }
};