mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 10:51:36 +01:00
Use SvelteKit render function for templating and add error page
This commit is contained in:
42
web-app/src/lib/templates/blog/BlogArticle.svelte
Normal file
42
web-app/src/lib/templates/blog/BlogArticle.svelte
Normal file
@@ -0,0 +1,42 @@
|
||||
<script lang="ts">
|
||||
const { title, logoType, logo, mainContent, coverImage, publicationDate, footerAdditionalText } =
|
||||
$props<{
|
||||
title: string;
|
||||
logoType: "text" | "image";
|
||||
logo: string;
|
||||
mainContent: string;
|
||||
coverImage: string;
|
||||
publicationDate: string;
|
||||
footerAdditionalText: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
</svelte:head>
|
||||
|
||||
<nav>
|
||||
{#if logoType === "text"}
|
||||
<p>
|
||||
<strong>{logo}</strong>
|
||||
</p>
|
||||
{:else}
|
||||
<img src={logo} alt="" />
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<header>
|
||||
<img src={coverImage} alt="" />
|
||||
<h1>{title}</h1>
|
||||
<p>{publicationDate}</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{@html mainContent}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
{footerAdditionalText}
|
||||
</footer>
|
||||
57
web-app/src/lib/templates/blog/BlogIndex.svelte
Normal file
57
web-app/src/lib/templates/blog/BlogIndex.svelte
Normal file
@@ -0,0 +1,57 @@
|
||||
<script lang="ts">
|
||||
const { title, logoType, logo, mainContent, articles, footerAdditionalText } = $props<{
|
||||
title: string;
|
||||
logoType: "text" | "image";
|
||||
logo: string;
|
||||
mainContent: string;
|
||||
articles: any[];
|
||||
footerAdditionalText: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
</svelte:head>
|
||||
|
||||
<nav>
|
||||
{#if logoType === "text"}
|
||||
<p>
|
||||
<strong>{logo}</strong>
|
||||
</p>
|
||||
{:else}
|
||||
<img src={logo} alt="" />
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<header>
|
||||
<h1>{title}</h1>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
{@html mainContent}
|
||||
</section>
|
||||
{#if articles.length > 0}
|
||||
<section>
|
||||
<h2>Articles</h2>
|
||||
|
||||
{#each articles as article}
|
||||
{@const articleFileName = article.title.toLowerCase().split(" ").join("-")}
|
||||
|
||||
<article>
|
||||
<p>{article.publication_date}</p>
|
||||
<h3>
|
||||
<a href="./articles/{articleFileName}.html">{article.title}</a>
|
||||
</h3>
|
||||
<p>{article.meta_description ?? "No description provided"}</p>
|
||||
</article>
|
||||
{/each}
|
||||
</section>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
{footerAdditionalText}
|
||||
</footer>
|
||||
7
web-app/src/routes/(authenticated)/+error.svelte
Normal file
7
web-app/src/routes/(authenticated)/+error.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<h1>Not found or access denied</h1>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { LayoutServerLoad } from "./$types";
|
||||
import { API_BASE_PREFIX } from "$lib/utils";
|
||||
import { error } from "@sveltejs/kit";
|
||||
|
||||
export const load: LayoutServerLoad = async ({ params, fetch, cookies }) => {
|
||||
const websiteData = await fetch(`${API_BASE_PREFIX}/website?id=eq.${params.websiteId}`, {
|
||||
@@ -11,6 +12,10 @@ export const load: LayoutServerLoad = async ({ params, fetch, cookies }) => {
|
||||
}
|
||||
});
|
||||
|
||||
if (!websiteData.ok) {
|
||||
throw error(404, "Website not found");
|
||||
}
|
||||
|
||||
const homeData = await fetch(`${API_BASE_PREFIX}/home?website_id=eq.${params.websiteId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { readFile, mkdir, writeFile } from "node:fs/promises";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { md } from "$lib/utils";
|
||||
import type { Actions, PageServerLoad } from "./$types";
|
||||
import { API_BASE_PREFIX, NGINX_BASE_PREFIX } from "$lib/utils";
|
||||
import { render } from "svelte/server";
|
||||
import BlogIndex from "$lib/templates/blog/BlogIndex.svelte";
|
||||
import BlogArticle from "$lib/templates/blog/BlogArticle.svelte";
|
||||
|
||||
export const load: PageServerLoad = async ({ params, fetch, cookies, locals }) => {
|
||||
export const load: PageServerLoad = async ({ params, fetch, cookies }) => {
|
||||
const websiteOverviewData = await fetch(
|
||||
`${API_BASE_PREFIX}/website_overview?id=eq.${params.websiteId}`,
|
||||
{
|
||||
@@ -41,56 +44,18 @@ export const actions: Actions = {
|
||||
};
|
||||
|
||||
const generateStaticFiles = async (websiteData: any, isPreview: boolean = true) => {
|
||||
const templatePath = join(
|
||||
process.cwd(),
|
||||
"..",
|
||||
"templates",
|
||||
websiteData.content_type.toLowerCase()
|
||||
);
|
||||
|
||||
const indexFile = await readFile(join(templatePath, "index.html"), { encoding: "utf-8" });
|
||||
const articleFile = await readFile(join(templatePath, "article.html"), {
|
||||
encoding: "utf-8"
|
||||
const { head, body } = render(BlogIndex, {
|
||||
props: {
|
||||
title: websiteData.title,
|
||||
logoType: websiteData.logo_type,
|
||||
logo: websiteData.logo_text,
|
||||
mainContent: md.render(websiteData.main_content ?? ""),
|
||||
articles: websiteData.articles ?? [],
|
||||
footerAdditionalText: websiteData.additional_text ?? ""
|
||||
}
|
||||
});
|
||||
const stylesFile = await readFile(join(templatePath, "styles.css"), { encoding: "utf-8" });
|
||||
|
||||
const indexFileContents = indexFile
|
||||
.replace(
|
||||
"{{logo}}",
|
||||
websiteData.logo_type === "text"
|
||||
? `<strong>${websiteData.logo_text}</strong>`
|
||||
: `<img src="https://picsum.photos/32/32" />`
|
||||
)
|
||||
.replace("{{title}}", `<h1>${websiteData.title}</h1>`)
|
||||
.replace("{{main_content}}", md.render(websiteData.main_content ?? ""))
|
||||
.replace(
|
||||
"{{articles}}",
|
||||
Array.isArray(websiteData.articles) && websiteData.articles.length > 0
|
||||
? `
|
||||
<h2>Articles</h2>
|
||||
${websiteData.articles
|
||||
.map(
|
||||
(article: { title: string; publication_date: string; meta_description: string }) => {
|
||||
const articleFileName = article.title.toLowerCase().split(" ").join("-");
|
||||
|
||||
return `
|
||||
<article>
|
||||
<p>${article.publication_date}</p>
|
||||
<h3>
|
||||
<a href="./articles/${articleFileName}.html">
|
||||
${article.title}
|
||||
</a>
|
||||
</h3>
|
||||
<p>${article.meta_description ?? "No description provided"}</p>
|
||||
</article>
|
||||
`;
|
||||
}
|
||||
)
|
||||
.join("")}
|
||||
`
|
||||
: "<h2>Articles</h2><p>No articles available at this time.</p>"
|
||||
)
|
||||
.replace("{{additional_text}}", md.render(websiteData.additional_text ?? ""));
|
||||
const indexFileContents = head.concat(body);
|
||||
|
||||
let uploadDir = "";
|
||||
|
||||
@@ -109,32 +74,26 @@ const generateStaticFiles = async (websiteData: any, isPreview: boolean = true)
|
||||
}
|
||||
|
||||
await mkdir(uploadDir, { recursive: true });
|
||||
|
||||
await writeFile(join(uploadDir, "index.html"), indexFileContents);
|
||||
|
||||
await mkdir(join(uploadDir, "articles"), { recursive: true });
|
||||
|
||||
for (const article of websiteData.articles ?? []) {
|
||||
const articleFileName = article.title.toLowerCase().split(" ").join("-");
|
||||
|
||||
const articleFileContents = articleFile
|
||||
.replace(
|
||||
"{{logo}}",
|
||||
websiteData.logo_type === "text"
|
||||
? `<strong>${websiteData.logo_text}</strong>`
|
||||
: `<img src="https://picsum.photos/32/32" />`
|
||||
)
|
||||
.replace(
|
||||
"{{cover_image}}",
|
||||
`<img src="${article.cover_image ? `${API_BASE_PREFIX}/rpc/retrieve_file?id=${article.cover_image}` : "https://picsum.photos/600/200"}" />`
|
||||
)
|
||||
.replace("{{title}}", `<h1>${article.title}</h1>`)
|
||||
.replace("{{publication_date}}", `<p>${article.publication_date}</p>`)
|
||||
.replace("{{main_content}}", md.render(article.main_content ?? ""))
|
||||
.replace("{{additional_text}}", md.render(websiteData.additional_text ?? ""));
|
||||
const { head, body } = render(BlogArticle, {
|
||||
props: {
|
||||
title: article.title,
|
||||
logoType: websiteData.logo_type,
|
||||
logo: websiteData.logo_text,
|
||||
coverImage: `${API_BASE_PREFIX}/rpc/retrieve_file?id=${article.cover_image}`,
|
||||
publicationDate: article.publication_date,
|
||||
mainContent: md.render(article.main_content ?? ""),
|
||||
footerAdditionalText: websiteData.additional_text ?? ""
|
||||
}
|
||||
});
|
||||
|
||||
const articleFileContents = head.concat(body);
|
||||
|
||||
await writeFile(join(uploadDir, "articles", `${articleFileName}.html`), articleFileContents);
|
||||
}
|
||||
|
||||
await writeFile(join(uploadDir, "styles.css"), stylesFile);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
const { data, children } = $props<{ data: LayoutServerData; children: Snippet }>();
|
||||
|
||||
const isProjectRoute = $derived($page.url.pathname.startsWith("/website"));
|
||||
const isProjectRoute = $derived($page.url.pathname.startsWith("/website") && !$page.error);
|
||||
const routeName = $derived(
|
||||
$page.url.pathname === "/"
|
||||
? "Dashboard"
|
||||
@@ -39,7 +39,7 @@
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{#if !isProjectRoute}
|
||||
{#if !isProjectRoute && !$page.error}
|
||||
<header>
|
||||
<h1>{routeName}</h1>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user