diff --git a/rest-api/db/migrations/20240828132309_adjust_website_overview_view.sql b/rest-api/db/migrations/20240828132309_adjust_website_overview_view.sql
new file mode 100644
index 0000000..57b7f65
--- /dev/null
+++ b/rest-api/db/migrations/20240828132309_adjust_website_overview_view.sql
@@ -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;
+
diff --git a/web-app/src/lib/templates/common/Nav.svelte b/web-app/src/lib/templates/common/Nav.svelte
index c16c3a0..05cb11d 100644
--- a/web-app/src/lib/templates/common/Nav.svelte
+++ b/web-app/src/lib/templates/common/Nav.svelte
@@ -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();
@@ -30,9 +34,23 @@
-
+
+
+ {#each Object.keys(categorizedArticles) as key}
+ -
+ {key}
+
+ {#each categorizedArticles[key] as { title }}
+ {@const articleFileName = title.toLowerCase().split(" ").join("-")}
+ -
+ {title}
+
+ {/each}
+
+
+ {/each}
+
+
{/if}
{#if logoType === "text"}
diff --git a/web-app/src/lib/templates/docs/DocsArticle.svelte b/web-app/src/lib/templates/docs/DocsArticle.svelte
index 4df5982..75fbbd2 100644
--- a/web-app/src/lib/templates/docs/DocsArticle.svelte
+++ b/web-app/src/lib/templates/docs/DocsArticle.svelte
@@ -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 @@
-
+
diff --git a/web-app/src/lib/templates/docs/DocsIndex.svelte b/web-app/src/lib/templates/docs/DocsIndex.svelte
index 7d4c1a1..cf78985 100644
--- a/web-app/src/lib/templates/docs/DocsIndex.svelte
+++ b/web-app/src/lib/templates/docs/DocsIndex.svelte
@@ -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();
-
+
@@ -35,30 +37,6 @@
{@html mainContent}
- {#if articles.length > 0}
-
- {/if}
diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts
index ecb1a8d..508dbf0 100644
--- a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts
+++ b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.server.ts
@@ -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 ?? "")
}
}));
diff --git a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte
index 4ff1ac1..23c4be9 100644
--- a/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte
+++ b/web-app/src/routes/(authenticated)/website/[websiteId]/publish/+page.svelte
@@ -20,7 +20,6 @@
- {JSON.stringify(data.websiteOverview.articles)}
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
diff --git a/web-app/template-styles/docs-styles.css b/web-app/template-styles/docs-styles.css
index ee669f7..590522c 100644
--- a/web-app/template-styles/docs-styles.css
+++ b/web-app/template-styles/docs-styles.css
@@ -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;