From 1744f2a63b77c20eacdd996416cfbd8455a6dcb4 Mon Sep 17 00:00:00 2001 From: Liam Keegan Date: Wed, 25 Sep 2024 15:57:11 +0200 Subject: [PATCH] Add milestones to backend - add/update Milestone, MilestoneText, MilestoneImage models - add admin endpoints to create / update / delete milestones Make endpoint naming more consistent - use plurals for all collections of entities - use PUT instead of PATCH since these endpoints take the entire entity, not just selected fields to update Refactor - use factory pattern for app and routers to make it easier to modify app settings in tests - extract common router code into utils - extend and refactor backend tests --- frontend/src/lib/admin.ts | 18 +- .../Admin/EditMilestoneGroupModal.svelte | 17 +- .../src/lib/components/Admin/Languages.svelte | 4 +- .../components/Admin/MilestoneGroups.svelte | 4 +- .../Admin/NewMilestoneGroupModal.svelte | 108 ----- frontend/src/lib/stores/adminStore.ts | 4 +- mondey_backend/src/mondey_backend/main.py | 39 +- .../src/mondey_backend/models/milestones.py | 77 ++-- .../src/mondey_backend/routers/admin.py | 267 +++++------ .../src/mondey_backend/routers/auth.py | 13 +- .../src/mondey_backend/routers/milestones.py | 94 ++-- .../src/mondey_backend/routers/users.py | 7 +- .../src/mondey_backend/routers/utils.py | 68 +++ mondey_backend/src/mondey_backend/settings.py | 4 + mondey_backend/tests/conftest.py | 423 +++++++++++++++++- mondey_backend/tests/routers/test_admin.py | 188 +++++--- .../tests/routers/test_milestones.py | 50 +-- 17 files changed, 891 insertions(+), 494 deletions(-) delete mode 100644 frontend/src/lib/components/Admin/NewMilestoneGroupModal.svelte create mode 100644 mondey_backend/src/mondey_backend/routers/utils.py diff --git a/frontend/src/lib/admin.ts b/frontend/src/lib/admin.ts index f6bdcb06..1877456b 100644 --- a/frontend/src/lib/admin.ts +++ b/frontend/src/lib/admin.ts @@ -28,7 +28,7 @@ export async function refreshMilestoneGroups() { export async function newMilestoneGroup() { console.log('newMilestoneGroup...'); try { - const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-group/`, { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-groups/`, { method: 'POST', credentials: 'include', headers: { @@ -50,12 +50,12 @@ export async function newMilestoneGroup() { return null; } -export async function patchMilestoneGroup(milestoneGroup) { - console.log('patchMilestoneGroup...'); +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-group`, { - method: 'PATCH', + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-groups`, { + method: 'PUT', credentials: 'include', headers: { 'Content-Type': 'application/json', @@ -83,9 +83,9 @@ export async function uploadMilestoneGroupImage(milestoneGroupId: number, file) const formData = new FormData(); formData.append('file', file); const res = await fetch( - `${import.meta.env.VITE_MONDEY_API_URL}/admin/upload-milestone-group-image/${milestoneGroupId}`, + `${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-group-images/${milestoneGroupId}`, { - method: 'POST', + method: 'PUT', credentials: 'include', body: formData } @@ -121,3 +121,7 @@ export async function deleteMilestoneGroup(milestoneGroupId: number | null) { console.error(e); } } + +export function milestoneGroupImageUrl(id: number) { + return `${import.meta.env.VITE_MONDEY_API_URL}/static/mg${id}.jpg`; +} diff --git a/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte b/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte index 8f9db1b7..b9cfa6f6 100644 --- a/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte +++ b/frontend/src/lib/components/Admin/EditMilestoneGroupModal.svelte @@ -10,7 +10,11 @@ Modal } from 'flowbite-svelte'; import { lang_id, languages } from '$lib/stores/adminStore'; - import { patchMilestoneGroup, uploadMilestoneGroupImage } from '$lib/admin'; + import { + updateMilestoneGroup, + uploadMilestoneGroupImage, + milestoneGroupImageUrl + } from '$lib/admin'; export let open: boolean = false; export let milestoneGroup: object | null = null; @@ -19,7 +23,7 @@ let image: string | ArrayBuffer | null | undefined = null; $: if (milestoneGroup !== null) { - image = `${import.meta.env.VITE_MONDEY_API_URL}/static/milestone_group_${milestoneGroup.id}.jpg`; + image = milestoneGroupImageUrl(milestoneGroup.id); } $: if (files) { @@ -30,20 +34,17 @@ }; } - async function reloadImg(url) { - console.log(`Reloading ${url}`); + async function reloadImg(url: string) { await fetch(url, { cache: 'reload', mode: 'no-cors' }); document.body.querySelectorAll(`img[src='${url}']`).forEach((img) => (img.src = url)); } export async function saveChanges() { try { - await patchMilestoneGroup(milestoneGroup); + await updateMilestoneGroup(milestoneGroup); if (files) { await uploadMilestoneGroupImage(milestoneGroup.id, files[0]); - reloadImg( - `${import.meta.env.VITE_MONDEY_API_URL}/static/milestone_group_${milestoneGroup.id}.jpg` - ); + await reloadImg(milestoneGroupImageUrl(milestoneGroup.id)); } } catch (e) { console.error(e); diff --git a/frontend/src/lib/components/Admin/Languages.svelte b/frontend/src/lib/components/Admin/Languages.svelte index 6ad1a4cd..56c4c37c 100644 --- a/frontend/src/lib/components/Admin/Languages.svelte +++ b/frontend/src/lib/components/Admin/Languages.svelte @@ -27,7 +27,7 @@ async function newLanguage() { try { - const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/language`, { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/languages`, { method: 'POST', credentials: 'include', headers: { @@ -48,7 +48,7 @@ async function deleteLanguage(id: string) { try { - const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/language/${id}`, { + const res = await fetch(`${import.meta.env.VITE_MONDEY_API_URL}/admin/languages/${id}`, { method: 'DELETE', credentials: 'include', headers: { diff --git a/frontend/src/lib/components/Admin/MilestoneGroups.svelte b/frontend/src/lib/components/Admin/MilestoneGroups.svelte index a022e28e..69e83907 100644 --- a/frontend/src/lib/components/Admin/MilestoneGroups.svelte +++ b/frontend/src/lib/components/Admin/MilestoneGroups.svelte @@ -14,7 +14,7 @@ import EditMilestoneGroupModal from '$lib/components/Admin/EditMilestoneGroupModal.svelte'; import DeleteMilestoneGroupModal from '$lib/components/Admin/DeleteMilestoneGroupModal.svelte'; import { lang_id, milestoneGroups } from '$lib/stores/adminStore'; - import { refreshMilestoneGroups, newMilestoneGroup } from '$lib/admin'; + import { refreshMilestoneGroups, newMilestoneGroup, milestoneGroupImageUrl } from '$lib/admin'; import { onMount } from 'svelte'; let currentGroup: object | null = null; @@ -77,7 +77,7 @@ {title} - import { - Button, - InputAddon, - Textarea, - Input, - Label, - ButtonGroup, - Fileupload, - Modal - } from 'flowbite-svelte'; - import { FileImageSolid } from 'flowbite-svelte-icons'; - - export let open: boolean = false; - export let milestoneGroupData = { - group: { order: 0 }, - text: [ - { lang: 'en', title: '', desc: '' }, - { lang: 'de', title: '', desc: '' } - ] - }; - let files: FileList; - let image: string | ArrayBuffer | null | undefined = ''; - - $: if (files) { - const reader = new FileReader(); - reader.readAsDataURL(files[0]); - reader.onload = (e) => { - image = e?.target?.result; - }; - } - - async function postMilestoneGroup() { - console.log(milestoneGroupData); - try { - const res_milestone_group = await fetch( - `${import.meta.env.VITE_MONDEY_API_URL}/admin/milestone-groups/`, - { - method: 'POST', - credentials: 'include', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - }, - body: JSON.stringify(milestoneGroupData) - } - ); - const new_milestone_group = await res_milestone_group.json(); - console.log(new_milestone_group); - if (files) { - let formData = new FormData(); - formData.append('file', files[0]); - const res_milestone_group_image = await fetch( - `${import.meta.env.VITE_MONDEY_API_URL}/admin/upload-milestone-group-image/${new_milestone_group.id}`, - { - method: 'POST', - credentials: 'include', - body: formData - } - ); - const new_milestone_group_image = await res_milestone_group_image.json(); - console.log(new_milestone_group_image); - } - } catch (e) { - console.error(e); - } - } - - - -
- - {#each milestoneGroupData.text as text} -
- - {text.lang} - - -
- {/each} -
-
- - {#each milestoneGroupData.text as text} -
- - {text.lang} -