✨ New Dashboard #80
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
"js-cookie": "^3.0.1",
|
||||
"luxon": "^2.5.0",
|
||||
"mapbox-gl": "^2.9.2",
|
||||
"minisearch": "^5.0.0",
|
||||
"plausible-tracker": "^0.3.8",
|
||||
"postcss": "^8.4.16",
|
||||
"postcss-import": "^14.1.0",
|
||||
|
||||
Generated
+12
-3
@@ -39,6 +39,7 @@ specifiers:
|
||||
js-cookie: ^3.0.1
|
||||
luxon: ^2.5.0
|
||||
mapbox-gl: ^2.9.2
|
||||
minisearch: ^5.0.0
|
||||
plausible-tracker: ^0.3.8
|
||||
postcss: ^8.4.16
|
||||
postcss-import: ^14.1.0
|
||||
@@ -74,7 +75,7 @@ devDependencies:
|
||||
'@sentry/tracing': 7.11.1
|
||||
'@sveltejs/adapter-auto': 1.0.0-next.64
|
||||
'@sveltejs/adapter-node': 1.0.0-next.86
|
||||
'@sveltejs/kit': 1.0.0-next.420_svelte@3.49.0+vite@3.0.8
|
||||
'@sveltejs/kit': 1.0.0-next.421_svelte@3.49.0+vite@3.0.8
|
||||
'@tailwindcss/typography': 0.5.4_tailwindcss@3.1.8
|
||||
'@types/cookie': 0.5.1
|
||||
'@types/js-cookie': 3.0.2
|
||||
@@ -103,6 +104,7 @@ devDependencies:
|
||||
js-cookie: 3.0.1
|
||||
luxon: 2.5.0
|
||||
mapbox-gl: 2.9.2
|
||||
minisearch: 5.0.0
|
||||
plausible-tracker: 0.3.8
|
||||
postcss: 8.4.16
|
||||
postcss-import: 14.1.0_postcss@8.4.16
|
||||
@@ -574,10 +576,10 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/kit/1.0.0-next.420_svelte@3.49.0+vite@3.0.8:
|
||||
/@sveltejs/kit/1.0.0-next.421_svelte@3.49.0+vite@3.0.8:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-9m/uWbd7Osj474TrkjRZ2x784PZzO6akxDFGfaEoFS5AsRUnDFRJ0HWHHdymy170aJsvlu20ZpLTNbbS5a95+g==
|
||||
integrity: sha512-DtrU43PKz8xR52aVXVyYCssSoB0LX9D1QZLsVEFc/vGppBAe+0eJCCFHH1BqdXoIPHzp3FhpGGsK7jt5l7XjOw==
|
||||
}
|
||||
engines: { node: '>=16.9' }
|
||||
hasBin: true
|
||||
@@ -3241,6 +3243,13 @@ packages:
|
||||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/minisearch/5.0.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-VEwBhl8aFtc2UG2XmP7a4XaZxVfNhe7GvB2W/ZRGbLL3P3LbBhkoOezBWsMqG8Mr5VonqXAMRWth79XXKja1bQ==
|
||||
}
|
||||
dev: true
|
||||
|
||||
/minizlib/2.1.2:
|
||||
resolution:
|
||||
{
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
<!--
|
||||
- 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/.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Swiper, SwiperSlide } from 'swiper/svelte';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/pagination';
|
||||
import { Pagination, EffectCoverflow } from 'swiper';
|
||||
import { QuizQuestionType } from '$lib/quiz_types.js';
|
||||
import { getLocalization } from '../i18n';
|
||||
import { alertModal } from '../stores';
|
||||
|
||||
const { t } = getLocalization();
|
||||
export let quizzes;
|
||||
|
||||
const startGame = async (id: string): Promise<void> => {
|
||||
let res;
|
||||
if (window.confirm('Do you want to enable the captcha for players?')) {
|
||||
res = await fetch(`/api/v1/quiz/start/${id}?captcha_enabled=True`, {
|
||||
method: 'POST'
|
||||
});
|
||||
} else {
|
||||
res = await fetch(`/api/v1/quiz/start/${id}?captcha_enabled=False`, {
|
||||
method: 'POST'
|
||||
});
|
||||
}
|
||||
|
||||
if (res.status !== 200) {
|
||||
alertModal.set({
|
||||
open: true,
|
||||
title: 'Start failed',
|
||||
body: `Failed to start game, ${await res.text()}`
|
||||
});
|
||||
alertModal.subscribe((_) => {
|
||||
window.location.assign('/account/login?returnTo=/dashboard');
|
||||
});
|
||||
}
|
||||
const data = await res.json();
|
||||
// eslint-disable-next-line no-undef
|
||||
plausible('Started Game', { props: { quiz_id: id } });
|
||||
window.location.assign(`/admin?token=${data.game_id}&pin=${data.game_pin}&connect=1`);
|
||||
};
|
||||
|
||||
const deleteQuiz = async (to_delete: string) => {
|
||||
if (!confirm('Do you really want to delete this quiz?')) {
|
||||
return;
|
||||
}
|
||||
await fetch(`/api/v1/quiz/delete/${to_delete}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
window.location.reload();
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="w-screen p-8">
|
||||
<Swiper
|
||||
grabCursor={true}
|
||||
effect={'coverflow'}
|
||||
modules={[EffectCoverflow, Pagination]}
|
||||
slidesPerView={1}
|
||||
mousewheel={true}
|
||||
centeredSlides={true}
|
||||
coverflowEffect={{
|
||||
rotate: 50,
|
||||
stretch: 0,
|
||||
depth: 100,
|
||||
modifier: 1,
|
||||
slideShadows: false
|
||||
}}
|
||||
pagination={{
|
||||
clickable: true
|
||||
}}
|
||||
>
|
||||
{#each quizzes as quiz}
|
||||
<SwiperSlide>
|
||||
<div class="flex justify-center pt-4 px-4">
|
||||
<a href="/edit?quiz_id={quiz.id}" class="text-3xl">{quiz.title}</a>
|
||||
</div>
|
||||
<div class="flex justify-center p-10 h-full">
|
||||
<div class="border-2 border-black rounded-lg w-5/6">
|
||||
<Swiper
|
||||
pagination={{
|
||||
clickable: true
|
||||
}}
|
||||
grabCursor={true}
|
||||
modules={[Pagination]}
|
||||
>
|
||||
<SwiperSlide>
|
||||
<div class="grid grid-cols-6 h-full">
|
||||
<p
|
||||
style="writing-mode: vertical-lr"
|
||||
class="text-center h-full text-xl p-2"
|
||||
>
|
||||
{quiz.title}
|
||||
</p>
|
||||
<p class="text-center col-start-2 col-end-6">
|
||||
{quiz.description}
|
||||
</p>
|
||||
<div class="flex justify-end">
|
||||
<p
|
||||
style="writing-mode: sideways-lr"
|
||||
class="text-center text-xl p-2"
|
||||
>
|
||||
{quiz.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">{quiz.questions.length} Questions</p>
|
||||
<div class="flex justify-center mt-8">
|
||||
{#if quiz.public}
|
||||
<svg
|
||||
class="w-8 h-8 inline-block"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>{$t('words.public')}</span>
|
||||
{:else}
|
||||
<svg
|
||||
class="w-8 h-8 inline-block"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
|
||||
/>
|
||||
</svg>
|
||||
<span>{$t('words.private')}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex justify-center pb-20 pt-8">
|
||||
<div class="flex flex-col gap-4">
|
||||
<a
|
||||
href="/edit?quiz_id={quiz.id}"
|
||||
class="px-4 py-2 leading-5 text-black dark:text-white transition-colors duration-200 transform bg-gray-50 dark:bg-gray-700 rounded text-center hover:bg-gray-300 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-gray-600"
|
||||
>Edit</a
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
startGame(quiz.id);
|
||||
}}
|
||||
class="px-4 py-2 leading-5 text-black dark:text-white transition-colors duration-200 transform bg-gray-50 dark:bg-gray-700 rounded text-center hover:bg-gray-300 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-gray-600"
|
||||
>
|
||||
Start
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-center" />
|
||||
</SwiperSlide>
|
||||
{#each quiz.questions as question}
|
||||
<SwiperSlide>
|
||||
<div class="h-full">
|
||||
<h5 class="text-center text-2xl">{question.question}</h5>
|
||||
{#if question.image}
|
||||
<div
|
||||
class="flex justify-center align-middle items-center"
|
||||
>
|
||||
<div class="h-[30vh] m-auto w-auto">
|
||||
<img
|
||||
class="max-h-full max-w-full block"
|
||||
src={question.image}
|
||||
alt="Not provided"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<p
|
||||
class="m-1 flex flex-row gap-2 flex-nowrap whitespace-nowrap w-full justify-center"
|
||||
>
|
||||
<svg
|
||||
class="w-8 h-8 inline-block"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text-lg">{question.time}s</span>
|
||||
</p>
|
||||
{#if question.type === QuizQuestionType.ABCD || question.type === undefined}
|
||||
<div class="grid grid-cols-2 gap-4 m-4 p-6">
|
||||
{#each question.answers as answer, index_answer}
|
||||
<div
|
||||
class="p-1 rounded-lg py-4"
|
||||
class:bg-green-500={answer.right}
|
||||
class:bg-red-500={!answer.right}
|
||||
>
|
||||
<h4 class="text-center">
|
||||
{answer.answer}
|
||||
</h4>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if question.type === QuizQuestionType.RANGE}
|
||||
<p class="m-1 text-center">
|
||||
All numbers between {question.answers.min_correct}
|
||||
and {question.answers.max_correct} are correct, where
|
||||
numbers between {question.answers.min} and {question
|
||||
.answers.max} can be selected.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
{/each}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
{/each}
|
||||
</Swiper>
|
||||
</div>
|
||||
@@ -5,10 +5,11 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { Question } from '$lib/quiz_types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { getLocalization } from '$lib/i18n';
|
||||
import Footer from '$lib/footer.svelte';
|
||||
import { alertModal, navbarVisible, signedIn } from '$lib/stores';
|
||||
import Spinner from '$lib/Spinner.svelte';
|
||||
import MiniSearch from 'minisearch';
|
||||
|
||||
interface QuizData {
|
||||
id: string;
|
||||
@@ -21,55 +22,60 @@
|
||||
questions: Question[];
|
||||
}
|
||||
|
||||
let search_term = '';
|
||||
signedIn.set(true);
|
||||
navbarVisible.set(true);
|
||||
const { t } = getLocalization();
|
||||
|
||||
let quizzes_to_show;
|
||||
let quizzes: Array<any>;
|
||||
const minisearch = new MiniSearch({
|
||||
fields: ['title', 'description'],
|
||||
idField: 'id',
|
||||
storeFields: ['id']
|
||||
});
|
||||
|
||||
let id_to_position_map = {};
|
||||
|
||||
const getData = async (): Promise<Array<QuizData>> => {
|
||||
const res = await fetch('/api/v1/quiz/list');
|
||||
return await res.json();
|
||||
quizzes_to_show = await res.json();
|
||||
await minisearch.addAllAsync(quizzes_to_show);
|
||||
quizzes = quizzes_to_show;
|
||||
for (let i = 0; i < quizzes.length; i++) {
|
||||
id_to_position_map[quizzes[i].id] = i;
|
||||
}
|
||||
console.log(id_to_position_map);
|
||||
return quizzes_to_show;
|
||||
};
|
||||
|
||||
const formatDate = (date: string): string => {
|
||||
const dt = DateTime.fromISO(date);
|
||||
return dt.toLocaleString(DateTime.DATETIME_MED);
|
||||
};
|
||||
let suggestions = [];
|
||||
|
||||
const startGame = async (id: string): Promise<void> => {
|
||||
console.log('start game', id);
|
||||
let res;
|
||||
if (window.confirm('Do you want to enable the captcha for players?')) {
|
||||
res = await fetch(`/api/v1/quiz/start/${id}?captcha_enabled=True`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const search = () => {
|
||||
console.log(search_term);
|
||||
if (search_term === '') {
|
||||
console.log('HELLO');
|
||||
quizzes_to_show = [];
|
||||
quizzes_to_show = quizzes;
|
||||
console.log(quizzes_to_show);
|
||||
quizzes_to_show = quizzes_to_show;
|
||||
} else {
|
||||
res = await fetch(`/api/v1/quiz/start/${id}?captcha_enabled=False`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const res = minisearch.search(search_term);
|
||||
if (res.length === 0) {
|
||||
quizzes_to_show = [];
|
||||
suggestions = minisearch.autoSuggest(search_term);
|
||||
} else {
|
||||
for (const quiz_data of res) {
|
||||
quizzes_to_show.push(quizzes[id_to_position_map[quiz_data.id]]);
|
||||
}
|
||||
}
|
||||
quizzes_to_show = quizzes_to_show;
|
||||
}
|
||||
|
||||
if (res.status !== 200) {
|
||||
alertModal.set({
|
||||
open: true,
|
||||
title: 'Start failed',
|
||||
body: `Failed to start game, ${await res.text()}`
|
||||
});
|
||||
alertModal.subscribe((_) => {
|
||||
window.location.assign('/account/login?returnTo=/dashboard');
|
||||
});
|
||||
}
|
||||
const data = await res.json();
|
||||
// eslint-disable-next-line no-undef
|
||||
plausible('Started Game', { props: { quiz_id: id } });
|
||||
window.location.assign(`/admin?token=${data.game_id}&pin=${data.game_pin}&connect=1`);
|
||||
};
|
||||
|
||||
const deleteQuiz = async (to_delete: string) => {
|
||||
await fetch(`/api/v1/quiz/delete/${to_delete}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
window.location.reload();
|
||||
};
|
||||
$: {
|
||||
search_term;
|
||||
search();
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -118,125 +124,59 @@
|
||||
</a>
|
||||
</div>
|
||||
{#if quizzes.length !== 0}
|
||||
<div class="overflow-x-auto sm:-mx-8 lg:-mx-8">
|
||||
<div class="inline-block py-2 min-w-full sm:px-6 lg:px-8">
|
||||
<div class="overflow-hidden shadow-md sm:rounded-lg">
|
||||
<table class="min-w-full">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('words.title')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 dark:text-gray-400 uppercase"
|
||||
>
|
||||
{$t('overview_page.created_at')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('overview_page.question_count')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('words.play')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('words.edit')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('words.delete')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="py-3 px-6 text-xs font-medium tracking-wider text-left text-gray-700 uppercase dark:text-gray-400"
|
||||
>
|
||||
{$t('words.public')}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each quizzes as quiz}
|
||||
<tr
|
||||
class="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
|
||||
>
|
||||
<td
|
||||
class="py-4 px-6 text-sm font-medium text-gray-900 whitespace-nowrap dark:text-white"
|
||||
{#await import('$lib/dashboard/main_slider.svelte')}
|
||||
<Spinner />
|
||||
{:then c}
|
||||
<div class="flex justify-center pt-4 w-full">
|
||||
<div>
|
||||
<div>
|
||||
<input
|
||||
bind:value={search_term}
|
||||
class="p-2 rounded-lg outline-none text-center w-96"
|
||||
placeholder="Search for your own quizzes"
|
||||
/>
|
||||
<button
|
||||
on:click={() => {
|
||||
search_term = '';
|
||||
quizzes_to_show = quizzes;
|
||||
suggestions = [];
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
class="h-8 inline-block"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{#if quizzes_to_show.length === 0 && suggestions.length !== 0}
|
||||
<ul class="relative bg-white mt-0.5">
|
||||
{#each suggestions as res}
|
||||
<li>
|
||||
<button
|
||||
class="w-full"
|
||||
on:click={() => {
|
||||
suggestions = [];
|
||||
search_term = res.suggestion;
|
||||
}}>{res.suggestion}</button
|
||||
>
|
||||
{quiz.title}
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
{formatDate(quiz.created_at)}
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
{quiz.questions.length}
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
startGame(quiz.id);
|
||||
}}
|
||||
class="border border-green-600"
|
||||
>
|
||||
{$t('words.start')}
|
||||
</button>
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
<a
|
||||
href="/edit?quiz_id={quiz.id}"
|
||||
class="border border-yellow-600"
|
||||
>{$t('words.edit')}</a
|
||||
>
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
deleteQuiz(quiz.id);
|
||||
}}
|
||||
class="border border-red-600"
|
||||
>
|
||||
{$t('words.delete')}
|
||||
</button>
|
||||
</td>
|
||||
<td
|
||||
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
|
||||
>
|
||||
{#if quiz.public}
|
||||
✅
|
||||
{:else}
|
||||
❌
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</li>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<svelte:component this={c.default} bind:quizzes={quizzes_to_show} />
|
||||
{/await}
|
||||
{:else}
|
||||
<p>
|
||||
{$t('overview_page.no_quizzes')}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
export let data;
|
||||
let { quiz_id } = data;
|
||||
console.log(quiz_id);
|
||||
let quiz_data: Data;
|
||||
|
||||
const get_quiz = async (): Promise<void> => {
|
||||
@@ -76,7 +77,7 @@
|
||||
</svg>
|
||||
{:then _}
|
||||
{#if quiz_data !== undefined}
|
||||
<Editor bind:quiz_data submit_button_text={$t('words.save')} bind:quiz_id />
|
||||
<Editor bind:data={quiz_data} submit_button_text={$t('words.save')} bind:quiz_id />
|
||||
{/if}
|
||||
{:catch err}
|
||||
<div class="text-center">
|
||||
|
||||
Reference in New Issue
Block a user