mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 10:51:36 +01:00
Finish base template for blog
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
-- migrate:up
|
||||
CREATE OR REPLACE VIEW api.website_overview WITH ( security_invoker = ON
|
||||
) AS
|
||||
SELECT
|
||||
w.id,
|
||||
w.user_id,
|
||||
w.content_type,
|
||||
w.title,
|
||||
s.accent_color_light_theme,
|
||||
s.accent_color_dark_theme,
|
||||
s.favicon_image,
|
||||
h.logo_type,
|
||||
h.logo_text,
|
||||
h.logo_image,
|
||||
ho.main_content,
|
||||
f.additional_text,
|
||||
(
|
||||
SELECT
|
||||
JSON_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'id', a.id, 'title', a.title, 'meta_description', a.meta_description, 'meta_author', a.meta_author, 'cover_image', a.cover_image, 'publication_date', a.publication_date, 'main_content', a.main_content, 'created_at', a.created_at, 'last_modified_at', a.last_modified_at
|
||||
)
|
||||
)
|
||||
FROM
|
||||
internal.article a
|
||||
WHERE
|
||||
a.website_id = w.id
|
||||
) AS articles,
|
||||
CASE WHEN w.content_type = 'Docs' THEN
|
||||
(
|
||||
SELECT
|
||||
JSON_OBJECT_AGG(
|
||||
COALESCE(
|
||||
category_name, 'Uncategorized'
|
||||
), articles
|
||||
)
|
||||
FROM (
|
||||
SELECT
|
||||
dc.category_name,
|
||||
dc.category_weight AS category_weight,
|
||||
JSON_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'id', a.id, 'title', a.title, 'meta_description', a.meta_description, 'meta_author', a.meta_author, 'cover_image', a.cover_image, 'publication_date', a.publication_date, 'main_content', a.main_content, 'created_at', a.created_at, 'last_modified_at', a.last_modified_at
|
||||
)
|
||||
) AS articles
|
||||
FROM
|
||||
internal.article a
|
||||
LEFT JOIN internal.docs_category dc ON a.category = dc.id
|
||||
WHERE
|
||||
a.website_id = w.id
|
||||
GROUP BY
|
||||
dc.id,
|
||||
dc.category_name,
|
||||
dc.category_weight
|
||||
ORDER BY
|
||||
category_weight DESC
|
||||
) AS categorized_articles)
|
||||
ELSE
|
||||
NULL
|
||||
END AS categorized_articles
|
||||
FROM
|
||||
internal.website w
|
||||
JOIN internal.settings s ON w.id = s.website_id
|
||||
JOIN internal.header h ON w.id = h.website_id
|
||||
JOIN internal.home ho ON w.id = ho.website_id
|
||||
JOIN internal.footer f ON w.id = f.website_id;
|
||||
|
||||
GRANT SELECT ON api.website_overview TO authenticated_user;
|
||||
|
||||
-- migrate:down
|
||||
DROP VIEW api.website_overview;
|
||||
|
||||
CREATE VIEW api.website_overview WITH ( security_invoker = ON
|
||||
) AS
|
||||
SELECT
|
||||
w.id,
|
||||
w.user_id,
|
||||
w.content_type,
|
||||
w.title,
|
||||
s.accent_color_light_theme,
|
||||
s.accent_color_dark_theme,
|
||||
s.favicon_image,
|
||||
h.logo_type,
|
||||
h.logo_text,
|
||||
h.logo_image,
|
||||
ho.main_content,
|
||||
f.additional_text,
|
||||
(
|
||||
SELECT
|
||||
JSON_AGG(
|
||||
JSON_BUILD_OBJECT(
|
||||
'title', a.title, 'meta_description', a.meta_description, 'meta_author', a.meta_author, 'cover_image', a.cover_image, 'publication_date', a.publication_date, 'main_content', a.main_content
|
||||
)
|
||||
)
|
||||
FROM
|
||||
internal.article a
|
||||
WHERE
|
||||
a.website_id = w.id
|
||||
) AS articles
|
||||
FROM
|
||||
internal.website w
|
||||
JOIN internal.settings s ON w.id = s.website_id
|
||||
JOIN internal.header h ON w.id = h.website_id
|
||||
JOIN internal.home ho ON w.id = ho.website_id
|
||||
JOIN internal.footer f ON w.id = f.website_id;
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
const {
|
||||
logoType,
|
||||
logo,
|
||||
isDocsTemplate = false
|
||||
isDocsTemplate = false,
|
||||
categorizedArticles = {},
|
||||
isIndexPage = true
|
||||
}: {
|
||||
logoType: "text" | "image";
|
||||
logo: string;
|
||||
isDocsTemplate?: boolean;
|
||||
categorizedArticles?: { [key: string]: { title: string }[] };
|
||||
isIndexPage?: boolean;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
@@ -30,9 +34,23 @@
|
||||
</svg>
|
||||
</label>
|
||||
|
||||
<ul class="docs-navigation">
|
||||
<li>nav comes here</li>
|
||||
<section id="docs-navigation" class="docs-navigation">
|
||||
<ul>
|
||||
{#each Object.keys(categorizedArticles) as key}
|
||||
<li>
|
||||
<strong>{key}</strong>
|
||||
<ul>
|
||||
{#each categorizedArticles[key] as { title }}
|
||||
{@const articleFileName = title.toLowerCase().split(" ").join("-")}
|
||||
<li>
|
||||
<a href="{isIndexPage ? './articles' : '.'}/{articleFileName}.html">{title}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
{/if}
|
||||
<a href="../">
|
||||
{#if logoType === "text"}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
logoType,
|
||||
logo,
|
||||
mainContent,
|
||||
categorizedArticles,
|
||||
coverImage,
|
||||
publicationDate,
|
||||
footerAdditionalText
|
||||
@@ -18,6 +19,7 @@
|
||||
logoType: "text" | "image";
|
||||
logo: string;
|
||||
mainContent: string;
|
||||
categorizedArticles: { [key: string]: { title: string }[] };
|
||||
coverImage: string;
|
||||
publicationDate: string;
|
||||
footerAdditionalText: string;
|
||||
@@ -26,7 +28,7 @@
|
||||
|
||||
<Head {title} {favicon} nestingLevel={1} />
|
||||
|
||||
<Nav {logoType} {logo} isDocsTemplate={true} />
|
||||
<Nav {logoType} {logo} isDocsTemplate={true} {categorizedArticles} isIndexPage={false} />
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
logo,
|
||||
mainContent,
|
||||
articles,
|
||||
categorizedArticles,
|
||||
footerAdditionalText
|
||||
}: {
|
||||
favicon: string;
|
||||
@@ -18,13 +19,14 @@
|
||||
logo: string;
|
||||
mainContent: string;
|
||||
articles: { title: string; publication_date: string; meta_description: string }[];
|
||||
categorizedArticles: { [key: string]: { title: string }[] };
|
||||
footerAdditionalText: string;
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<Head {title} {favicon} />
|
||||
|
||||
<Nav {logoType} {logo} isDocsTemplate={true} />
|
||||
<Nav {logoType} {logo} isDocsTemplate={true} {categorizedArticles} />
|
||||
|
||||
<header>
|
||||
<div class="container">
|
||||
@@ -35,30 +37,6 @@
|
||||
<main>
|
||||
<div class="container">
|
||||
{@html mainContent}
|
||||
{#if articles.length > 0}
|
||||
<section class="articles" id="articles">
|
||||
<h2>
|
||||
<a href="#articles">Articles</a>
|
||||
</h2>
|
||||
|
||||
<ul class="unpadded">
|
||||
{#each articles as article}
|
||||
{@const articleFileName = article.title.toLowerCase().split(" ").join("-")}
|
||||
<li>
|
||||
<p>{article.publication_date}</p>
|
||||
<p>
|
||||
<strong>
|
||||
<a href="./articles/{articleFileName}.html">{article.title}</a>
|
||||
</strong>
|
||||
</p>
|
||||
{#if article.meta_description}
|
||||
<p>{article.meta_description}</p>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ const generateStaticFiles = async (websiteData: any, isPreview: boolean = true)
|
||||
: `${API_BASE_PREFIX}/rpc/retrieve_file?id=${websiteData.logo_image}`,
|
||||
mainContent: md(websiteData.main_content ?? "", false),
|
||||
articles: websiteData.articles ?? [],
|
||||
categorizedArticles: websiteData.categorized_articles ?? [],
|
||||
footerAdditionalText: md(websiteData.additional_text ?? "")
|
||||
}
|
||||
}));
|
||||
@@ -169,6 +170,7 @@ const generateStaticFiles = async (websiteData: any, isPreview: boolean = true)
|
||||
: "",
|
||||
publicationDate: article.publication_date,
|
||||
mainContent: md(article.main_content ?? ""),
|
||||
categorizedArticles: websiteData.categorized_articles ?? [],
|
||||
footerAdditionalText: md(websiteData.additional_text ?? "")
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<h2>
|
||||
<a href="#publish-website">Publish website</a>
|
||||
</h2>
|
||||
{JSON.stringify(data.websiteOverview.articles)}
|
||||
<p>
|
||||
The preview area on this page allows you to see exactly how your website will look when it is
|
||||
is published. If you are happy with the results, click the button below and your website will
|
||||
|
||||
@@ -41,6 +41,40 @@ label[for="toggle-sidebar"] {
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
.docs-navigation {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset-block-start: var(--space-xl);
|
||||
padding: var(--space-s);
|
||||
padding-inline-start: 0;
|
||||
inline-size: 15rem;
|
||||
block-size: calc(100vh - var(--space-xl));
|
||||
background-color: var(--bg-primary);
|
||||
border-inline-end: var(--border-primary);
|
||||
}
|
||||
|
||||
.docs-navigation > ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-s);
|
||||
}
|
||||
|
||||
#toggle-sidebar:checked ~ .docs-navigation {
|
||||
display: unset;
|
||||
}
|
||||
|
||||
@media (min-width: 1300px) {
|
||||
.docs-navigation {
|
||||
display: unset;
|
||||
inset-inline-start: calc(50% - 37.5ch - var(--space-m));
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
#toggle-sidebar:checked ~ .docs-navigation {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1525px) {
|
||||
#table-of-contents {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user