New dashboard done

This commit is contained in:
Mawoka
2023-05-14 11:27:46 +02:00
parent 75d736c0ad
commit fd9e5dec38
8 changed files with 139 additions and 48 deletions
@@ -18,7 +18,11 @@
<a <a
{href} {href}
{target} {target}
class="text-black hover:bg-opacity-80 w-full px-4 py-2 leading-5 text-black transition-all duration-200 transform bg-[#B07156] rounded text-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 outline-none" {disabled}
class:opacity-50={disabled}
class:cursor-not-allowed={disabled}
class:pointer-events-none={disabled}
class="text-black hover:bg-opacity-80 w-full px-4 py-2 leading-5 transition-all duration-200 transform bg-[#B07156] rounded text-center outline-none"
on:click on:click
class:flex class:flex
class:justify-center={flex} class:justify-center={flex}
@@ -29,7 +33,7 @@
<button <button
{disabled} {disabled}
{type} {type}
class="text-black hover:opacity-80 w-full px-4 py-2 leading-5 text-black transition-all duration-200 transform bg-[#B07156] rounded text-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 outline-none" class="text-black hover:opacity-80 w-full px-4 py-2 leading-5 transition-all duration-200 transform bg-[#B07156] rounded text-center focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 outline-none"
on:click on:click
class:flex class:flex
class:justify-center={flex} class:justify-center={flex}
+28 -1
View File
@@ -169,7 +169,12 @@
"point_plural": "Points", "point_plural": "Points",
"back": "Back", "back": "Back",
"finish": "Finish", "finish": "Finish",
"normal": "Normal" "normal": "Normal",
"selected": "Selected",
"select": "Select",
"quiz": "Quiz",
"quiztivity": "Quiztivity",
"next": "Next"
}, },
"editor": { "editor": {
"time_in_seconds": "Time in seconds", "time_in_seconds": "Time in seconds",
@@ -344,5 +349,27 @@
"old_school_mode": "Old-School", "old_school_mode": "Old-School",
"old_school_mode_description": "Questions and images will be shown on both admins screen and on the screen of the players", "old_school_mode_description": "Questions and images will be shown on both admins screen and on the screen of the players",
"start_game": "Start Game" "start_game": "Start Game"
},
"quiztivity": {
"editor": {
"select_page_type": "Select Page Type",
"move_left": "Move left",
"move_right": "Move right",
"title_placeholder": "Enter title here",
"add_new": "Add new",
"delete": "Delete"
},
"memory": {
"editor": {
"add_card": "Add card",
"upload_image": "Upload image",
"add_pair": "Add pair"
}
},
"play": {
"memory": {
"try_count": "Tries: {{try_count}}"
}
}
} }
} }
@@ -12,12 +12,12 @@
export let type: QuizTivityTypes | undefined; export let type: QuizTivityTypes | undefined;
const PageTypes = [ const PageTypes = [
{ /* {
name: 'Pdf', name: 'Pdf',
description: 'Upload a PDF!', description: 'Upload a PDF!',
type: QuizTivityTypes.PDF, type: QuizTivityTypes.PDF,
svg: undefined svg: undefined
}, },*/
{ {
name: 'Memory', name: 'Memory',
description: 'Matching Pairs game', description: 'Matching Pairs game',
+2 -1
View File
@@ -41,7 +41,8 @@
$: handle_slide_add(selected_type); $: handle_slide_add(selected_type);
const delete_slide = () => { const delete_slide = () => {
data.pages.slice(selected_slide, 1); console.log(selected_slide);
data.pages.splice(selected_slide, 1);
data.pages = data.pages; data.pages = data.pages;
}; };
+79 -40
View File
@@ -11,6 +11,8 @@
// import Spinner from "$lib/Spinner.svelte"; // import Spinner from "$lib/Spinner.svelte";
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';
import BrownButton from '$lib/components/buttons/brown.svelte'; import BrownButton from '$lib/components/buttons/brown.svelte';
import type { PageData } from './$types';
import { fly } from 'svelte/transition';
// import GrayButton from "$lib/components/buttons/gray.svelte"; // import GrayButton from "$lib/components/buttons/gray.svelte";
@@ -25,60 +27,73 @@
questions: Question[]; questions: Question[];
} }
export let data: PageData;
let search_term = ''; let search_term = '';
let start_game = null; let start_game = null;
signedIn.set(true); signedIn.set(true);
navbarVisible.set(true); navbarVisible.set(true);
const { t } = getLocalization(); const { t } = getLocalization();
let quizzes_to_show = []; let items_to_show = [];
let quizzes: Array<any>; let all_items: Array<any>;
let fuse; let fuse;
/* const minisearch = new MiniSearch({
fields: ['title', 'description'],
idField: 'id',
storeFields: ['id']
})*/
let id_to_position_map = {}; let id_to_position_map = {};
const getData = async (): Promise<Array<QuizData>> => { const getData = async (): Promise<Array<QuizData>> => {
const res = await fetch('/api/v1/quiz/list?page_size=100'); items_to_show = [];
quizzes_to_show = await res.json(); for (let i = 0; i < data.quizzes.length; i++) {
fuse = new Fuse(quizzes_to_show, { items_to_show.push({ ...data.quizzes[i], type: 'quiz' });
keys: ['title', 'description', 'questions.question'], }
for (let i = 0; i < data.quiztivities.length; i++) {
items_to_show.push({ ...data.quiztivities[i], type: 'quiztivity' });
}
fuse = new Fuse(items_to_show, {
keys: ['title', 'description', 'questions.title'],
findAllMatches: true findAllMatches: true
}); });
quizzes = quizzes_to_show; all_items = items_to_show;
for (let i = 0; i < quizzes.length; i++) { for (let i = 0; i < all_items.length; i++) {
id_to_position_map[quizzes[i].id] = i; id_to_position_map[all_items[i].id] = i;
} }
return quizzes_to_show; return all_items;
}; };
let suggestions = [];
const search = () => { const search = () => {
if (search_term === '') { if (search_term === '') {
quizzes_to_show = []; items_to_show = all_items;
quizzes_to_show = quizzes;
quizzes_to_show = quizzes_to_show;
} else { } else {
const res = fuse.search(search_term); const res = fuse.search(search_term);
console.log(res, 'search_res'); console.log(res, 'search_res');
quizzes_to_show = []; items_to_show = [];
for (const quiz_data of res) { for (const quiz_data of res) {
quizzes_to_show.push(quiz_data.item); items_to_show.push(quiz_data.item);
} }
quizzes_to_show = quizzes_to_show; items_to_show = items_to_show;
} }
}; };
$: { $: {
search_term; search_term;
// console.log(search_term);
search(); search();
} }
const deleteQuiz = async (to_delete: string, type: 'quiz' | 'quiztivity') => {
if (!confirm('Do you really want to delete this quiz?')) {
return;
}
if (type === 'quiz') {
await fetch(`/api/v1/quiz/delete/${to_delete}`, {
method: 'DELETE'
});
} else {
await fetch(`/api/v1/quiztivity/${to_delete}`, {
method: 'DELETE'
});
}
window.location.reload();
};
let create_button_clicked = false;
</script> </script>
<svelte:head> <svelte:head>
@@ -104,7 +119,19 @@
Primary Primary
</button>--> </button>-->
<div class="w-full grid lg:grid-cols-4 gap-2 grid-cols-2 px-4"> <div class="w-full grid lg:grid-cols-4 gap-2 grid-cols-2 px-4">
<BrownButton href="/create">{$t('words.create')}</BrownButton> {#if create_button_clicked}
<div class="flex gap-2" transition:fly={{ y: 10 }}>
<BrownButton href="/create">{$t('words.quiz')}</BrownButton>
<BrownButton href="/quiztivity/create">{$t('words.quiztivity')}</BrownButton
>
</div>
{:else}
<BrownButton
on:click={() => {
create_button_clicked = true;
}}>{$t('words.create')}</BrownButton
>
{/if}
<BrownButton href="/import">{$t('words.import')}</BrownButton> <BrownButton href="/import">{$t('words.import')}</BrownButton>
<BrownButton href="/results">{$t('words.results')}</BrownButton> <BrownButton href="/results">{$t('words.results')}</BrownButton>
<BrownButton href="/account/settings"> <BrownButton href="/account/settings">
@@ -123,8 +150,7 @@
<button <button
on:click={() => { on:click={() => {
search_term = ''; search_term = '';
quizzes_to_show = quizzes; items_to_show = all_items;
suggestions = [];
}} }}
> >
<svg <svg
@@ -146,7 +172,7 @@
</div> </div>
</div> </div>
<div class="flex flex-col gap-4 mt-4 px-2"> <div class="flex flex-col gap-4 mt-4 px-2">
{#each quizzes_to_show as quiz} {#each items_to_show as quiz}
<div <div
class="grid grid-cols-2 lg:grid-cols-3 w-full rounded border-[#B07156] border-2 p-2 h-[20vh] overflow-hidden max-h-[20vh]" class="grid grid-cols-2 lg:grid-cols-3 w-full rounded border-[#B07156] border-2 p-2 h-[20vh] overflow-hidden max-h-[20vh]"
> >
@@ -160,28 +186,38 @@
/> />
{/if} {/if}
</div> </div>
<div class="my-auto mx-auto max-h-full"> <div class="my-auto mx-auto max-h-full overflow-hidden">
<p class="text-xl text-center">{@html quiz.title}</p> <p class="text-xl text-center">{@html quiz.title}</p>
<p class="text-sm text-center text-clip overflow-hidden"> <p class="text-sm text-center text-clip overflow-hidden">
{@html quiz.description} {@html quiz.description ?? ''}
</p> </p>
</div> </div>
<div <div
class="grid grid-cols-2 grid-rows-2 ml-auto gap-2 w-fit self-end my-auto" class="grid grid-cols-2 grid-rows-2 ml-auto gap-2 w-fit self-end my-auto"
> >
<BrownButton href="/edit?quiz_id={quiz.id}" <BrownButton
href={quiz.type === 'quiz'
? `/edit?quiz_id=${quiz.id}`
: `/quiztivity/edit?id=${quiz.id}`}
>{$t('words.edit')}</BrownButton >{$t('words.edit')}</BrownButton
> >
{#if quiz.type === 'quiz'}
<BrownButton
on:click={() => {
start_game = quiz.id;
}}
>
{$t('words.start')}
</BrownButton>
{:else}
<BrownButton href="/quiztivity/play?id={quiz.id}">
{$t('words.play')}
</BrownButton>
{/if}
<BrownButton <BrownButton
on:click={() => { on:click={() => {
start_game = quiz.id; deleteQuiz(quiz.id, quiz.type);
}}
>
{$t('words.start')}
</BrownButton>
<BrownButton
on:click={() => {
// deleteQuiz(quiz.id);
}} }}
flex={true} flex={true}
> >
@@ -201,7 +237,10 @@
/> />
</svg> </svg>
</BrownButton> </BrownButton>
<BrownButton href="/api/v1/eximport/{quiz.id}" flex={true} <BrownButton
href="/api/v1/eximport/{quiz.id}"
flex={true}
disabled={quiz.type !== 'quiz'}
><!-- heroicons/download --> ><!-- heroicons/download -->
<svg <svg
class="w-5 h-5" class="w-5 h-5"
+18
View File
@@ -0,0 +1,18 @@
/*
* 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';
export const load = (async ({ fetch }) => {
const quiz_res = await fetch('/api/v1/quiz/list?page_size=100');
const quizzes = await quiz_res.json();
const quiztivity_res = await fetch('/api/v1/quiztivity/');
const quiztivities = await quiztivity_res.json();
return {
quizzes,
quiztivities
};
}) satisfies PageLoad;
@@ -6,6 +6,7 @@
<script lang="ts"> <script lang="ts">
import type { Data } from '$lib/quiztivity/types'; import type { Data } from '$lib/quiztivity/types';
import Editor from '$lib/quiztivity/editor.svelte'; import Editor from '$lib/quiztivity/editor.svelte';
import { goto } from '$app/navigation';
let data: Data = { pages: [], id: undefined, title: '' }; let data: Data = { pages: [], id: undefined, title: '' };
let saving = false; let saving = false;
@@ -24,7 +25,7 @@
body: stringification body: stringification
}); });
if (res.ok) { if (res.ok) {
// await goto("/dashboard") await goto('/dashboard');
} else { } else {
alert("Couldn't save"); alert("Couldn't save");
} }
@@ -6,6 +6,7 @@
<script lang="ts"> <script lang="ts">
import type { PageData } from './$types'; import type { PageData } from './$types';
import Editor from '../../../lib/quiztivity/editor.svelte'; import Editor from '../../../lib/quiztivity/editor.svelte';
import { goto } from '$app/navigation';
export let data: PageData; export let data: PageData;
@@ -25,7 +26,7 @@
body: stringification body: stringification
}); });
if (res.ok) { if (res.ok) {
// await goto("/dashboard") await goto('/dashboard');
} else { } else {
alert("Couldn't save"); alert("Couldn't save");
} }