From a230be21c30187563971fd90a709e1fc1772307a Mon Sep 17 00:00:00 2001 From: Liam Keegan Date: Thu, 26 Sep 2024 09:31:51 +0200 Subject: [PATCH] Add initial support for user questions - backend - add models/questions with UserQuestion and UserQuestionText - add /user-questions endpoint to get list of questions - add /admin/user-questions endpoints to create, update and delete questions - admin frontend - add UserQuestions component to edit list of questions - only support text and select inputs for now - refactor admin frontend --- frontend/src/lib/admin.ts | 99 ++++++++++++- .../src/lib/components/Admin/AddButton.svelte | 12 ++ .../lib/components/Admin/DeleteButton.svelte | 11 ++ ...neGroupModal.svelte => DeleteModal.svelte} | 18 +-- .../lib/components/Admin/EditButton.svelte | 11 ++ .../Admin/EditMilestoneGroupModal.svelte | 2 +- .../Admin/EditUserQuestionModal.svelte | 139 ++++++++++++++++++ .../lib/components/Admin/InputPreview.svelte | 30 ++++ .../src/lib/components/Admin/Languages.svelte | 38 +++-- .../components/Admin/MilestoneGroups.svelte | 47 +++--- .../lib/components/Admin/UserQuestions.svelte | 100 +++++++++++++ frontend/src/lib/stores/adminStore.ts | 2 + frontend/src/locales/de.json | 9 +- frontend/src/locales/en.json | 9 +- frontend/src/routes/admin/+page.svelte | 44 +++++- mondey_backend/src/mondey_backend/main.py | 2 + .../src/mondey_backend/models/milestones.py | 2 - .../src/mondey_backend/models/questions.py | 54 +++++++ .../src/mondey_backend/routers/admin.py | 48 +++++- .../src/mondey_backend/routers/questions.py | 24 +++ .../src/mondey_backend/routers/users.py | 1 + .../src/mondey_backend/routers/utils.py | 11 +- mondey_backend/src/mondey_backend/settings.py | 2 +- 23 files changed, 647 insertions(+), 68 deletions(-) create mode 100644 frontend/src/lib/components/Admin/AddButton.svelte create mode 100644 frontend/src/lib/components/Admin/DeleteButton.svelte rename frontend/src/lib/components/Admin/{DeleteMilestoneGroupModal.svelte => DeleteModal.svelte} (57%) create mode 100644 frontend/src/lib/components/Admin/EditButton.svelte create mode 100644 frontend/src/lib/components/Admin/EditUserQuestionModal.svelte create mode 100644 frontend/src/lib/components/Admin/InputPreview.svelte create mode 100644 frontend/src/lib/components/Admin/UserQuestions.svelte create mode 100644 mondey_backend/src/mondey_backend/models/questions.py create mode 100644 mondey_backend/src/mondey_backend/routers/questions.py diff --git a/frontend/src/lib/admin.ts b/frontend/src/lib/admin.ts index 1877456b..dd32d488 100644 --- a/frontend/src/lib/admin.ts +++ b/frontend/src/lib/admin.ts @@ -1,4 +1,4 @@ -import { milestoneGroups } from '$lib/stores/adminStore'; +import { milestoneGroups, userQuestions } from '$lib/stores/adminStore'; export async function refreshMilestoneGroups() { console.log('refreshMilestoneGroups...'); @@ -54,7 +54,7 @@ export async function updateMilestoneGroup(milestoneGroup) { console.log('updateMilestoneGroup...'); console.log(milestoneGroup); try { - const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-groups`, { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-groups/`, { method: 'PUT', credentials: 'include', headers: { @@ -125,3 +125,98 @@ export async function deleteMilestoneGroup(milestoneGroupId: number | null) { export function milestoneGroupImageUrl(id: number) { return `${import.meta.env.VITE_MONDEY_API_URL}/static/mg${id}.jpg`; } + +export async function refreshUserQuestions() { + console.log('refreshQuestions...'); + try { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/user-questions/`, { + method: 'GET', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }); + const json = await res.json(); + console.log(json); + if (res.status === 200) { + userQuestions.set(json); + } else { + console.log('Failed to get UserQuestions'); + userQuestions.set([]); + } + } catch (e) { + console.error(e); + userQuestions.set([]); + } +} + +export async function newUserQuestion() { + try { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/user-questions/`, { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json' + } + }); + if (res.status === 200) { + const newUserQuestion = await res.json(); + console.log(newUserQuestion); + await refreshUserQuestions(); + return newUserQuestion; + } else { + console.log('Failed to create new Question'); + } + } catch (e) { + console.error(e); + } +} + +export async function updateUserQuestion(userQuestion) { + console.log('updateUserQuestion...'); + console.log(userQuestion); + try { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/user-questions/`, { + method: 'PUT', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify(userQuestion) + }); + if (res.status === 200) { + const updatedUserQuestion = await res.json(); + console.log(updatedUserQuestion); + await refreshUserQuestions(); + return updatedUserQuestion; + } else { + console.log('Failed to create new UserQuestion'); + } + } catch (e) { + console.error(e); + } + return null; +} + +export async function deleteUserQuestion(id: number) { + try { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/user-questions/${id}`, { + method: 'DELETE', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + }); + if (res.status === 200) { + await refreshUserQuestions(); + } else { + console.log('Failed to delete Question'); + } + } catch (e) { + console.error(e); + } + return null; +} diff --git a/frontend/src/lib/components/Admin/AddButton.svelte b/frontend/src/lib/components/Admin/AddButton.svelte new file mode 100644 index 00000000..4047d2d9 --- /dev/null +++ b/frontend/src/lib/components/Admin/AddButton.svelte @@ -0,0 +1,12 @@ + + + diff --git a/frontend/src/lib/components/Admin/DeleteButton.svelte b/frontend/src/lib/components/Admin/DeleteButton.svelte new file mode 100644 index 00000000..ed5fdc43 --- /dev/null +++ b/frontend/src/lib/components/Admin/DeleteButton.svelte @@ -0,0 +1,11 @@ + + + diff --git a/frontend/src/lib/components/Admin/DeleteMilestoneGroupModal.svelte b/frontend/src/lib/components/Admin/DeleteModal.svelte similarity index 57% rename from frontend/src/lib/components/Admin/DeleteMilestoneGroupModal.svelte rename to frontend/src/lib/components/Admin/DeleteModal.svelte index f678fa84..0da3ba1d 100644 --- a/frontend/src/lib/components/Admin/DeleteMilestoneGroupModal.svelte +++ b/frontend/src/lib/components/Admin/DeleteModal.svelte @@ -1,25 +1,21 @@

- Are you sure you want to delete this MilestoneGroup? + {$_('admin.delete-are-you-sure')}

- - + +
diff --git a/frontend/src/lib/components/Admin/EditButton.svelte b/frontend/src/lib/components/Admin/EditButton.svelte new file mode 100644 index 00000000..899133fa --- /dev/null +++ b/frontend/src/lib/components/Admin/EditButton.svelte @@ -0,0 +1,11 @@ + + + diff --git a/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte b/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte index b9cfa6f6..166db5ce 100644 --- a/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte +++ b/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte @@ -9,7 +9,7 @@ Fileupload, Modal } from 'flowbite-svelte'; - import { lang_id, languages } from '$lib/stores/adminStore'; + import { languages } from '$lib/stores/adminStore'; import { updateMilestoneGroup, uploadMilestoneGroupImage, diff --git a/frontend/src/lib/components/Admin/EditUserQuestionModal.svelte b/frontend/src/lib/components/Admin/EditUserQuestionModal.svelte new file mode 100644 index 00000000..82af7f3f --- /dev/null +++ b/frontend/src/lib/components/Admin/EditUserQuestionModal.svelte @@ -0,0 +1,139 @@ + + + + {#if userQuestion} +
+
+
+ + {#each Object.values(userQuestion.text) as text} +
+ + {$languages[text.lang_id]} + { + userQuestion = userQuestion; + }} + placeholder="Question" + /> + +
+ {/each} +
+
+ +