From 9c0058f1c3775465cfa8eaeb177945ad741fbca0 Mon Sep 17 00:00:00 2001 From: Mawoka Date: Sun, 11 Jun 2023 20:10:53 +0200 Subject: [PATCH] :sparkles: Improved file uploader; uploads from the library can be selected --- classquiz/routers/storage.py | 17 +++ frontend/src/lib/editor/card.svelte | 2 +- frontend/src/lib/editor/uploader.svelte | 112 +++++++++++++----- .../src/lib/editor/uploader/Library.svelte | 62 ++++++++++ frontend/src/lib/quiz_types.ts | 16 +++ frontend/src/routes/edit/files/+page.ts | 19 +-- 6 files changed, 183 insertions(+), 45 deletions(-) create mode 100644 frontend/src/lib/editor/uploader/Library.svelte diff --git a/classquiz/routers/storage.py b/classquiz/routers/storage.py index 35672fc..c7d6ae5 100644 --- a/classquiz/routers/storage.py +++ b/classquiz/routers/storage.py @@ -222,6 +222,23 @@ async def list_images( return return_items +@router.get("/list/last") +async def get_latest_images(count: int = 50, user: User = Depends(get_current_user)) -> list[PrivateStorageItem]: + if count > 50: + count = 50 + items = ( + await StorageItem.objects.filter(user=user) + .limit(count) + .select_related([StorageItem.quizzes, StorageItem.quiztivities]) + .order_by(StorageItem.uploaded_at.desc()) + .all() + ) + return_items: list[PrivateStorageItem] = [] + for item in items: + return_items.append(PrivateStorageItem.from_db_model(item)) + return return_items + + class ReturnGetStorageLimit(BaseModel): limit: int limit_reached: bool diff --git a/frontend/src/lib/editor/card.svelte b/frontend/src/lib/editor/card.svelte index a5028c3..d4c6b4d 100644 --- a/frontend/src/lib/editor/card.svelte +++ b/frontend/src/lib/editor/card.svelte @@ -70,7 +70,7 @@
-
+
{ + if (e.target === e.currentTarget) { + modalOpen = false; + selected_type = null; + } + }; + onMount(() => { + window.addEventListener('keydown', (e: KeyboardEvent) => { + if (e.key === 'Escape') { + modalOpen = false; + selected_type = null; + } + }); + }); {#if modalOpen}
-
-
- - {#if video_upload} - - {/if} -
- {#if video_popup} -
-

Popup open

+ {#if selected_type === null} +
+

Select the Upload Type

+
+
+ { + selected_type = AvailableUploadTypes.Image; + }}>Image +
+
+ { + selected_type = AvailableUploadTypes.Video; + }} + >Video + +
+
+ { + selected_type = AvailableUploadTypes.Library; + }} + >Library + +
- {:else} +
+ {:else if selected_type === AvailableUploadTypes.Image} +
- {/if} -
+
+ {:else if selected_type === AvailableUploadTypes.Video} +
+

Upload a Video

+ {#if video_popup} +

+ The popup is open; have a look at it for further information +

+ {:else} + Upload video + {/if} +
+ {:else if selected_type === AvailableUploadTypes.Library} +
+ +
+ {/if}
{/if}
diff --git a/frontend/src/lib/editor/uploader/Library.svelte b/frontend/src/lib/editor/uploader/Library.svelte new file mode 100644 index 0000000..2b703dd --- /dev/null +++ b/frontend/src/lib/editor/uploader/Library.svelte @@ -0,0 +1,62 @@ + + + + +{#await image_fetch} + +{:then images} +
+
+ {#each images as image} +
+
+ {image.alt_text} +
+

{image.filename ?? 'No name available'}

+ { + set_image(image.id); + }}>Select +
+ {/each} +
+
+{/await} diff --git a/frontend/src/lib/quiz_types.ts b/frontend/src/lib/quiz_types.ts index 03bb640..614c6ac 100644 --- a/frontend/src/lib/quiz_types.ts +++ b/frontend/src/lib/quiz_types.ts @@ -88,3 +88,19 @@ export interface EditorData { background_color?: string; background_image?: string; } + +export interface PrivateImageData { + id: string; + uploaded_at: string; + mime_type: string; + hash?: string; + size?: number; + deleted_at?: string; + alt_text?: string; + filename?: string; + thumbhash?: string; + server?: string; + imported: boolean; + quizzes: { id: string }[]; + quiztivities: { id: string }[]; +} diff --git a/frontend/src/routes/edit/files/+page.ts b/frontend/src/routes/edit/files/+page.ts index e663cff..fae735a 100644 --- a/frontend/src/routes/edit/files/+page.ts +++ b/frontend/src/routes/edit/files/+page.ts @@ -4,26 +4,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { PageLoad } from './$types'; - -export interface ImageData { - id: string; - uploaded_at: string; - mime_type: string; - hash?: string; - size?: number; - deleted_at?: string; - alt_text?: string; - filename?: string; - thumbhash?: string; - server?: string; - imported: boolean; - quizzes: { id: string }[]; - quiztivities: { id: string }[]; -} +import type { PrivateImageData } from '$lib/quiz_types'; export const load = (async ({ fetch }) => { const res = await fetch('/api/v1/storage/list'); - const json: ImageData[] = await res.json(); + const json: PrivateImageData[] = await res.json(); return { images: json };