2024-08-01 18:09:35 +02:00
|
|
|
<script lang="ts">
|
|
|
|
|
import { enhance } from "$app/forms";
|
|
|
|
|
import WebsiteEditor from "$lib/components/WebsiteEditor.svelte";
|
2024-08-19 19:31:41 +02:00
|
|
|
import { ALLOWED_MIME_TYPES, handleImagePaste } from "$lib/utils";
|
2024-08-02 16:36:21 +02:00
|
|
|
import SuccessOrError from "$lib/components/SuccessOrError.svelte";
|
2024-08-20 19:17:05 +02:00
|
|
|
import type { ActionData, LayoutServerData, PageServerData } from "./$types";
|
2024-08-09 16:17:33 +02:00
|
|
|
import Modal from "$lib/components/Modal.svelte";
|
2024-09-07 14:28:23 +02:00
|
|
|
import LoadingSpinner from "$lib/components/LoadingSpinner.svelte";
|
2024-07-31 07:23:32 +02:00
|
|
|
|
2024-08-20 19:17:05 +02:00
|
|
|
const { data, form }: { data: PageServerData & LayoutServerData; form: ActionData } = $props();
|
2024-08-17 16:05:14 +02:00
|
|
|
|
|
|
|
|
let previewContent = $state(data.home.main_content);
|
|
|
|
|
let mainContentTextarea: HTMLTextAreaElement;
|
|
|
|
|
let textareaScrollTop = $state(0);
|
|
|
|
|
|
|
|
|
|
const updateScrollPercentage = () => {
|
|
|
|
|
const { scrollTop, scrollHeight, clientHeight } = mainContentTextarea;
|
|
|
|
|
textareaScrollTop = (scrollTop / (scrollHeight - clientHeight)) * 100;
|
|
|
|
|
};
|
2024-08-19 19:31:41 +02:00
|
|
|
|
|
|
|
|
const handlePaste = async (event: ClipboardEvent) => {
|
2024-08-19 20:33:23 +02:00
|
|
|
const newContent = await handleImagePaste(event, data.API_BASE_PREFIX);
|
2024-08-20 19:17:05 +02:00
|
|
|
|
|
|
|
|
if (newContent) {
|
|
|
|
|
previewContent = newContent;
|
|
|
|
|
}
|
2024-08-19 19:31:41 +02:00
|
|
|
};
|
2024-09-07 14:28:23 +02:00
|
|
|
|
|
|
|
|
let sending = $state(false);
|
2024-08-01 18:09:35 +02:00
|
|
|
</script>
|
2024-07-31 07:23:32 +02:00
|
|
|
|
2024-08-02 16:36:21 +02:00
|
|
|
<SuccessOrError success={form?.success} message={form?.message} />
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-09-07 14:28:23 +02:00
|
|
|
{#if sending}
|
|
|
|
|
<LoadingSpinner />
|
|
|
|
|
{/if}
|
|
|
|
|
|
2024-08-01 18:09:35 +02:00
|
|
|
<WebsiteEditor
|
|
|
|
|
id={data.website.id}
|
2024-08-27 16:39:29 +02:00
|
|
|
contentType={data.website.content_type}
|
2024-08-01 18:09:35 +02:00
|
|
|
title={data.website.title}
|
2024-09-08 16:42:32 +02:00
|
|
|
previewContent={previewContent ||
|
|
|
|
|
"Put some markdown content in main content to see a live preview here"}
|
2024-08-17 16:05:14 +02:00
|
|
|
previewScrollTop={textareaScrollTop}
|
2024-08-01 18:09:35 +02:00
|
|
|
>
|
2024-08-24 21:43:15 +02:00
|
|
|
<section id="global">
|
|
|
|
|
<h2>
|
|
|
|
|
<a href="#global">Global</a>
|
|
|
|
|
</h2>
|
2024-08-02 15:33:18 +02:00
|
|
|
<form
|
|
|
|
|
action="?/updateGlobal"
|
|
|
|
|
method="POST"
|
|
|
|
|
enctype="multipart/form-data"
|
|
|
|
|
use:enhance={() => {
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = true;
|
2024-08-02 15:33:18 +02:00
|
|
|
return async ({ update }) => {
|
|
|
|
|
await update({ reset: false });
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = false;
|
2024-08-02 15:33:18 +02:00
|
|
|
};
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<label>
|
|
|
|
|
Light accent color:
|
|
|
|
|
<input
|
|
|
|
|
type="color"
|
|
|
|
|
name="accent-color-light"
|
|
|
|
|
value={data.globalSettings.accent_color_light_theme}
|
2024-08-05 16:03:07 +02:00
|
|
|
pattern="\S(.*\S)?"
|
|
|
|
|
required
|
2024-08-02 15:33:18 +02:00
|
|
|
/>
|
|
|
|
|
</label>
|
|
|
|
|
<label>
|
2024-08-03 18:07:27 +02:00
|
|
|
Dark accent color:
|
2024-08-02 15:33:18 +02:00
|
|
|
<input
|
|
|
|
|
type="color"
|
|
|
|
|
name="accent-color-dark"
|
|
|
|
|
value={data.globalSettings.accent_color_dark_theme}
|
2024-08-05 16:03:07 +02:00
|
|
|
pattern="\S(.*\S)?"
|
|
|
|
|
required
|
2024-08-02 15:33:18 +02:00
|
|
|
/>
|
|
|
|
|
</label>
|
2024-08-09 16:17:33 +02:00
|
|
|
<div class="file-field">
|
|
|
|
|
<label>
|
|
|
|
|
Favicon:
|
|
|
|
|
<input type="file" name="favicon" accept={ALLOWED_MIME_TYPES.join(", ")} />
|
|
|
|
|
</label>
|
2024-08-10 17:09:12 +02:00
|
|
|
{#if data.globalSettings.favicon_image}
|
2024-08-09 16:17:33 +02:00
|
|
|
<Modal id="preview-favicon-global-{data.globalSettings.website_id}" text="Preview">
|
2024-08-14 19:33:41 +02:00
|
|
|
<img
|
2024-08-19 20:33:23 +02:00
|
|
|
src={`${data.API_BASE_PREFIX}/rpc/retrieve_file?id=${data.globalSettings.favicon_image}`}
|
2024-08-14 19:33:41 +02:00
|
|
|
alt=""
|
|
|
|
|
/>
|
2024-08-09 16:17:33 +02:00
|
|
|
</Modal>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<button type="submit">Submit</button>
|
|
|
|
|
</form>
|
|
|
|
|
</section>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-24 21:43:15 +02:00
|
|
|
<section id="header">
|
|
|
|
|
<h2>
|
|
|
|
|
<a href="#header">Header</a>
|
|
|
|
|
</h2>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<form
|
|
|
|
|
action="?/updateHeader"
|
|
|
|
|
method="POST"
|
|
|
|
|
enctype="multipart/form-data"
|
|
|
|
|
use:enhance={() => {
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = true;
|
2024-08-02 15:33:18 +02:00
|
|
|
return async ({ update }) => {
|
|
|
|
|
await update({ reset: false });
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = false;
|
2024-08-02 15:33:18 +02:00
|
|
|
};
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<label>
|
|
|
|
|
Logo type:
|
|
|
|
|
<select name="logo-type">
|
|
|
|
|
<option value="text" selected={"text" === data.header.logo_type}>Text</option>
|
|
|
|
|
<option value="image" selected={"image" === data.header.logo_type}>Image</option>
|
|
|
|
|
</select>
|
|
|
|
|
</label>
|
|
|
|
|
<label>
|
|
|
|
|
Logo text:
|
2024-08-05 16:03:07 +02:00
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
name="logo-text"
|
|
|
|
|
value={data.header.logo_text}
|
|
|
|
|
pattern="\S(.*\S)?"
|
|
|
|
|
required={data.header.logo_type === "text"}
|
|
|
|
|
/>
|
2024-08-02 15:33:18 +02:00
|
|
|
</label>
|
2024-08-09 16:17:33 +02:00
|
|
|
<div class="file-field">
|
|
|
|
|
<label>
|
|
|
|
|
Logo image:
|
2024-08-30 15:48:15 +02:00
|
|
|
<input type="file" name="logo-image" accept={ALLOWED_MIME_TYPES.join(", ")} />
|
2024-08-09 16:17:33 +02:00
|
|
|
</label>
|
2024-08-10 17:09:12 +02:00
|
|
|
{#if data.header.logo_image}
|
2024-08-09 16:17:33 +02:00
|
|
|
<Modal id="preview-logo-header-{data.header.website_id}" text="Preview">
|
2024-08-19 20:33:23 +02:00
|
|
|
<img
|
|
|
|
|
src={`${data.API_BASE_PREFIX}/rpc/retrieve_file?id=${data.header.logo_image}`}
|
|
|
|
|
alt=""
|
|
|
|
|
/>
|
2024-08-09 16:17:33 +02:00
|
|
|
</Modal>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<button type="submit">Submit</button>
|
|
|
|
|
</form>
|
|
|
|
|
</section>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-24 21:43:15 +02:00
|
|
|
<section id="home">
|
|
|
|
|
<h2>
|
|
|
|
|
<a href="#home">Home</a>
|
|
|
|
|
</h2>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<form
|
|
|
|
|
action="?/updateHome"
|
|
|
|
|
method="POST"
|
|
|
|
|
use:enhance={() => {
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = true;
|
2024-08-02 15:33:18 +02:00
|
|
|
return async ({ update }) => {
|
|
|
|
|
await update({ reset: false });
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = false;
|
2024-08-02 15:33:18 +02:00
|
|
|
};
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<label>
|
|
|
|
|
Main content:
|
2024-08-17 16:05:14 +02:00
|
|
|
<textarea
|
|
|
|
|
name="main-content"
|
|
|
|
|
rows="20"
|
|
|
|
|
bind:value={previewContent}
|
|
|
|
|
bind:this={mainContentTextarea}
|
|
|
|
|
onscroll={updateScrollPercentage}
|
2024-08-19 19:31:41 +02:00
|
|
|
onpaste={handlePaste}
|
2024-08-17 16:05:14 +02:00
|
|
|
required>{data.home.main_content}</textarea
|
|
|
|
|
>
|
2024-08-02 15:33:18 +02:00
|
|
|
</label>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<button type="submit">Submit</button>
|
|
|
|
|
</form>
|
|
|
|
|
</section>
|
|
|
|
|
|
2024-08-24 21:43:15 +02:00
|
|
|
<section id="footer">
|
|
|
|
|
<h2>
|
|
|
|
|
<a href="#footer">Footer</a>
|
|
|
|
|
</h2>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<form
|
|
|
|
|
action="?/updateFooter"
|
|
|
|
|
method="POST"
|
|
|
|
|
use:enhance={() => {
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = true;
|
2024-08-02 15:33:18 +02:00
|
|
|
return async ({ update }) => {
|
|
|
|
|
await update({ reset: false });
|
2024-09-07 14:28:23 +02:00
|
|
|
sending = false;
|
2024-08-02 15:33:18 +02:00
|
|
|
};
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<label>
|
|
|
|
|
Additional text:
|
2024-08-05 16:03:07 +02:00
|
|
|
<textarea name="additional-text" rows="5" maxlength="250" required
|
|
|
|
|
>{data.footer.additional_text}</textarea
|
|
|
|
|
>
|
2024-08-02 15:33:18 +02:00
|
|
|
</label>
|
2024-08-01 18:09:35 +02:00
|
|
|
|
2024-08-02 15:33:18 +02:00
|
|
|
<button type="submit">Submit</button>
|
|
|
|
|
</form>
|
2024-08-01 18:09:35 +02:00
|
|
|
</section>
|
|
|
|
|
</WebsiteEditor>
|