From 7b3ca1bcf087cf2a537eb555be03af699874ee92 Mon Sep 17 00:00:00 2001 From: MangoSwirl Date: Thu, 6 Jun 2024 00:47:26 -0700 Subject: [PATCH] Fix person editor --- package-lock.json | 11 +- package.json | 3 +- src/lib/util/person/role/roles.ts | 2 +- src/routes/tools/people/+page.server.ts | 2 +- src/routes/tools/people/[id]/+page.server.ts | 60 +++++- .../tools/people/[id]/ProfileCard.svelte | 181 +++++++++++++++--- 6 files changed, 231 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd53905..5f12ceb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,8 @@ "dotenv": "^16.3.1", "magnolia-ui-svelte": "github:highlanderrobotics/magnolia-ui-svelte#production", "pngjs": "^7.0.0", - "sqlite3": "^5.1.6" + "sqlite3": "^5.1.6", + "zod": "^3.23.8" }, "devDependencies": { "@prgm/sveltekit-progress-bar": "^1.0.1", @@ -5692,6 +5693,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 7a83041..5ede302 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "dotenv": "^16.3.1", "magnolia-ui-svelte": "github:highlanderrobotics/magnolia-ui-svelte#production", "pngjs": "^7.0.0", - "sqlite3": "^5.1.6" + "sqlite3": "^5.1.6", + "zod": "^3.23.8" } } diff --git a/src/lib/util/person/role/roles.ts b/src/lib/util/person/role/roles.ts index dcb0b18..0b95553 100644 --- a/src/lib/util/person/role/roles.ts +++ b/src/lib/util/person/role/roles.ts @@ -3,6 +3,6 @@ export const roles = [ "MENTOR", "SUPERVISOR", "OTHER", -] +] as const; export type RoleString = typeof roles[number]; diff --git a/src/routes/tools/people/+page.server.ts b/src/routes/tools/people/+page.server.ts index 46c0758..c744931 100644 --- a/src/routes/tools/people/+page.server.ts +++ b/src/routes/tools/people/+page.server.ts @@ -64,7 +64,7 @@ export const actions = { if (!name) throw error(400, 'Missing "name" field.'); if (!email) throw error(400, 'Missing "email" field.'); if (!role) throw error(400, 'Missing "role" field.'); - if (!roles.includes(role.toString())) throw error(400, 'Invalid "role" field'); + if (!(role.toString() in roles)) throw error(400, 'Invalid "role" field'); try { await addPerson(name.toString(), email.toString(), role as RoleString, teamAffiliated); diff --git a/src/routes/tools/people/[id]/+page.server.ts b/src/routes/tools/people/[id]/+page.server.ts index d9812d1..6913914 100644 --- a/src/routes/tools/people/[id]/+page.server.ts +++ b/src/routes/tools/people/[id]/+page.server.ts @@ -1,9 +1,12 @@ import { hasPermission } from '$lib/server/util/permission/hasPermission'; -import { error } from '@sveltejs/kit'; +import { error, fail } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; import { getPersonFromUser } from '$lib/server/util/person/getPersonFromUser'; import type { Prisma } from '@prisma/client'; import prisma from '$lib/server/util/prisma'; +import * as z from 'zod'; +import { roles } from '$lib/util/person/role/roles'; +import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'; export const load: PageServerLoad = async ({ params, locals }) => { const session = await locals.getSession(); @@ -57,3 +60,58 @@ export const load: PageServerLoad = async ({ params, locals }) => { person }; }; + +export const actions = { + edit: async (event) => { + const session = await event.locals.getSession(); + if (!session?.user) throw error(500); + + const requester = await getPersonFromUser(session?.user); + if (!requester) throw error(500); + + const canEdit = await hasPermission(requester, 'people.edit'); + + if (!canEdit) { + throw error(403, 'You do not have permission to edit people.'); + } + + const formData = await event.request.formData(); + + // Validate data + const schema = z.object({ + name: z.string().min(1), + role: z.enum(roles), + email: z.string().email(), + teamAffiliated: z.enum(['on', 'off']).optional().transform((value) => value === 'on'), + }); + + try { + const data = schema.parse(Object.fromEntries(formData)); + + await prisma.person.update({ + where: { + id: event.params.id + }, + data + }); + } catch (e) { + console.error(e); + + if (e instanceof z.ZodError) { + const sentError = e.errors[0]; + + return fail(400, { + message: sentError.message, + }); + } + + if (e instanceof PrismaClientKnownRequestError) { + return fail(400, { + message: 'An error occured. Check if the email is already used.', + }); + } + + throw error(500); + } + } +} \ No newline at end of file diff --git a/src/routes/tools/people/[id]/ProfileCard.svelte b/src/routes/tools/people/[id]/ProfileCard.svelte index c138b12..0d9dab8 100644 --- a/src/routes/tools/people/[id]/ProfileCard.svelte +++ b/src/routes/tools/people/[id]/ProfileCard.svelte @@ -1,7 +1,9 @@ -
- {#if canEdit} -
- - - +{#if editing} +
{ + return async ({ result, update }) => { + editSaving = false; + + if (result.type === 'success') { + console.log('success'); + + editing = false; + } else if (result.type === 'failure') { + editError = + typeof result.data?.message === 'string' + ? result.data.message + : 'Failed to save changes.'; + } + + update(); + }; + }} + on:submit={() => (editSaving = true)} + > +
+
+ +
+
+ Profile +
+
+ + +
+
+ + +
+
+ + + +
+ {#if editError} +
{editError}
+ {/if}
- {/if} -
- Profile -
-

{person.name}

-

{localizedRole(person.role)}

+ +{:else} +
+ {#if canEdit} +
+ + + +
+ {/if} +
+ Profile +
+

{person.name}

+

{localizedRole(person.role)}

+
-
-
-
Email
- {person.email} -
-
-
Affiliation
-
- {person.teamAffiliated ? 'Affiliated with 8033' : 'Not affiliated with 8033'} +
+
Email
+ {person.email} +
+
+
Affiliation
+
+ {person.teamAffiliated ? 'Affiliated with 8033' : 'Not affiliated with 8033'} +
-
+{/if}