🔀 Merged slides into master
This commit is contained in:
+15
-1
@@ -14,7 +14,20 @@ from classquiz.db import database
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from classquiz.oauth import rememberme_middleware
|
from classquiz.oauth import rememberme_middleware
|
||||||
from classquiz.routers import users, quiz, utils, stats, storage, search, testing_routes, editor, live, eximport, login
|
from classquiz.routers import (
|
||||||
|
users,
|
||||||
|
quiz,
|
||||||
|
utils,
|
||||||
|
stats,
|
||||||
|
storage,
|
||||||
|
search,
|
||||||
|
testing_routes,
|
||||||
|
editor,
|
||||||
|
live,
|
||||||
|
eximport,
|
||||||
|
login,
|
||||||
|
sitemap,
|
||||||
|
)
|
||||||
from classquiz.socket_server import sio
|
from classquiz.socket_server import sio
|
||||||
from classquiz.helpers import meilisearch_init, telemetry_ping, bg_tasks
|
from classquiz.helpers import meilisearch_init, telemetry_ping, bg_tasks
|
||||||
from scheduler.asyncio import Scheduler
|
from scheduler.asyncio import Scheduler
|
||||||
@@ -82,4 +95,5 @@ app.include_router(
|
|||||||
)
|
)
|
||||||
app.include_router(editor.router, tags=["editor"], prefix="/api/v1/editor", include_in_schema=True)
|
app.include_router(editor.router, tags=["editor"], prefix="/api/v1/editor", include_in_schema=True)
|
||||||
app.include_router(eximport.router, tags=["export", "import"], prefix="/api/v1/eximport", include_in_schema=True)
|
app.include_router(eximport.router, tags=["export", "import"], prefix="/api/v1/eximport", include_in_schema=True)
|
||||||
|
app.include_router(sitemap.router, tags=["sitemap"], prefix="/api/v1/sitemap", include_in_schema=True)
|
||||||
app.mount("/", ASGIApp(sio))
|
app.mount("/", ASGIApp(sio))
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# 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 datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Response
|
||||||
|
from jinja2 import Template
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from classquiz.config import redis, settings
|
||||||
|
from classquiz.db import database
|
||||||
|
|
||||||
|
settings = settings()
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
sitemap_template = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
{% for entry in pages -%}
|
||||||
|
<url>
|
||||||
|
<loc>{{ root_address}}/view/{{ entry.id.hex }}</loc>
|
||||||
|
{%- if entry.updated_at != None -%}
|
||||||
|
<lastmod>{{ entry.updated_at.strftime("%Y-%m-%d") }}</lastmod>
|
||||||
|
{% endif %}
|
||||||
|
</url>
|
||||||
|
{%- endfor %}
|
||||||
|
</urlset>"""
|
||||||
|
|
||||||
|
|
||||||
|
sql_statement_metadata = """
|
||||||
|
SELECT id, title, description, updated_at from quiz where public ='t'
|
||||||
|
"""
|
||||||
|
|
||||||
|
sql_statement_id_and_modified_only = """
|
||||||
|
SELECT id, updated_at from quiz where public ='t'
|
||||||
|
"""
|
||||||
|
|
||||||
|
template = Template(sitemap_template, enable_async=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SitemapQuiz(BaseModel):
|
||||||
|
id: uuid.UUID
|
||||||
|
updated_at: datetime.datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/get")
|
||||||
|
async def get_sitemap():
|
||||||
|
redis_cache_resp = await redis.get("sitemap")
|
||||||
|
if redis_cache_resp is None:
|
||||||
|
res = await database.fetch_all(sql_statement_id_and_modified_only)
|
||||||
|
entries = []
|
||||||
|
for i in res:
|
||||||
|
entries.append(SitemapQuiz.from_orm(i))
|
||||||
|
rendered_sitemap = await template.render_async({"pages": entries, "root_address": settings.root_address})
|
||||||
|
await redis.set("sitemap", rendered_sitemap, ex=86400)
|
||||||
|
return Response(content=rendered_sitemap, media_type="application/xml")
|
||||||
|
else:
|
||||||
|
return Response(content=redis_cache_resp, media_type="application/xml")
|
||||||
@@ -11,8 +11,6 @@
|
|||||||
import SettingsCard from '$lib/editor/settings-card.svelte';
|
import SettingsCard from '$lib/editor/settings-card.svelte';
|
||||||
import QuizCard from '$lib/editor/card.svelte';
|
import QuizCard from '$lib/editor/card.svelte';
|
||||||
import Spinner from './Spinner.svelte';
|
import Spinner from './Spinner.svelte';
|
||||||
import { elementSelection } from '$lib/stores.js';
|
|
||||||
import ElementSelection from '$lib/editor/slides/element_selection.svelte';
|
|
||||||
|
|
||||||
let schemaInvalid = false;
|
let schemaInvalid = false;
|
||||||
let yupErrorMessage = '';
|
let yupErrorMessage = '';
|
||||||
@@ -191,7 +189,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
{#if $elementSelection.data === null}
|
|
||||||
<ElementSelection />
|
|
||||||
{/if}
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
import Spinner from '../Spinner.svelte';
|
import Spinner from '../Spinner.svelte';
|
||||||
import { createTippy } from 'svelte-tippy';
|
import { createTippy } from 'svelte-tippy';
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
// import Slide from './slide.svelte';
|
import Slide from './slide.svelte';
|
||||||
|
|
||||||
const { t } = getLocalization();
|
const { t } = getLocalization();
|
||||||
|
|
||||||
@@ -50,8 +50,6 @@
|
|||||||
data.questions[selected_question].type = QuizQuestionType.ABCD;
|
data.questions[selected_question].type = QuizQuestionType.ABCD;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$: console.log();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full max-h-full pb-20 px-20 h-full">
|
<div class="w-full max-h-full pb-20 px-20 h-full">
|
||||||
@@ -69,13 +67,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if data.questions[selected_question].type === QuizQuestionType.SLIDE}
|
{#if data.questions[selected_question].time}
|
||||||
{#await import('./slide.svelte')}
|
|
||||||
<Spinner my_20={false} />
|
|
||||||
{:then c}
|
|
||||||
<svelte:component this={c.default} bind:data={data.questions[selected_question]} />
|
|
||||||
{/await}
|
|
||||||
{:else}
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex justify-center pt-10 w-full">
|
<div class="flex justify-center pt-10 w-full">
|
||||||
{#await import('$lib/inline-editor.svelte')}
|
{#await import('$lib/inline-editor.svelte')}
|
||||||
@@ -187,6 +179,8 @@
|
|||||||
{$t('editor_page.right_click_to_delete')}
|
{$t('editor_page.right_click_to_delete')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Slide bind:data={data.questions[selected_question]} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export interface EditorData {
|
|||||||
public: boolean;
|
public: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
questions: (Question | object)[];
|
questions: Question[];
|
||||||
cover_image?: string;
|
cover_image?: string;
|
||||||
background_color?: string;
|
background_color?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ export const signedIn = writable(false);
|
|||||||
export const pathname = writable('/');
|
export const pathname = writable('/');
|
||||||
|
|
||||||
export const alertModal = writable({ open: false, title: '', body: '' });
|
export const alertModal = writable({ open: false, title: '', body: '' });
|
||||||
export const elementSelection = writable({ data: undefined });
|
|
||||||
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|||||||
Reference in New Issue
Block a user