From dc3a404a5b774fcb50251c35240bf1c44fb3da6a Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 29 Nov 2024 01:52:19 +0100 Subject: [PATCH] add feedback endpoint (#28) and some other stuff --- src/lib/components/Input/Input.svelte | 2 + src/lib/permissions.ts | 56 ++---- src/lib/server/database.ts | 21 +- src/lib/stores.ts | 1 + src/routes/admin/+layout.server.ts | 14 +- src/routes/admin/+layout.svelte | 19 +- src/routes/admin/+page.svelte | 12 +- src/routes/admin/admin/+page.server.ts | 2 +- src/routes/admin/admin/+page.svelte | 55 ++---- src/routes/admin/admin/+server.ts | 6 +- src/routes/admin/feedback/+page.svelte | 180 ++++++++++++++++++ src/routes/admin/feedback/+server.ts | 50 +++++ src/routes/admin/feedback/HeaderBar.svelte | 21 ++ src/routes/admin/feedback/schema.ts | 13 ++ src/routes/admin/reports/+server.ts | 7 +- src/routes/admin/settings/+page.server.ts | 2 +- src/routes/admin/settings/+server.ts | 2 +- src/routes/admin/users/+page.server.ts | 2 +- src/routes/admin/users/+server.ts | 8 +- src/routes/api/feedback/+server.ts | 50 +++++ src/routes/api/feedback/schema.ts | 6 + src/routes/api/report/+server.ts | 4 +- src/routes/feedback/+page.ts | 7 + .../feedback/[...url_hash]/+layout.svelte | 3 + .../feedback/[...url_hash]/+page.server.ts | 18 ++ .../feedback/[...url_hash]/+page.svelte | 30 +++ src/routes/feedback/[...url_hash]/+server.ts | 24 +++ .../[...url_hash]/FeedbackDraft.svelte | 78 ++++++++ .../[...url_hash]/FeedbackSent.svelte | 4 + src/routes/feedback/[...url_hash]/schema.ts | 6 + 30 files changed, 599 insertions(+), 104 deletions(-) create mode 100644 src/routes/admin/feedback/+page.svelte create mode 100644 src/routes/admin/feedback/+server.ts create mode 100644 src/routes/admin/feedback/HeaderBar.svelte create mode 100644 src/routes/admin/feedback/schema.ts create mode 100644 src/routes/api/feedback/+server.ts create mode 100644 src/routes/api/feedback/schema.ts create mode 100644 src/routes/feedback/+page.ts create mode 100644 src/routes/feedback/[...url_hash]/+layout.svelte create mode 100644 src/routes/feedback/[...url_hash]/+page.server.ts create mode 100644 src/routes/feedback/[...url_hash]/+page.svelte create mode 100644 src/routes/feedback/[...url_hash]/+server.ts create mode 100644 src/routes/feedback/[...url_hash]/FeedbackDraft.svelte create mode 100644 src/routes/feedback/[...url_hash]/FeedbackSent.svelte create mode 100644 src/routes/feedback/[...url_hash]/schema.ts diff --git a/src/lib/components/Input/Input.svelte b/src/lib/components/Input/Input.svelte index cdd9563..d9e52b3 100644 --- a/src/lib/components/Input/Input.svelte +++ b/src/lib/components/Input/Input.svelte @@ -11,6 +11,7 @@ export let required = false; export let disabled = false; export let readonly = false; + export let checked = false; export let size: 'xs' | 'sm' | 'md' | 'lg' = 'md'; export let pickyWidth = true; export let containerClass = ''; @@ -85,6 +86,7 @@ {name} {type} {value} + {checked} {placeholder} {required} {disabled} diff --git a/src/lib/permissions.ts b/src/lib/permissions.ts index 96dbab3..c1f441c 100644 --- a/src/lib/permissions.ts +++ b/src/lib/permissions.ts @@ -1,12 +1,9 @@ export class Permissions { - static readonly AdminRead = 2; - static readonly AdminWrite = 4; - static readonly UserRead = 8; - static readonly UserWrite = 16; - static readonly ReportRead = 32; - static readonly ReportWrite = 64; - static readonly SettingsRead = 128; - static readonly SettingsWrite = 256; + static readonly Admin = 2 << 0; + static readonly Users = 2 << 1; + static readonly Reports = 2 << 2; + static readonly Feedback = 2 << 3; + static readonly Settings = 2 << 4; readonly value: number; @@ -30,40 +27,29 @@ export class Permissions { static allPermissions(): number[] { return [ - Permissions.AdminRead, - Permissions.AdminWrite, - Permissions.UserRead, - Permissions.UserWrite, - Permissions.ReportRead, - Permissions.ReportWrite, - Permissions.SettingsRead, - Permissions.SettingsWrite + Permissions.Admin, + Permissions.Users, + Permissions.Reports, + Permissions.Feedback, + Permissions.Settings ]; } - adminRead(): boolean { - return (this.value & Permissions.AdminRead) != 0; + admin(): boolean { + return (this.value & Permissions.Admin) != 0; } - adminWrite(): boolean { - return (this.value & Permissions.AdminWrite) != 0; + + users(): boolean { + return (this.value & Permissions.Users) != 0; } - userRead(): boolean { - return (this.value & Permissions.UserRead) != 0; + reports(): boolean { + return (this.value & Permissions.Reports) != 0; } - userWrite(): boolean { - return (this.value & Permissions.UserWrite) != 0; + feedback(): boolean { + return (this.value & Permissions.Reports) != 0; } - reportRead(): boolean { - return (this.value & Permissions.ReportRead) != 0; - } - reportWrite(): boolean { - return (this.value & Permissions.ReportWrite) != 0; - } - settingsRead(): boolean { - return (this.value & Permissions.SettingsRead) != 0; - } - settingsWrite(): boolean { - return (this.value & Permissions.SettingsWrite) != 0; + settings(): boolean { + return (this.value & Permissions.Reports) != 0; } asArray(): number[] { diff --git a/src/lib/server/database.ts b/src/lib/server/database.ts index bcb58e7..d95f736 100644 --- a/src/lib/server/database.ts +++ b/src/lib/server/database.ts @@ -1,4 +1,4 @@ -import { DataTypes } from 'sequelize'; +import { DataTypes, Op } from 'sequelize'; import { env } from '$env/dynamic/private'; import { building, dev } from '$app/environment'; import * as bcrypt from 'bcrypt'; @@ -97,6 +97,23 @@ export class StrikePunishment extends Model { declare punishment_in_seconds: number; } +@Table({ modelName: 'feedback', underscored: true }) +export class Feedback extends Model { + @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) + @Index + declare url_hash: string; + @Column({ type: DataTypes.STRING, allowNull: false }) + declare event: string; + @Column({ type: DataTypes.STRING }) + declare content: string; + @Column({ type: DataTypes.INTEGER }) + @ForeignKey(() => User) + declare user_id: number; + + @BelongsTo(() => User, 'user_id') + declare user: User; +} + @Table({ modelName: 'admin', underscored: true }) export class Admin extends Model { @Column({ type: DataTypes.STRING, allowNull: false, unique: true }) @@ -148,5 +165,5 @@ export class Settings extends Model { export const sequelize = new Sequelize(building ? 'sqlite::memory:' : env.DATABASE_URI, { // only log sql queries in dev mode logging: dev ? console.log : false, - models: [User, Report, StrikeReason, StrikePunishment, Admin, Settings] + models: [User, Report, StrikeReason, StrikePunishment, Feedback, Admin, Settings] }); diff --git a/src/lib/stores.ts b/src/lib/stores.ts index 7dc15dc..2827015 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -13,4 +13,5 @@ export const errorMessage: Writable = (() => { }; })(); export const reportCount: Writable = writable(0); +export const feedbackCount: Writable = writable(0); export const adminCount: Writable = writable(0); diff --git a/src/routes/admin/+layout.server.ts b/src/routes/admin/+layout.server.ts index 1de97d0..1b59655 100644 --- a/src/routes/admin/+layout.server.ts +++ b/src/routes/admin/+layout.server.ts @@ -1,8 +1,9 @@ import type { LayoutServerLoad } from './$types'; -import { Admin, Report, User } from '$lib/server/database'; +import { Admin, Feedback, Report, User } from '$lib/server/database'; import { getSession } from '$lib/server/session'; import { redirect } from '@sveltejs/kit'; import { env } from '$env/dynamic/public'; +import { Op } from 'sequelize'; export const load: LayoutServerLoad = async ({ route, cookies }) => { const session = getSession(cookies); @@ -11,12 +12,15 @@ export const load: LayoutServerLoad = async ({ route, cookies }) => { throw redirect(302, `${env.PUBLIC_BASE_PATH}/admin/login`); return { - userCount: session?.permissions.userRead() ? await User.count() : null, - reportCount: session?.permissions.reportRead() + userCount: session?.permissions.users() ? await User.count() : null, + reportCount: session?.permissions.reports() ? await Report.count({ where: { draft: false, status: ['none', 'review'] } }) : null, - adminCount: session?.permissions.adminRead() ? await Admin.count() : null, - settingsRead: session?.permissions.settingsRead(), + feedbackCount: session?.permissions.feedback() + ? await Feedback.count({ where: { content: { [Op.not]: null } } }) + : null, + adminCount: session?.permissions.admin() ? await Admin.count() : null, + settingsRead: session?.permissions.settings(), self: session ? JSON.parse(JSON.stringify(await Admin.findOne({ where: { id: session.userId } }))) : null diff --git a/src/routes/admin/+layout.svelte b/src/routes/admin/+layout.svelte index 9ff6307..c3bb9ba 100644 --- a/src/routes/admin/+layout.svelte +++ b/src/routes/admin/+layout.svelte @@ -1,11 +1,18 @@ + +
+
+ +
+ + + + + + + + + + + await fetchFeedback().then((res) => (feedback = [...feedback, ...res]))} + > + {#each feedback as feedback} + { + goto(`${window.location.href.split('#')[0]}#${feedback.url_hash}`, { + replaceState: true + }); + activeFeedback = feedback; + }} + > + + + + + + {/each} + +
EventNutzerDatumInhalt
{feedback.event} + {feedback.user?.username || ''} + {#if feedback.user} + + {/if} + {new Intl.DateTimeFormat('de-DE', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }).format(new Date(feedback.updatedAt))} Uhr{feedback.content}...
+
+ {#if activeFeedback} +
+
+ + +
+

Feedback

+
+ + Nutzer + +