make feedback title optional
All checks were successful
delpoy / build-and-deploy (push) Successful in 54s

This commit is contained in:
bytedream 2024-12-27 19:00:22 +01:00
parent 1596fb605e
commit 8d8b1c52c0
8 changed files with 40 additions and 13 deletions

View File

@ -113,6 +113,8 @@ export class Feedback extends Model {
@Column({ type: DataTypes.STRING, allowNull: false }) @Column({ type: DataTypes.STRING, allowNull: false })
declare event: string; declare event: string;
@Column({ type: DataTypes.STRING }) @Column({ type: DataTypes.STRING })
declare title: string | null;
@Column({ type: DataTypes.STRING })
declare content: string | null; declare content: string | null;
@Column({ type: DataTypes.STRING, allowNull: false, unique: true }) @Column({ type: DataTypes.STRING, allowNull: false, unique: true })
@Index @Index

View File

@ -70,6 +70,7 @@
<thead> <thead>
<tr> <tr>
<th>Event</th> <th>Event</th>
<th>Titel</th>
<th>Nutzer</th> <th>Nutzer</th>
<th>Datum</th> <th>Datum</th>
<th>Inhalt</th> <th>Inhalt</th>
@ -91,6 +92,7 @@
}} }}
> >
<td title={feedback.event}>{feedback.event}</td> <td title={feedback.event}>{feedback.event}</td>
<td class="overflow-hidden overflow-ellipsis">{feedback.title}</td>
<td class="flex"> <td class="flex">
{feedback.user?.username || ''} {feedback.user?.username || ''}
{#if feedback.user} {#if feedback.user}
@ -116,7 +118,9 @@
minute: '2-digit' minute: '2-digit'
}).format(new Date(feedback.updatedAt))} Uhr</td }).format(new Date(feedback.updatedAt))} Uhr</td
> >
<td>{feedback.content}...</td> <td class="overflow-hidden overflow-ellipsis"
>{feedback.content}{feedback.content_stripped ? '...' : ''}</td
>
</tr> </tr>
{/each} {/each}
</PaginationTableBody> </PaginationTableBody>
@ -167,6 +171,18 @@
</div> </div>
<h3 class="font-roboto font-semibold text-2xl mb-2">Feedback</h3> <h3 class="font-roboto font-semibold text-2xl mb-2">Feedback</h3>
<div class="w-full"> <div class="w-full">
<Input readonly={true} size="sm" value={activeFeedback.event} pickyWidth={false}>
{#snippet label()}
<span>Event</span>
{/snippet}
</Input>
<Input readonly={true} size="sm" value={activeFeedback.title} pickyWidth={false}>
{#snippet label()}
<span>Titel</span>
{/snippet}
</Input>
<Textarea readonly={true} rows={4} label="Inhalt" value={activeFeedback.content} />
<div class="divider mb-1"></div>
<Input <Input
readonly={true} readonly={true}
size="sm" size="sm"
@ -177,7 +193,6 @@
<span>Nutzer</span> <span>Nutzer</span>
{/snippet} {/snippet}
</Input> </Input>
<Textarea readonly={true} rows={4} label="Inhalt" value={activeFeedback.content} />
</div> </div>
</div> </div>
{/if} {/if}

View File

@ -42,7 +42,10 @@ export const POST = (async ({ request, cookies }) => {
attributes: data.preview attributes: data.preview
? { ? {
exclude: ['content'], exclude: ['content'],
include: [[sequelize.literal('SUBSTR(content, 1, 50)'), 'content']] include: [
[sequelize.literal('SUBSTR(content, 1, 50)'), 'content'],
[sequelize.literal('LENGTH(content) > 50'), 'content_stripped']
]
} }
: undefined, : undefined,
include: { model: User, as: 'user' }, include: { model: User, as: 'user' },

View File

@ -21,9 +21,10 @@ export const POST = (async ({ request, url }) => {
where: { uuid: data.users }, where: { uuid: data.users },
attributes: ['id', 'uuid'] attributes: ['id', 'uuid']
})) { })) {
feedback[user.uuid] = { feedback[user.uuid!] = {
url_hash: crypto.randomBytes(18).toString('hex'), url_hash: crypto.randomBytes(18).toString('hex'),
event: data.event, event: data.event,
title: data.title ?? null,
draft: true, draft: true,
user_id: user.id user_id: user.id
}; };

View File

@ -2,5 +2,6 @@ import { z } from 'zod';
export const FeedbackAddSchema = z.object({ export const FeedbackAddSchema = z.object({
event: z.string(), event: z.string(),
title: z.string().nullish(),
users: z.array(z.string()) users: z.array(z.string())
}); });

View File

@ -12,7 +12,7 @@ export const load: PageServerLoad = async ({ params }) => {
return { return {
draft: feedback.content === null, draft: feedback.content === null,
event: feedback.event, title: feedback.title,
anonymous: feedback.user_id === null anonymous: feedback.user_id === null
}; };
}; };

View File

@ -16,7 +16,7 @@
{#if draft} {#if draft}
<div class="col-[1] row-[1]" transition:fly={{ x: -200, duration: 300 }}> <div class="col-[1] row-[1]" transition:fly={{ x: -200, duration: 300 }}>
<FeedbackDraft event={data.event} anonymous={data.anonymous} onSubmit={() => (draft = false)} /> <FeedbackDraft title={data.title} anonymous={data.anonymous} onSubmit={() => (draft = false)} />
</div> </div>
{:else} {:else}
<div class="col-[1] row-[1]" transition:fly={{ x: 200, duration: 300 }}> <div class="col-[1] row-[1]" transition:fly={{ x: 200, duration: 300 }}>

View File

@ -5,8 +5,11 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
import { getPopupModalShowFn } from '$lib/context'; import { getPopupModalShowFn } from '$lib/context';
let { event, anonymous, onSubmit }: { event: string; anonymous: boolean; onSubmit?: () => void } = let {
$props(); title,
anonymous,
onSubmit
}: { title: string | null; anonymous: boolean; onSubmit?: () => void } = $props();
let showPopupModal = getPopupModalShowFn(); let showPopupModal = getPopupModalShowFn();
@ -47,11 +50,13 @@
}} }}
> >
<div class="space-y-4 my-4"> <div class="space-y-4 my-4">
<Input size="sm" pickyWidth={false} disabled value={event}> {#if title}
<Input size="sm" pickyWidth={false} disabled value={title}>
{#snippet label()} {#snippet label()}
<span>Event</span> <span>Event</span>
{/snippet} {/snippet}
</Input> </Input>
{/if}
<Textarea required={true} rows={4} label="Feedback" bind:value={content} /> <Textarea required={true} rows={4} label="Feedback" bind:value={content} />
{#if !anonymous} {#if !anonymous}
<div class="flex items-center gap-2 mt-2"> <div class="flex items-center gap-2 mt-2">