✨ Added newsletter and small fixes
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { EditorData, Answer } from '$lib/quiz_types';
|
||||
import CheckerBg from '$lib/editor/checker-bg.svg';
|
||||
import { reach } from 'yup';
|
||||
import { dataSchema } from '$lib/yupSchemas';
|
||||
import Spinner from '../Spinner.svelte';
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
class:dark:bg-green-500={index === selected_question}
|
||||
on:contextmenu|preventDefault={() => {
|
||||
if (confirm('Do you really want to delete this Question?')) {
|
||||
selected_question = selected_question - 1;
|
||||
data.questions.splice(index, 1);
|
||||
data.questions = data.questions;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<script lang="ts">
|
||||
export let open: boolean;
|
||||
|
||||
const closeThing = () => {
|
||||
open = false;
|
||||
localStorage.setItem('newsletter', 'closed');
|
||||
};
|
||||
</script>
|
||||
|
||||
<form method="post" action="https://newsletter.mawoka.eu/subscription/form" class="bg-transparent">
|
||||
<div class="absolute top-1 right-1">
|
||||
<button type="button" on:click={closeThing}>
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
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="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-semibold">ClassQuiz-Newsletter</h3>
|
||||
<input type="hidden" name="nonce" />
|
||||
<p>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
required
|
||||
placeholder="E-mail"
|
||||
class="m-0.5 border-b-2 border-gray-300 rounded-lg p-0.5 outline-none focus:outline-gray-400 bg-transparent"
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="Name (optional)"
|
||||
class="m-0.5 border-b-2 border-gray-300 rounded-lg p-0.5 outline-none focus:outline-gray-400 bg-transparent"
|
||||
/>
|
||||
</p>
|
||||
|
||||
<p class="hidden">
|
||||
<input
|
||||
id="fec55"
|
||||
type="checkbox"
|
||||
name="l"
|
||||
checked
|
||||
value="fec5595e-9af1-497a-b7eb-1edd7ad2e21c"
|
||||
/>
|
||||
<label for="fec55">ClassQuiz-News</label>
|
||||
</p>
|
||||
<div class="bg-gradient-to-r from-[#009444] via-[#39b54a] to-[#8dc63f] w-fit rounded-lg">
|
||||
<button
|
||||
type="submit"
|
||||
class="m-0.5 bg-opacity-70 bg-white rounded-lg py-0.5 px-1 text-black"
|
||||
>Subscribe!
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -15,8 +15,11 @@
|
||||
import Footer from '$lib/footer.svelte';
|
||||
import WebPOpenGraph from '$lib/assets/landing/opengraph-home.webp';
|
||||
import JpgOpenGraph from '$lib/assets/landing/opengraph-home.jpg';
|
||||
import Newsletter from '$lib/landing/newsletter.svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
|
||||
import LandingPromo from '$lib/landing/landing-promo.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const { t } = getLocalization();
|
||||
|
||||
@@ -31,6 +34,11 @@
|
||||
const response = await fetch('/api/v1/stats/combined');
|
||||
return await response.json();
|
||||
};
|
||||
let newsletterModalOpen;
|
||||
onMount(() => {
|
||||
const ls = localStorage.getItem('newsletter');
|
||||
newsletterModalOpen = ls === null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -108,5 +116,12 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{#if newsletterModalOpen}
|
||||
<div
|
||||
class="fixed bottom-8 right-5 bg-white rounded-lg h-fit w-11/12 ml-5 lg:w-2/12 z-50 p-2 bg-white dark:bg-gray-700"
|
||||
transition:fly
|
||||
>
|
||||
<Newsletter bind:open={newsletterModalOpen} />
|
||||
</div>
|
||||
{/if}
|
||||
<Footer />
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import asyncio
|
||||
|
||||
from classquiz.config import settings, redis, storage
|
||||
from classquiz.storage.errors import DeletionFailedError
|
||||
|
||||
settings = settings()
|
||||
|
||||
|
||||
async def main():
|
||||
edit_sessions = await redis.smembers("edit_sessions")
|
||||
for session_id in edit_sessions:
|
||||
session = await redis.get(f"edit_session:{session_id}")
|
||||
if session is None:
|
||||
images = await redis.lrange(f"edit_session:{session_id}:images", 0, 3000)
|
||||
if len(images) != 0:
|
||||
try:
|
||||
await storage.delete(images)
|
||||
except DeletionFailedError:
|
||||
print("Deletion Error", images)
|
||||
await redis.srem("edit_sessions", session_id)
|
||||
await redis.delete(f"edit_session:{session_id}:images")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user