Quicksave

This commit is contained in:
Mawoka
2025-08-22 12:33:15 +02:00
parent bd659895ad
commit 51f1d74cf2
45 changed files with 15682 additions and 2572 deletions
-23
View File
@@ -1,23 +0,0 @@
<!--
SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { browser } from '$app/environment';
import { Map, Marker } from '@beyonk/svelte-mapbox';
export let lng: number;
export let lat: number;
export let markerText: string;
export let zoom = 12;
let center: [number, number];
$: center = [lng, lat];
</script>
{#if browser}
<Map accessToken={import.meta.env.VITE_MAPBOX_ACCESS_TOKEN} bind:center bind:zoom>
<Marker bind:lat bind:lng bind:label={markerText} />
</Map>
{/if}
+3 -2
View File
@@ -45,7 +45,7 @@ export class I18nService {
initialize(): void {
this.i18n.use(LanguageDetector).init({
// lng: INITIAL_LANGUAGE,
compatibilityJSON: 'v3',
compatibilityJSON: 'v4',
fallbackLng: 'en',
debug: false,
defaultNS: 'translation',
@@ -61,7 +61,8 @@ export class I18nService {
detection: {
order: ['querystring', 'cookie', 'localStorage', 'navigator'],
lookupQuerystring: 'lng',
lookupLocalStorage: 'language'
lookupLocalStorage: 'language',
lookupSessionStorage: true
}
});
this.i18n.addResourceBundle('en', 'translation', en);
+32 -2
View File
@@ -5,7 +5,19 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import BalloonEditor from '@ckeditor/ckeditor5-build-balloon';
import {
BalloonEditor,
Essentials,
Autoformat,
Bold,
Italic,
Paragraph,
TextTransformation,
Superscript,
Subscript,
Strikethrough
} from 'ckeditor5';
import 'ckeditor5/ckeditor5.css';
// import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
// import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold.js';
// import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic.js';
@@ -54,8 +66,26 @@ SPDX-License-Identifier: MPL-2.0
};*/
let editor;
onMount(() => {
class Editor extends BalloonEditor {
static builtinPlugins = [
Essentials,
Autoformat,
Bold,
Italic,
Paragraph,
TextTransformation,
Strikethrough,
Subscript,
Superscript
];
static defaultConfig = {
language: 'en'
};
}
// BalloonEditor.builtinPlugins = [Strikethrough]
BalloonEditor.create(html_el, {
Editor.create(html_el, {
licenseKey: 'GPL',
// plugins: [Strikethrough],
config: {
enterMode: BalloonEditor.ENTER_DIV,
@@ -29,7 +29,9 @@ SPDX-License-Identifier: MPL-2.0
const redirect_back = (done_var: boolean) => {
if (done_var) {
window.location.reload();
setTimeout(() => {
window.location.reload();
}, 100);
}
};
let alertModalOpen = false;
@@ -32,6 +32,7 @@ SPDX-License-Identifier: MPL-2.0
body: JSON.stringify({ auth_type: 'BACKUP', data: backup_code })
});
if (res.status === 200) {
window.location.reload();
done = true;
} else {
step += 1;
@@ -28,6 +28,7 @@ SPDX-License-Identifier: MPL-2.0
body: JSON.stringify({ auth_type: 'PASSWORD', data: password })
});
if (res.status === 200) {
window.location.reload();
done = true;
} else if (res.status === 202) {
step += 1;
@@ -36,6 +36,7 @@ SPDX-License-Identifier: MPL-2.0
}
);
if (res.status === 200) {
window.location.reload();
done = true;
} else if (res.status === 202) {
step += 1;
@@ -22,7 +22,7 @@ SPDX-License-Identifier: MPL-2.0
let asseResp;
isLoading = true;
try {
asseResp = await startAuthentication(data);
asseResp = await startAuthentication({ optionsJSON: data });
} catch (e) {
console.error(e);
/* alertModal.set({
@@ -44,6 +44,7 @@ SPDX-License-Identifier: MPL-2.0
}
);
if (res.status === 200) {
window.location.reload();
done = true;
} else if (res.status === 202) {
step += 1;
@@ -14,8 +14,6 @@ SPDX-License-Identifier: MPL-2.0
const { t } = getLocalization();
let showMap = false;
interface UserAccount {
id: string;
email: string;
@@ -133,19 +131,6 @@ SPDX-License-Identifier: MPL-2.0
return `${result.browser.name} ${result.browser.version} (${result.os.name})`;
};
const checkLocation = async (session_ip: string) => {
const res = await fetch(`/api/v1/utils/ip-lookup/${session_ip}`);
const json = await res.json();
console.log(json.status, json.status === 'fail');
if (json.status === 'fail') {
alert('This feature is kinda broken...');
return;
} else {
locationData = await res.json();
showMap = true;
}
};
const deleteSession = async (session_id: string) => {
const res = await fetch(`/api/v1/users/sessions/${session_id}`, {
method: 'DELETE'
@@ -275,12 +260,6 @@ SPDX-License-Identifier: MPL-2.0
>
{$t('words.browser')}
</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('settings_page.check_location')}
</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"
@@ -313,15 +292,6 @@ SPDX-License-Identifier: MPL-2.0
>
{getFormattedUserAgent(session.user_agent)}
</td>
<td
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
>
<button
on:click={() => {
checkLocation(session.ip_address);
}}>{$t('words.view')}</button
>
</td>
<td
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
>
@@ -334,7 +304,7 @@ SPDX-License-Identifier: MPL-2.0
<td
class="py-4 px-6 text-sm text-gray-500 whitespace-nowrap dark:text-gray-400"
>
{#if session.id === this_session.id}
{#if session.id === this_session?.id}
{:else}
@@ -345,26 +315,3 @@ SPDX-License-Identifier: MPL-2.0
</tbody>
</table>
{/await}
<div class="w-5/6 h-5/6 z-20 absolute top-10 pt-16 left-28" class:hidden={!showMap}>
{#if showMap}
{#await import('$lib/Map.svelte')}
<Spinner />
{:then c}
<button
on:click={() => {
showMap = false;
}}
class="bg-black text-white rounded-t-lg px-1">{$t('words.close')}</button
>
<div class="w-full h-full">
<svelte:component
this={c.default}
lat={locationData.lat}
lng={locationData.lon}
markerText={'Somewhere here was this session registered.'}
/>
</div>
{/await}
{/if}
</div>
@@ -73,7 +73,7 @@ SPDX-License-Identifier: MPL-2.0
for (let i = 0; i++; i < resp_data.excludeCredentials.length) {
resp_data.excludeCredentials[i].transports = undefined;
}
attResp = await startRegistration(resp_data);
attResp = await startRegistration({ optionsJSON: resp_data });
} catch (e) {
throw e;
}
@@ -66,7 +66,6 @@ SPDX-License-Identifier: MPL-2.0
items_to_show = all_items;
} else {
const res = fuse.search(search_term);
console.log(res, 'search_res');
items_to_show = [];
for (const quiz_data of res) {
items_to_show.push(quiz_data.item);
@@ -102,7 +102,7 @@ SPDX-License-Identifier: MPL-2.0
</li>
<li>
Add the following line to your <code>/etc/hosts</code>-file, so you can visit ClassQuiz
via <code>test.com</code> (Required for the Captcha and Mapbox)
via <code>test.com</code> (Required for the Captcha)
<pre><code>127.0.0.1 test.com</code></pre>
Now you can visit ClassQuiz at<a
@@ -74,7 +74,6 @@ SPDX-License-Identifier: MPL-2.0
>:
</p>
<ul>
<li><code>VITE_MAPBOX_ACCESS_TOKEN</code>: A Mapbox-token which is optional.</li>
<li><code>VITE_HCAPTCHA</code>: The hCaptcha-Siteky for captchas</li>
<li>
<code>VITE_CAPTCHA_ENABLED</code>: Set it to <code>true</code>, if the captcha should be