From d6ad0d2ccd69c5a1dddb6143983c80d2fca9b8f8 Mon Sep 17 00:00:00 2001 From: Markus Brueckner Date: Tue, 7 Jan 2025 21:10:55 +0100 Subject: [PATCH] Survey editing Closes #16 --- src/{lib/queries.ts => db/survey.ts} | 36 ++++++++++ src/lib/components/SurveyEditForm.svelte | 65 +++++++++++++++++ src/lib/components/icons/EditIcon.svelte | 14 ++++ src/lib/survey.ts | 20 ++++++ .../(app)/survey/[surveyId]/+page.server.ts | 26 +------ .../(app)/survey/[surveyId]/+page.svelte | 11 ++- .../survey/[surveyId]/edit/+page.server.ts | 72 +++++++++++++++++++ .../(app)/survey/[surveyId]/edit/+page.svelte | 20 ++++++ src/routes/(app)/survey/new/+page.server.ts | 36 ++++------ src/routes/(app)/survey/new/+page.svelte | 59 +-------------- 10 files changed, 254 insertions(+), 105 deletions(-) rename src/{lib/queries.ts => db/survey.ts} (57%) create mode 100644 src/lib/components/SurveyEditForm.svelte create mode 100644 src/lib/components/icons/EditIcon.svelte create mode 100644 src/lib/survey.ts create mode 100644 src/routes/(app)/survey/[surveyId]/edit/+page.server.ts create mode 100644 src/routes/(app)/survey/[surveyId]/edit/+page.svelte diff --git a/src/lib/queries.ts b/src/db/survey.ts similarity index 57% rename from src/lib/queries.ts rename to src/db/survey.ts index 6835a43..0c88626 100644 --- a/src/lib/queries.ts +++ b/src/db/survey.ts @@ -1,6 +1,12 @@ +import { error } from "@sveltejs/kit"; +import debug from "debug"; + +const log = debug('survey:admin:edit'); + import { eq, and, inArray } from "drizzle-orm"; import { db } from "../db"; import { surveyAccessTable, surveyAnswersTable, surveySkillsTable, surveysTable } from "../db/schema"; +import { generateRandomToken } from "$lib/randomToken"; export async function loadSurvey(id: number, ownerId: number) { const survey = await db.select().from(surveysTable).where(and(eq(surveysTable.id, id), eq(surveysTable.owner, ownerId))).limit(1); @@ -31,4 +37,34 @@ export async function loadSurvey(id: number, ownerId: number) { description: skill.description })) } +} + +export async function loadSurveyData(surveyId: string, userId: number | null) { + const sId = parseInt(surveyId); + + if (isNaN(sId)) { + log('Invalid survey ID %s', surveyId); + error(404, 'Invalid survey ID'); + } + if (!userId) { + log('User is not logged in'); + error(403, 'User is not logged in'); + } + + const surveyData = await loadSurvey(sId, userId); + if (!surveyData) { + log('Survey not found or user (%s) does not have access: %s', userId, surveyId); + error(404, 'Survey not found'); + } + return surveyData; +} + +// add a new participant to a survey +export async function addParticipant(surveyId: number, recepientEmail: string) { + await db.insert(surveyAccessTable).values({ surveyId, recepientEmail, accessToken: generateRandomToken() }); +} + +// add a new skill to a survey +export async function addSkill(surveyId: number, title: string, description: string) { + await db.insert(surveySkillsTable).values({ surveyId, title, description }); } \ No newline at end of file diff --git a/src/lib/components/SurveyEditForm.svelte b/src/lib/components/SurveyEditForm.svelte new file mode 100644 index 0000000..e517284 --- /dev/null +++ b/src/lib/components/SurveyEditForm.svelte @@ -0,0 +1,65 @@ + + +
+ + + + + +

Participants

+ {#each Array(numParticipants) as _, idx} + + + {/each} + + +

Skills

+ {#each Array(numSkills) as _, idx} +
+
+ + +
+
+ + +
+
+ {/each} + + + +
diff --git a/src/lib/components/icons/EditIcon.svelte b/src/lib/components/icons/EditIcon.svelte new file mode 100644 index 0000000..9493590 --- /dev/null +++ b/src/lib/components/icons/EditIcon.svelte @@ -0,0 +1,14 @@ + + + diff --git a/src/lib/survey.ts b/src/lib/survey.ts new file mode 100644 index 0000000..5ccc486 --- /dev/null +++ b/src/lib/survey.ts @@ -0,0 +1,20 @@ + +export function fromFormData(formData: FormData) { + const participants = formData.getAll('participants').filter(email => !!email).map(email => email.toString()); + const title = formData.get('title')?.toString(); + const description = formData.get('description')?.toString(); + const skillTitles = formData.getAll('skill'); + const skillDescriptions = formData.getAll('skill-description'); + + const skills = skillTitles.flatMap((title, index) => !!title ? [({ + title: title.toString(), + description: skillDescriptions[index].toString() + })] : []); + + return { + participants, + title, + description, + skills + } +} \ No newline at end of file diff --git a/src/routes/(app)/survey/[surveyId]/+page.server.ts b/src/routes/(app)/survey/[surveyId]/+page.server.ts index 4a419df..5bf4d19 100644 --- a/src/routes/(app)/survey/[surveyId]/+page.server.ts +++ b/src/routes/(app)/survey/[surveyId]/+page.server.ts @@ -1,39 +1,19 @@ import { error, redirect } from '@sveltejs/kit'; import type { PageServerLoad, RouteParams } from './$types'; -import { loadSurvey } from '$lib/queries'; import debug from 'debug'; import { deleteAnswers } from '../../../../db/answers'; +import { loadSurveyData } from '../../../../db/survey'; const log = debug('survey:admin'); -async function loadSurveyData(params: RouteParams, locals: App.Locals) { - const surveyId = parseInt(params.surveyId); - - if (isNaN(surveyId)) { - log('Invalid survey ID %s', params.surveyId); - error(400, 'Invalid survey ID'); - } - if (!locals.userId) { - log('User is not logged in'); - error(403, 'User is not logged in'); - } - - const surveyData = await loadSurvey(surveyId, locals.userId); - if (!surveyData) { - log('Survey not found or user (%s) does not have access: %s', locals.userId, params.surveyId); - error(404, 'Survey not found'); - } - return surveyData; -} - export const load: PageServerLoad = async ({ params, locals }) => { - return await loadSurveyData(params, locals); + return await loadSurveyData(params.surveyId, locals.userId); } export const actions = { deleteAnswers: async ({ params, locals, request }) => { - const survey = await loadSurveyData(params, locals); + const survey = await loadSurveyData(params.surveyId, locals.userId); let formData = await request.formData(); const participantId = parseInt(formData.get('participantId')?.toString() ?? ''); diff --git a/src/routes/(app)/survey/[surveyId]/+page.svelte b/src/routes/(app)/survey/[surveyId]/+page.svelte index c2863e9..91cc3fb 100644 --- a/src/routes/(app)/survey/[surveyId]/+page.svelte +++ b/src/routes/(app)/survey/[surveyId]/+page.svelte @@ -11,9 +11,9 @@ import { goto } from '$app/navigation'; import { success } from '$lib/toast'; import MarkdownBlock from '$lib/components/MarkdownBlock.svelte'; - import MenuIcon from '$lib/components/icons/MenuIcon.svelte'; import DeleteIcon from '$lib/components/icons/DeleteIcon.svelte'; import WarningDialog from '$lib/components/WarningDialog.svelte'; + import EditIcon from '$lib/components/icons/EditIcon.svelte'; let { data }: { data: PageData } = $props(); @@ -43,7 +43,7 @@ -
+
@@ -54,6 +54,13 @@ title="Duplicate" > + + - -

Skills

- {#each Array(skills) as _, idx} -
-
- - -
-
- - -
-
- {/each} - - - - +