Skip to content

Commit

Permalink
Merge pull request #1 from Albert-mah/main
Browse files Browse the repository at this point in the history
feat: add tutorials page
  • Loading branch information
Albert-mah authored Nov 1, 2024
2 parents 5b56c83 + b6bf091 commit c0e0fca
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 8 deletions.
3 changes: 3 additions & 0 deletions src/layouts/BaseCN.astro
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ const meta = {
<li>
<a href="https://docs-cn.nocobase.com" class="sub-menu-item" target="_blank">文档</a>
</li>
<li>
<a href="/cn/tutorials" class="sub-menu-item">实战教程</a>
</li>
<li>
<a href="/cn/blog" class="sub-menu-item">博客</a>
</li>
Expand Down
15 changes: 9 additions & 6 deletions src/layouts/BaseEN.astro
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const meta = {
<meta name="twitter:title" content={meta.title} />
<meta name="twitter:description" content={meta.description} />
<meta name="twitter:image" content={meta.image} />

<!-- favicon -->
<link
rel="apple-touch-icon"
Expand Down Expand Up @@ -142,20 +142,20 @@ const meta = {
text-align: left;
color: #c0ccda;
}

#sib-container input::placeholder {
text-align: left;
color: #c0ccda;
}

#sib-container textarea::placeholder {
text-align: left;
color: #c0ccda;
}
</style>
<link rel="stylesheet" href="https://sibforms.com/forms/end-form/build/sib-styles.css">
<!-- END Brevo Form -->

<!-- Global site tag (gtag.js) - Google Analytics -->
<script type="text/javascript" async src="https://www.googletagmanager.com/gtag/js?id=G-237XXSVYHE"></script>

Expand All @@ -166,14 +166,14 @@ const meta = {

gtag('config', 'G-237XXSVYHE');
</script>

<!-- Baidu Analytics -->
<script type="text/javascript">
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?acfb678ac7bbc9df89e1aa4327e47907";
var s = document.getElementsByTagName("script")[0];
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
Expand Down Expand Up @@ -267,6 +267,9 @@ const meta = {
<li>
<a href="https://docs.nocobase.com" title="NocoBase Guide Documents and References" class="sub-menu-item" target="_blank">Documentation</a>
</li>
<li>
<a href="/en/tutorials" title="NocoBase blog" class="sub-menu-item">Tutorials</a>
</li>
<li>
<a href="/en/blog" title="NocoBase blog" class="sub-menu-item">Blog</a>
</li>
Expand Down
80 changes: 80 additions & 0 deletions src/pages/cn/tutorials/[slug].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
import FormattedDate from "../../../components/FormattedDate.astro";
import PageHeader from "../../../components/PageHeader.astro";
import Toc from "../../../components/Toc.astro";
import Layout from "../../../layouts/Layout.astro";
import { getTutorialArticle, url } from "../../../utils";
const { slug } = Astro.params;
const { data, headings, html } = await getTutorialArticle(slug, 'cn');
if (!data) {
return new Response("Not found", { status: 404 });
}
const title = data.title_cn || data.title;
// const keywords = (data.tags || [])
// .map((tag: any) => tag.title_cn || tag.title)
// .join(",");
const description = data.description_cn || data.description;
const basepath = "/cn/tutorials";
const tabs = [
{
title: "首页",
link: "/cn/",
},
{
title: "实战教程",
link: basepath,
},
{
title: '详情',
active: true,
},
];
---

<Layout title={title} description={description}>
<PageHeader title={title} description={description} breadcrumb={tabs}>
<div>
{
data.author && (
<span title={data.author}>
{data.author}
<span style="opacity: 0.3; display:inline-block; padding: 0 .8em;">
|
</span>
</span>
)
}
<FormattedDate locale={"zh-cn"} date={data.publishedAt || data.createdAt} />
</div>
</PageHeader>
<section class="section bg-white-color">
<main
class={headings.length > 0 ? "container blog-container row" : "container"}
>
{
headings.length > 0 ? (
<>
<div class="col-md-9 col-18 markdown-body">
<Fragment set:html={html} />
</div>
<div class="col-md-3 col-6 markdown-toc">
<Toc headings={headings} />
</div>
</>
) : (
<>
<Fragment set:html={html} />
</>
)
}
</main>
</section>
</Layout>

<style>
main {
max-width: 960px;
margin: 0 auto;
}
</style>
73 changes: 73 additions & 0 deletions src/pages/cn/tutorials/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
import PageHeader from "../../../components/PageHeader.astro";
import Layout from "../../../layouts/Layout.astro";
import { getLastUpdatedAt, getPage, listTutorialArticles } from "../../../utils";
const page = await getPage("tutorials");
const title = page.title_cn || page.title;
const description = page.description_cn || page.description;
const keywords = page.keywords_cn || page.keywords;
const tutorialsData = await listTutorialArticles({ pageSize: 100 });
// Group tutorials by series dynamically
const tutorials = tutorialsData.data.reduce((acc, item) => {
const seriesTitle = item.serials?.title_cn || item.serials?.title || 'Uncategorized';
const seriesDescription = item.serials?.description_cn || item.serials?.description || "";
// Initialize the series if not present in the accumulator
if (!acc[seriesTitle]) {
acc[seriesTitle] = {
description: seriesDescription,
articles: [],
};
}
// Add the tutorial to the respective series
acc[seriesTitle].articles.push({
title: item.title_cn || item.title,
link: `/cn/tutorials/${item.slug}`,
description: item.description_cn || item.description || "",
});
return acc;
}, {});
// Convert the tutorials object into an array of series objects for easier mapping
const tutorialSeries = Object.entries(tutorials).map(([seriesTitle, seriesData]) => ({
seriesTitle,
description: seriesData.description,
articles: seriesData.articles,
}));
---

<Layout title={title} description={description} keywords={keywords}>
<PageHeader title={title} description={description} />
<section class="section">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-9">
<div class="card shadow border-0 rounded">
<div class="card-body">
{tutorialSeries.map(series => (
<>
<h5 class="card-title">{series.seriesTitle}</h5>
{series.description && <p class="text-muted">{series.description}</p>}
<ul class="list-unstyled text-muted mb-4 pb-4">
{series.articles.map(article => (
<li>
<i data-feather="arrow-right" class="fea icon-sm me-2"></i>
<a href={article.link} target="_blank">{article.title}</a>
{article.description && ` - ${article.description}`}
</li>
))}
</ul>
</>
))}
</div>
</div>
</div>
</div>
</div>
</section>
</Layout>
78 changes: 78 additions & 0 deletions src/pages/en/tutorials/[slug].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
import FormattedDate from "../../../components/FormattedDate.astro";
import PageHeader from "../../../components/PageHeader.astro";
import Toc from "../../../components/Toc.astro";
import Layout from "../../../layouts/Layout.astro";
import { getTutorialArticle, url } from "../../../utils";
const { slug } = Astro.params;
const { data, headings, html } = await getTutorialArticle(slug);
if (!data) {
return new Response("Not found", { status: 404 });
}
const title = data.title;
const keywords = (data.tags || []).map((tag: any) => tag.title).join(",");
const description = data.description;
const basepath = "/en/tutorials";
const tabs = [
{
title: "Home",
link: "/en/",
},
{
title: "Tutorials",
link: basepath,
},
{
title: 'Detail',
active: true,
},
];
---

<Layout title={title} description={description} keywords={keywords}>
<PageHeader title={title} description={description} breadcrumb={tabs}>
<div>
{
data.author && (
<span title={data.author}>
{data.author}
<span style="opacity: 0.3; display:inline-block; padding: 0 .8em;">
|
</span>
</span>
)
}
<FormattedDate date={data.publishedAt || data.createdAt} />
</div>
</PageHeader>
<section class="section bg-white-color">
<main
class={headings.length > 0 ? "container blog-container row" : "container"}
>
{
headings.length > 0 ? (
<>
<div class="col-md-9 col-18 markdown-body">
<Fragment set:html={html} />
</div>
<div class="col-md-3 col-6 markdown-toc">
<Toc headings={headings} />
</div>
</>
) : (
<>
<Fragment set:html={html} />
</>
)
}
</main>
</section>
</Layout>

<style>
main {
max-width: 960px;
margin: 0 auto;
}
</style>
73 changes: 73 additions & 0 deletions src/pages/en/tutorials/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
import PageHeader from "../../../components/PageHeader.astro";
import Layout from "../../../layouts/Layout.astro";
import { getPage, listTutorialArticles } from "../../../utils";
const page = await getPage("tutorials");
const title = page.title;
const description = page.description;
const keywords = page.keywords;
const tutorialsData = await listTutorialArticles({ pageSize: 100 });
// Group tutorials by series dynamically
const tutorials = tutorialsData.data.reduce((acc, item) => {
const seriesTitle = item.serials?.title || 'Uncategorized';
const seriesDescription = item.serials?.description || "";
// Initialize the series if not present in the accumulator
if (!acc[seriesTitle]) {
acc[seriesTitle] = {
description: seriesDescription,
articles: [],
};
}
// Add the tutorial to the respective series
acc[seriesTitle].articles.push({
title: item.title,
link: `/en/tutorials/${item.slug}`, //${item.serials?.slug}/
description: item.description || "",
});
return acc;
}, {});
// Convert the tutorials object into an array of series objects for easier mapping
const tutorialSeries = Object.entries(tutorials).map(([seriesTitle, seriesData]) => ({
seriesTitle,
description: seriesData.description,
articles: seriesData.articles,
}));
---

<Layout title={title} description={description} keywords={keywords}>
<PageHeader title={title} description={description} />
<section class="section">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-9">
<div class="card shadow border-0 rounded">
<div class="card-body">
{tutorialSeries.map(series => (
<>
<h5 class="card-title">{series.seriesTitle}</h5>
{series.description && <p class="text-muted">{series.description}</p>}
<ul class="list-unstyled text-muted mb-4 pb-4">
{series.articles.map(article => (
<li>
<i data-feather="arrow-right" class="fea icon-sm me-2"></i>
<a href={article.link} target="_blank">{article.title}</a>
{article.description && ` - ${article.description}`}
</li>
))}
</ul>
</>
))}
</div>
</div>
</div>
</div>
</div>
</section>
</Layout>
Loading

0 comments on commit c0e0fca

Please sign in to comment.