diff --git a/classquiz/routers/quiztivity.py b/classquiz/routers/quiztivity.py
index 7b694da..e725909 100644
--- a/classquiz/routers/quiztivity.py
+++ b/classquiz/routers/quiztivity.py
@@ -42,3 +42,9 @@ async def delete_quiztivity(uuid: UUID):
if quiztivity is None:
raise HTTPException(status_code=404, detail="QuizTivity not found")
await quiztivity.delete()
+
+
+@router.get("/")
+async def get_all_quiztivities(user: User = Depends(get_current_user)) -> list[QuizTivity]:
+ quiztivities = await QuizTivity.objects.filter(user=user).order_by(QuizTivity.created_at.desc()).all()
+ return quiztivities
diff --git a/frontend/package.json b/frontend/package.json
index 3525fcd..cf535b5 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -33,6 +33,7 @@
"@tailwindcss/typography": "^0.5.9",
"@types/canvas-confetti": "^1.6.0",
"@types/cookie": "^0.5.1",
+ "@types/dompurify": "^3.0.2",
"@types/js-cookie": "^3.0.3",
"@types/luxon": "^3.3.0",
"@types/marked": "^4.3.0",
@@ -56,6 +57,7 @@
"cookie": "^0.5.0",
"crypto-js": "^4.1.1",
"cssnano": "^6.0.0",
+ "dompurify": "^3.0.3",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-svelte3": "^4.0.0",
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index eec0f6b..797eb29 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -20,6 +20,7 @@ specifiers:
'@tailwindcss/typography': ^0.5.9
'@types/canvas-confetti': ^1.6.0
'@types/cookie': ^0.5.1
+ '@types/dompurify': ^3.0.2
'@types/js-cookie': ^3.0.3
'@types/luxon': ^3.3.0
'@types/marked': ^4.3.0
@@ -43,6 +44,7 @@ specifiers:
cookie: ^0.5.0
crypto-js: ^4.1.1
cssnano: ^6.0.0
+ dompurify: ^3.0.3
eslint: ^8.38.0
eslint-config-prettier: ^8.8.0
eslint-plugin-svelte3: ^4.0.0
@@ -106,6 +108,7 @@ devDependencies:
'@tailwindcss/typography': 0.5.9_tailwindcss@3.3.1
'@types/canvas-confetti': 1.6.0
'@types/cookie': 0.5.1
+ '@types/dompurify': 3.0.2
'@types/js-cookie': 3.0.3
'@types/luxon': 3.3.0
'@types/marked': 4.3.0
@@ -129,6 +132,7 @@ devDependencies:
cookie: 0.5.0
crypto-js: 4.1.1
cssnano: 6.0.0_postcss@8.4.22
+ dompurify: 3.0.3
eslint: 8.38.0
eslint-config-prettier: 8.8.0_eslint@8.38.0
eslint-plugin-svelte3: 4.0.0_a4ckjr7darsrglbip3svgxgxc4
@@ -1438,6 +1442,15 @@ packages:
}
dev: true
+ /@types/dompurify/3.0.2:
+ resolution:
+ {
+ integrity: sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==
+ }
+ dependencies:
+ '@types/trusted-types': 2.0.3
+ dev: true
+
/@types/estree/1.0.1:
resolution:
{
@@ -1517,6 +1530,13 @@ packages:
}
dev: true
+ /@types/trusted-types/2.0.3:
+ resolution:
+ {
+ integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==
+ }
+ dev: true
+
/@types/ua-parser-js/0.7.36:
resolution:
{
@@ -2620,6 +2640,13 @@ packages:
domelementtype: 2.3.0
dev: true
+ /dompurify/3.0.3:
+ resolution:
+ {
+ integrity: sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==
+ }
+ dev: true
+
/domutils/3.0.1:
resolution:
{
diff --git a/frontend/src/lib/quiztivity/components/markdown/edit.svelte b/frontend/src/lib/quiztivity/components/markdown/edit.svelte
index b94ce1f..6128518 100644
--- a/frontend/src/lib/quiztivity/components/markdown/edit.svelte
+++ b/frontend/src/lib/quiztivity/components/markdown/edit.svelte
@@ -5,13 +5,9 @@
-->
+
+
+ {@html rendered_html}
+
diff --git a/frontend/src/lib/quiztivity/components/memory/edit.svelte b/frontend/src/lib/quiztivity/components/memory/edit.svelte
index bc16121..e9405e6 100644
--- a/frontend/src/lib/quiztivity/components/memory/edit.svelte
+++ b/frontend/src/lib/quiztivity/components/memory/edit.svelte
@@ -7,6 +7,7 @@
import type { Memory } from '../../types';
import { getLocalization } from '$lib/i18n';
import BrownButton from '$lib/components/buttons/brown.svelte';
+ import { flip } from 'svelte/animate';
const { t } = getLocalization();
@@ -21,6 +22,20 @@
cards: []
};
}
+ const arraymove = (arr: any[], fromI: number, toI: number) => {
+ const el = arr[fromI];
+ arr.splice(fromI, 1);
+ arr.splice(toI, 0, el);
+ };
+ const move_card_left = (selected_slide: number) => {
+ arraymove(data.cards, selected_slide, selected_slide - 1);
+ data.cards = data.cards;
+ };
+
+ const move_card_right = (selected_slide: number) => {
+ arraymove(data.cards, selected_slide, selected_slide + 1);
+ data.cards = data.cards;
+ };
const add_card = () => {
if (!new_pair_data.text_1 || !new_pair_data.text_2) {
@@ -81,8 +96,11 @@
>
- {#each data.cards as card_pair}
-
+ {#each data.cards as card_pair, i (card_pair[0].id)}
+
{#each card_pair as card}
@@ -90,6 +108,21 @@
{/each}
+
+ {
+ move_card_left(i);
+ }}
+ disabled={i === 0}>{$t('quiztivity.editor.move_left')}
+ {
+ move_card_right(i);
+ }}
+ disabled={i + 1 === data.cards.length}
+ >{$t('quiztivity.editor.move_right')}
+
{/each}
diff --git a/frontend/src/lib/quiztivity/components/memory/play.svelte b/frontend/src/lib/quiztivity/components/memory/play.svelte
new file mode 100644
index 0000000..a45c675
--- /dev/null
+++ b/frontend/src/lib/quiztivity/components/memory/play.svelte
@@ -0,0 +1,101 @@
+
+
+
+
+
{$t('quiztivity.play.memory.try_count', { try_count })}
+
+ {#each random_card_order as card}
+
{
+ flip_card(card.id);
+ }}
+ >
+ {#if card_opened[card.id]}
+ {card.text}
+ {:else}
+
+ {/if}
+
+ {/each}
+
+
diff --git a/frontend/src/lib/quiztivity/editor.svelte b/frontend/src/lib/quiztivity/editor.svelte
index bb20167..dc94952 100644
--- a/frontend/src/lib/quiztivity/editor.svelte
+++ b/frontend/src/lib/quiztivity/editor.svelte
@@ -109,7 +109,7 @@
-
+
{#each data.pages as page, i (page.id)}
+
+
diff --git a/frontend/src/routes/quiztivity/play/+page.ts b/frontend/src/routes/quiztivity/play/+page.ts
new file mode 100644
index 0000000..be54a5d
--- /dev/null
+++ b/frontend/src/routes/quiztivity/play/+page.ts
@@ -0,0 +1,24 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+import type { PageLoad } from './$types';
+import { error } from '@sveltejs/kit';
+import type { Data } from '$lib/quiztivity/types';
+
+export const load = (async ({ url, fetch }) => {
+ const id = url.searchParams.get('id');
+ if (!id) {
+ throw error(400, 'id missing');
+ }
+ const resp = await fetch(`/api/v1/quiztivity/${id}`);
+ if (!resp.ok) {
+ throw error(404, 'quiztivity not found');
+ }
+ const data: Data = await resp.json();
+ return {
+ quiztivity: data
+ };
+}) satisfies PageLoad;
diff --git a/frontend/src/routes/quiztivity/play/navigation_bar.svelte b/frontend/src/routes/quiztivity/play/navigation_bar.svelte
new file mode 100644
index 0000000..abe6c9d
--- /dev/null
+++ b/frontend/src/routes/quiztivity/play/navigation_bar.svelte
@@ -0,0 +1,36 @@
+
+
+
+
+
+ {
+ current_slide_index -= 1;
+ }}>{$t('words.back')}
+
+
+ {current_slide_index + 1}/{question_count}
+
+
+ {
+ current_slide_index += 1;
+ }}>{$t('words.next')}
+
+