Skip to content

Commit

Permalink
Merge pull request #16 from derGraph/fix-Userpage
Browse files Browse the repository at this point in the history
new Version
  • Loading branch information
derGraph authored Dec 31, 2024
2 parents 1e91e36 + 644463b commit 8713cad
Show file tree
Hide file tree
Showing 33 changed files with 992 additions and 333 deletions.
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json .
RUN npm i
#TODO: remove legacy peer drops as soon as the adapter is updated!
RUN npm i --force
COPY . .
RUN npx prisma generate
RUN npm run build
RUN npm prune --production
RUN npm prune --production --force

WORKDIR /app/workers
RUN npm i
RUN npx tsc
RUN npx tsc-alias

FROM node:22-alpine
FROM node:23-alpine3.20
WORKDIR /app
COPY --from=builder /app/build build/
COPY --from=builder /app/node_modules node_modules/
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"postcss": "8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"prisma": "^5.21.1",
"prisma": "^6.1.0",
"svelte": "^5.1.9",
"svelte-check": "^4.0.5",
"tailwindcss": "3.4.14",
Expand All @@ -41,7 +41,7 @@
"dependencies": {
"@lucia-auth/adapter-prisma": "^4.0.1",
"@node-rs/argon2": "^2.0.0",
"@prisma/client": "^5.21.1",
"@prisma/client": "^6.1.0",
"@skeletonlabs/skeleton": "^2.10.3",
"@skeletonlabs/tw-plugin": "^0.4.0",
"@sveltejs/adapter-auto": "^3.3.1",
Expand Down Expand Up @@ -75,7 +75,7 @@
"postcss": "8.4.47",
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"prisma": "^5.21.1",
"prisma": "^6.1.0",
"sailblog": "file:",
"sharp": "^0.33.5",
"svelte-check": "^4.0.5",
Expand Down
18 changes: 15 additions & 3 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ model User {
roleId String @default("user")
skipperedTrips Trip[] @relation("skipper")
crewedTrips Trip[] @relation("crew")
activeTrip Trip @relation(fields: [activeTripId], references: [id])
activeTripId String
activeTrip Trip? @relation(fields: [activeTripId], references: [id], onDelete: SetNull)
activeTripId String?
crewedLengthSail Int @default(0)
crewedLengthMotor Int @default(0)
skipperedLengthSail Int @default(0)
skipperedLengthMotor Int @default(0)
recalculate Boolean @default(true)
uploadedMedia Media[] @relation("uploader")
sessions Session[]
key Key[]
Expand Down Expand Up @@ -73,17 +78,19 @@ model Trip {
skipper User? @relation("skipper", fields: [skipperName], references: [username])
skipperName String?
crew User[] @relation("crew")
location Location[]
visibility Int @default(1) // 0: private
// 1: logged in
// 2: public
recalculate Boolean @default(true)
deleted Boolean @default(false)
}

model Datapoint {
id String @id @default(cuid())
tripStart Trip? @relation("startPoint")
tripEnd Trip? @relation("endPoint")
trip Trip @relation(fields: [tripId], references: [id])
trip Trip @relation(fields: [tripId], references: [id], onDelete: Cascade)
tripId String
time DateTime @default(now())
lat Decimal
Expand All @@ -101,6 +108,11 @@ model Datapoint {
// 2: needed
}

model Location {
name String @id
trips Trip[]
}

model Media {
id String @id @default(cuid())
visibility Int @default(1) // 0: private
Expand Down
143 changes: 73 additions & 70 deletions src/lib/Tiptap/+Tiptap.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
let isOpen = $state(false);
interface Props {
saveEditor: any;
description?: string;
description: string | null;
usernameToFetch?: string;
}
let { saveEditor, description = '', usernameToFetch = '' } = $props();
let { saveEditor, description = '', usernameToFetch = '' }:Props = $props();
function setContent(description: string) {
function setContent(description: string | null) {
if (editor) {
editor.commands.setContent(description);
}
Expand Down Expand Up @@ -101,7 +102,7 @@
],
editorProps: {
attributes: {
class: 'card p-2 m-1 variant-ghost-secondary min-h-96'
class: 'outline-none max-h-full min-h-96 overflow-auto text-wrap'
}
},
content: description,
Expand All @@ -118,8 +119,8 @@
}
});
function finishedImageUpload(url:string){
editor?.commands.setImage({src: url});
function finishedImageUpload(owner:string, imageId:string){
editor?.commands.setImage({src: "/api/Media/"+owner+"/"+imageId+".avif"});
}
function save() {
Expand All @@ -131,77 +132,79 @@
});
</script>

<div class="items-center">
<div class="items-center h-full flex flex-col">
{#if editing && editor}
<div class="btn-group variant-ghost-secondary m-1 [&>*+*]:border-secondary-500">
<div>
<div class="btn-group variant-ghost-secondary m-1 [&>*+*]:border-secondary-500">
<button
onclick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
class:active={editor.isActive('heading', { level: 2 })}
class="!pl-1 !pr-1 !py-1 !text-end material-symbols-outlined"
style="font-size: 1.5rem">title</button
>
<button
onclick={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
class:active={editor.isActive('heading', { level: 3 })}
class="!px-1 !py-1 material-symbols-outlined"
style="font-size: 1.25rem">title</button
>
<button
onclick={() => editor?.chain().focus().setParagraph().run()}
class:active={editor.isActive('paragraph')}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
style="font-size: 1rem">title</button
>
<button
onclick={() => editor?.chain().focus().toggleBlockquote().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('blockquote')}
style="font-size: 1.5rem">read_more</button
>
<button
onclick={() => editor?.chain().focus().toggleBulletList().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('bulletList')}
style="font-size: 1.5rem">format_list_bulleted</button
>
<button
onclick={() => editor?.chain().focus().toggleOrderedList().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('orderedList')}
style="font-size: 1.5rem">format_list_numbered</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('left').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'left' })}
style="font-size: 1.5rem">format_align_left</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('center').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'center' })}
style="font-size: 1.5rem">format_align_center</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('right').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'right' })}
style="font-size: 1.5rem">format_align_right</button
>
<button
onclick={() => isOpen=true}
class="!pl-1 !pr-2 !py-1 material-symbols-outlined"
style="font-size: 1.5rem">add_photo_alternate</button
>
</div>
<button
onclick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
class:active={editor.isActive('heading', { level: 2 })}
class="!pl-1 !pr-1 !py-1 !text-end material-symbols-outlined"
style="font-size: 1.5rem">title</button
>
<button
onclick={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
class:active={editor.isActive('heading', { level: 3 })}
class="!px-1 !py-1 material-symbols-outlined"
style="font-size: 1.25rem">title</button
>
<button
onclick={() => editor?.chain().focus().setParagraph().run()}
class:active={editor.isActive('paragraph')}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
style="font-size: 1rem">title</button
>
<button
onclick={() => editor?.chain().focus().toggleBlockquote().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('blockquote')}
style="font-size: 1.5rem">read_more</button
>
<button
onclick={() => editor?.chain().focus().toggleBulletList().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('bulletList')}
style="font-size: 1.5rem">format_list_bulleted</button
>
<button
onclick={() => editor?.chain().focus().toggleOrderedList().run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive('orderedList')}
style="font-size: 1.5rem">format_list_numbered</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('left').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'left' })}
style="font-size: 1.5rem">format_align_left</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('center').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'center' })}
style="font-size: 1.5rem">format_align_center</button
>
<button
onclick={() => editor?.chain().focus().setTextAlign('right').run()}
class="!px-1 !py-1 !py-1 material-symbols-outlined"
class:active={editor.isActive({ textAlign: 'right' })}
style="font-size: 1.5rem">format_align_right</button
>
<button
onclick={() => isOpen=true}
onclick={save}
class="!pl-1 !pr-2 !py-1 material-symbols-outlined"
style="font-size: 1.5rem">add_photo_alternate</button
style="font-size: 1.5rem">save</button
>
</div>
<button
onclick={save}
class="!pl-1 !pr-2 !py-1 material-symbols-outlined"
style="font-size: 1.5rem">save</button
>
{/if}

<div bind:this={element}></div>
<div bind:this={element} class="overflow-hidden h-full w-full card p-2 m-1 variant-ghost-secondary"></div>
<MediaPicker {usernameToFetch} bind:isOpen={isOpen} onFinished={finishedImageUpload}/>
</div>

Expand Down
19 changes: 19 additions & 0 deletions src/lib/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@ export function parseDate(unparsedDate:any){
}
let parsedDate = new Date(unparsedDate.time);
return parsedDate.getDate()+"."+(parsedDate.getMonth()+1)+"."+parsedDate.getFullYear();
}


export function getProfilePicture(user:{
description: string | null;
username: string;
firstName: string | null;
lastName: string | null;
profilePictureId: string | null;
dateOfBirth: Date | null;
roleId: string;
activeTripId: string | null;
lastPing: Date;
}){
if(user?.username && user?.profilePictureId){
return "/api/Media/"+user.username+"/"+user.profilePictureId+".avif"
}else{
return ""
}
}
16 changes: 8 additions & 8 deletions src/lib/mediaPicker.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<script lang="ts">
import { onMount } from "svelte";
import errorStore from "./errorStore";
let {isOpen = $bindable(false), usernameToFetch = "", onFinished = function(id:string){}} = $props();
let {isOpen = $bindable(false), usernameToFetch = "", onFinished = function(username:string, id:string){}} = $props();
let images: any[] = $state([]);
let files: any[] = [];
let mediaVisibilityPopup = $state(false);
let fileToUpload: string | Blob | null = null;
// Fetch images when the component mounts
onMount(async () => {
await fetchImages();
// Fetch images when username changes
$effect(()=>{
usernameToFetch;
fetchImages();
});
// Fetch images from the API
Expand Down Expand Up @@ -72,8 +72,8 @@
}
// Close the modal and return the selected image ID
function selectImage(url: any) {
onFinished(url);
function selectImage(username:String, imageId:String) {
onFinished(username, imageId);
isOpen = false;
}
Expand Down Expand Up @@ -134,7 +134,7 @@
{#each images as image}
<button
class="border rounded cursor-pointer h-min"
onclick={() => selectImage("/api/Media/"+image.username+"/"+image.id+".avif")}
onclick={() => selectImage(image.username, image.id)}
>
<img src={"/api/Media/"+image.username+"/"+image.id+".avif"} alt={parseAlt(image.alt)} class="object-cover rounded content-center w-full h-full" />
</button>
Expand Down
11 changes: 5 additions & 6 deletions src/lib/searchBar.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
// Sample data for demonstration purposes
let {displayed = $bindable(false), onSelected = function(id: string) {}, getList = (searchTerm: string) => Promise.resolve([] as String[])}:
{displayed: boolean, onSelected: Function, getList: (searchTerm: string) => Promise<String[]>} = $props();
let {displayed = $bindable(false), onSelected = function(id: string) {}, getList = (searchTerm: string) => Promise.resolve([] as String[]), inputClass = "", placeholder = "Search..."}:
{displayed: boolean, onSelected: Function, getList: (searchTerm: string) => Promise<String[]>, inputClass?: string, placeholder?: string} = $props();
let items: String[] = $state([]);
let searchTerm = $state('');
Expand Down Expand Up @@ -74,12 +73,12 @@
</script>

{#if displayed}
<div class="relative w-32 mx-auto">
<div class={"relative " + inputClass}>
<input
type="text"
id="search"
placeholder="Search..."
class="w-full px-3 py-1 input"
placeholder={placeholder}
class="w-full h-full px-3 py-1 input"
bind:value={searchTerm}
oninput={handleInput}
onfocus={handleFocus}
Expand Down
Empty file removed src/lib/server/lucia.ts
Empty file.
3 changes: 2 additions & 1 deletion src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { setModeCurrent, setModeUserPrefers, modeCurrent } from '@skeletonlabs/skeleton';
import { onMount } from 'svelte';
import errorStore from '$lib/errorStore';
import { getProfilePicture } from '$lib/functions';
let navHeight = 2;
let { data, children } = $props();
Expand Down Expand Up @@ -87,7 +88,7 @@
<a href="/user" aria-label="Get to the Users page!"
><Avatar
initials={getInitials()}
src={getPictureUrl()}
src={getProfilePicture(user)}
background="bg-primary-500"
width="w-11"
link
Expand Down
Loading

0 comments on commit 8713cad

Please sign in to comment.