📝 Updated docs with warning
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
# ClassQuiz
|
||||
|
||||
ClassQuiz is a quiz-application like KAHOOT!, but open-source which is very important if it is a product for educational
|
||||
purposes. You can create quizzes and play them remotely with other people. It is mainly made for teachers, who create a
|
||||
purposes.
|
||||
You can create quizzes and play them remotely with other people.
|
||||
It is mainly made for teachers, who create a
|
||||
quiz, so students can compete with their knowledge against each other.
|
||||
|
||||
## Try it
|
||||
@@ -20,7 +22,7 @@ See https://classquiz.mawoka.eu/docs/develop
|
||||
|
||||
## Docs
|
||||
|
||||
The docs are https://classquiz.mawoka.eu/docs on the website
|
||||
The docs are online at https://classquiz.mawoka.eu/docs
|
||||
|
||||
### Things to know about the structure
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang='ts'>
|
||||
<script lang="ts">
|
||||
import { getLocalization } from '$lib/i18n';
|
||||
|
||||
const { t } = getLocalization();
|
||||
@@ -62,82 +62,82 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<label class='pl-2 w-2/6 flex gap-2 flex-row'>
|
||||
<input type='checkbox' class='w-fit' bind:checked={data.public} />
|
||||
<span class='w-fit'>{$t('words.public')}?</span>
|
||||
<label class="pl-2 w-2/6 flex gap-2 flex-row">
|
||||
<input type="checkbox" class="w-fit" bind:checked={data.public} />
|
||||
<span class="w-fit">{$t('words.public')}?</span>
|
||||
</label>
|
||||
<label class='pl-2 flex flex-row gap-2 w-3/5'>
|
||||
<span class='w-fit'>{$t('words.title')}:</span>
|
||||
<label class="pl-2 flex flex-row gap-2 w-3/5">
|
||||
<span class="w-fit">{$t('words.title')}:</span>
|
||||
<input
|
||||
type='text'
|
||||
type="text"
|
||||
placeholder={$t('words.title')}
|
||||
bind:value={data.title}
|
||||
class='text-black bg-inherit border-dotted border-b-2 border-black w-full'
|
||||
class="text-black bg-inherit border-dotted border-b-2 border-black w-full"
|
||||
/>
|
||||
</label>
|
||||
<label class='pl-2 flex flex-row gap-2 w-3/5'>
|
||||
<label class="pl-2 flex flex-row gap-2 w-3/5">
|
||||
{$t('words.description')}:
|
||||
<textarea
|
||||
placeholder={$t('words.description')}
|
||||
bind:value={data.description}
|
||||
class='text-black w-full'
|
||||
class="text-black w-full"
|
||||
/>
|
||||
</label>
|
||||
{#each data.questions as question, index_question}
|
||||
<div class='ml-8 grid grid-cols-1 gap-2 m-2 border border-black border-2'>
|
||||
<h1 class='text-3xl m-1'>{$t('words.question')} {index_question + 1}</h1>
|
||||
<div class="ml-8 grid grid-cols-1 gap-2 m-2 border border-black border-2">
|
||||
<h1 class="text-3xl m-1">{$t('words.question')} {index_question + 1}</h1>
|
||||
|
||||
<label class='m-1 flex flex-row gap-2 w-3/5'>
|
||||
<label class="m-1 flex flex-row gap-2 w-3/5">
|
||||
{$t('words.question')}:
|
||||
<input
|
||||
type='text'
|
||||
type="text"
|
||||
placeholder={$t('words.question')}
|
||||
bind:value={question.question}
|
||||
class='text-black w-full bg-inherit border-dotted border-b-2 border-black'
|
||||
class="text-black w-full bg-inherit border-dotted border-b-2 border-black"
|
||||
/>
|
||||
</label>
|
||||
<label class='m-1 flex flex-row gap-2 w-3/5'>
|
||||
<label class="m-1 flex flex-row gap-2 w-3/5">
|
||||
{$t('words.image')}:
|
||||
<input
|
||||
type='text'
|
||||
placeholder='https://i.imgur.com/kSPCidY.png'
|
||||
type="text"
|
||||
placeholder="https://i.imgur.com/kSPCidY.png"
|
||||
bind:value={question.image}
|
||||
class='text-black w-full bg-inherit border-dotted border-b-2 border-black'
|
||||
class="text-black w-full bg-inherit border-dotted border-b-2 border-black"
|
||||
/>
|
||||
</label>
|
||||
<label class='m-1 flex flex-row gap-2 w-3/5 flex-nowrap whitespace-nowrap'>
|
||||
<label class="m-1 flex flex-row gap-2 w-3/5 flex-nowrap whitespace-nowrap">
|
||||
{$t('editor.time_in_seconds')}:
|
||||
<input
|
||||
type='text'
|
||||
placeholder='20'
|
||||
type="text"
|
||||
placeholder="20"
|
||||
bind:value={question.time}
|
||||
class='text-black w-full bg-inherit border-dotted border-b-2 border-black'
|
||||
class="text-black w-full bg-inherit border-dotted border-b-2 border-black"
|
||||
/>
|
||||
</label>
|
||||
{#each question.answers as answer, index_answer}
|
||||
<div class='ml-8 grid grid-cols-1 gap-2 m-2 border border-black border-2 m-1'>
|
||||
<h1 class='text-3xl m-1'>{$t('words.answer')} {index_answer + 1}</h1>
|
||||
<p class='m-1'>
|
||||
<div class="ml-8 grid grid-cols-1 gap-2 m-2 border border-black border-2 m-1">
|
||||
<h1 class="text-3xl m-1">{$t('words.answer')} {index_answer + 1}</h1>
|
||||
<p class="m-1">
|
||||
{$t('words.answer')}: {index_answer + 1}
|
||||
{$t('words.question')}: {index_question + 1}
|
||||
</p>
|
||||
<label class='m-1 flex flex-row gap-2 w-3/5 flex-nowrap whitespace-nowrap'>
|
||||
<label class="m-1 flex flex-row gap-2 w-3/5 flex-nowrap whitespace-nowrap">
|
||||
{$t('words.answer')}:
|
||||
<input
|
||||
type='text'
|
||||
type="text"
|
||||
placeholder={$t('words.answer')}
|
||||
bind:value={data.questions[index_question].answers[index_answer].answer}
|
||||
class='text-black w-full bg-inherit border-dotted border-b-2 border-black'
|
||||
class="text-black w-full bg-inherit border-dotted border-b-2 border-black"
|
||||
/>
|
||||
</label>
|
||||
<label class='m-1 flex flex-row gap-2 w-2/6 flex-nowrap whitespace-nowrap'>
|
||||
<input type='checkbox' bind:checked={answer.right} class='text-black w-fit' />
|
||||
<span class='w-fit'>{$t('editor.right_or_true?')}</span>
|
||||
<label class="m-1 flex flex-row gap-2 w-2/6 flex-nowrap whitespace-nowrap">
|
||||
<input type="checkbox" bind:checked={answer.right} class="text-black w-fit" />
|
||||
<span class="w-fit">{$t('editor.right_or_true?')}</span>
|
||||
</label>
|
||||
|
||||
<button
|
||||
class='text-left border-yellow-500 border-2 w-fit m-1'
|
||||
type='button'
|
||||
class="text-left border-yellow-500 border-2 w-fit m-1"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
data.questions[index_question].answers.splice(index_answer, 1);
|
||||
data.questions[index_question].answers =
|
||||
@@ -149,8 +149,8 @@
|
||||
</div>
|
||||
{/each}
|
||||
<button
|
||||
class='text-left border-green-500 border-2 w-fit m-1'
|
||||
type='button'
|
||||
class="text-left border-green-500 border-2 w-fit m-1"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
data.questions[index_question].answers = [
|
||||
...data.questions[index_question].answers,
|
||||
@@ -161,8 +161,8 @@
|
||||
{$t('editor.add_new_answer')}
|
||||
</button>
|
||||
<button
|
||||
class='text-left border-red-500 border-2 w-fit m-1'
|
||||
type='button'
|
||||
class="text-left border-red-500 border-2 w-fit m-1"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
data.questions.splice(index_question, 1);
|
||||
data.questions = data.questions;
|
||||
@@ -173,8 +173,8 @@
|
||||
</div>
|
||||
{/each}
|
||||
<button
|
||||
class='text-left'
|
||||
type='button'
|
||||
class="text-left"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
data.questions = [...data.questions, { ...empty_question }];
|
||||
}}
|
||||
@@ -182,12 +182,12 @@
|
||||
{$t('editor.add_new_question')}
|
||||
</button>
|
||||
{#if imgur_links_valid}
|
||||
<p class='text-blue-600 text-xl text-center w-fit mx-auto'>
|
||||
<p class="text-blue-600 text-xl text-center w-fit mx-auto">
|
||||
Not all links are imgur-links! <!-- TODO: Add translation -->
|
||||
</p>
|
||||
{/if}
|
||||
<button
|
||||
type='submit'
|
||||
class='text-xl disabled:cursor-not-allowed disabled:border disabled:border-red-500 w-fit mx-auto'
|
||||
type="submit"
|
||||
class="text-xl disabled:cursor-not-allowed disabled:border disabled:border-red-500 w-fit mx-auto"
|
||||
disabled={imgur_links_valid}>{submit_button_text}</button
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script lang='ts'>
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import '$lib/hljs.css';
|
||||
|
||||
@@ -11,33 +11,42 @@
|
||||
<svelte:head>
|
||||
<title>ClassQuiz/docs - Self-Host</title>
|
||||
<meta
|
||||
name='description'
|
||||
content='How to self-host ClassQuiz, the open-source quiz-application'
|
||||
name="description"
|
||||
content="How to self-host ClassQuiz, the open-source quiz-application"
|
||||
/>
|
||||
</svelte:head>
|
||||
<article
|
||||
class='prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto mt-10 prose-pink text-yellow-50 px-4'
|
||||
class="prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto mt-10 prose-pink text-yellow-50 px-4"
|
||||
>
|
||||
<h1>Self-Hosting</h1>
|
||||
<p>Since ClassQuiz is open-source, it can also be self-hosted.</p>
|
||||
|
||||
<h2>Warning</h2>
|
||||
<p>
|
||||
Since ClassQuiz is in pretty early development, breaking changes come and go! Please check
|
||||
these docs again before updating your instance. I may also add more dependencies like <a
|
||||
href="https://typesense.org/">Typesense</a
|
||||
>
|
||||
ore something similar in the future, but I'll always provide a
|
||||
<code>docker-compose.yml</code> file, so the self-hosting process is still easy.
|
||||
</p>
|
||||
|
||||
<h2>Requirements</h2>
|
||||
<ul>
|
||||
<li><a href='https://docker.com'>Docker</a></li>
|
||||
<li><a href='https://git-scm.com/'>Git</a></li>
|
||||
<li><a href="https://docker.com">Docker</a></li>
|
||||
<li><a href="https://git-scm.com/">Git</a></li>
|
||||
<li>
|
||||
A <a href='https://redis.com'>Redis</a>-Server (I recommend
|
||||
<a href='https://upstash.com'>Upstash</a>)
|
||||
A <a href="https://redis.com">Redis</a>-Server (I recommend
|
||||
<a href="https://upstash.com">Upstash</a>)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Installation</h2>
|
||||
<p>At first, clone the repo:</p>
|
||||
|
||||
<pre><code class='language-bash'
|
||||
>git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz</code
|
||||
></pre>
|
||||
<pre><code class="language-bash"
|
||||
>git clone https://github.com/mawoka-myblock/classquiz && cd ClassQuiz</code
|
||||
></pre>
|
||||
<p>
|
||||
Now, set a <b>VALID</b> Redis-URI in <code>frontend/Dockerfile</code> and, if you want Sentry,
|
||||
set a valid Sentry-DSN.
|
||||
@@ -49,25 +58,29 @@
|
||||
<h2>Configuration</h2>
|
||||
<h3>Storage Provider</h3>
|
||||
<p>
|
||||
You'll have to set up a storage provider for some pictures (these getting imported from KAHOOT!). For now, you
|
||||
can use <a href='https://deta.sh'>Deta</a> or the local filesystem. Please note that I would <b>NOT</b> use it
|
||||
because of these funny path-things. I tried to prevent these attacks, but i really wouldn't trust it.
|
||||
You'll have to set the <code>STORAGE_BACKEND</code>-environment-variable to either <code>deta</code> or <code>local</code>.
|
||||
You'll have to set up a storage provider for some pictures (these getting imported from
|
||||
KAHOOT!). For now, you can use <a href="https://deta.sh">Deta</a> or the local filesystem.
|
||||
Please note that I would <b>NOT</b> use it because of these funny path-things. I tried to
|
||||
prevent these attacks, but i really wouldn't trust it. You'll have to set the
|
||||
<code>STORAGE_BACKEND</code>-environment-variable to either <code>deta</code> or
|
||||
<code>local</code>.
|
||||
</p>
|
||||
<h4>If you chose Deta...</h4>
|
||||
<p>
|
||||
...you'll also have to set the <code>DETA_PROJECT_KEY</code> and the <code>DETA_PROJECT_ID</code>.
|
||||
...you'll also have to set the <code>DETA_PROJECT_KEY</code> and the
|
||||
<code>DETA_PROJECT_ID</code>.
|
||||
</p>
|
||||
<h4>If you chose the local filesystem...</h4>
|
||||
<p>
|
||||
...you'll have to set the <code>STORAGE_PATH</code> enviromnent variable. The path must be absolute (so start with a <code>/</code>).
|
||||
...you'll have to set the <code>STORAGE_PATH</code> enviromnent variable. The path must be
|
||||
absolute (so start with a <code>/</code>).
|
||||
</p>
|
||||
<p>
|
||||
Before you can start your stack, you have to set some environment-variables in your
|
||||
<code>docker-compose.yml</code>.
|
||||
</p>
|
||||
<pre><code class='language-yaml'
|
||||
>version: "3"
|
||||
<pre><code class="language-yaml"
|
||||
>version: "3"
|
||||
|
||||
services:
|
||||
frontend:
|
||||
@@ -143,5 +156,5 @@ volumes:
|
||||
data:
|
||||
</code></pre>
|
||||
<p>Now build and deploy:</p>
|
||||
<pre><code class='language-bash'>docker compose build && docker compose up -d</code></pre>
|
||||
<pre><code class="language-bash">docker compose build && docker compose up -d</code></pre>
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user