diff --git a/pages/blog.js b/pages/blog.js
index 2c6e03d49..ec29847f8 100644
--- a/pages/blog.js
+++ b/pages/blog.js
@@ -1,6 +1,6 @@
import BlogRes from "src/Blog.mjs";
-export { getStaticProps } from "src/Blog.mjs";
+export { getStaticProps_All as getStaticProps } from "src/Blog.mjs";
export default function Blog(props) {
return
diff --git a/pages/blog/archived.js b/pages/blog/archived.js
new file mode 100644
index 000000000..112948ab4
--- /dev/null
+++ b/pages/blog/archived.js
@@ -0,0 +1,7 @@
+import BlogRes from "src/Blog.mjs";
+
+export { getStaticProps_Archived as getStaticProps } from "src/Blog.mjs";
+
+export default function Blog(props) {
+ return
+}
diff --git a/src/Blog.res b/src/Blog.res
index f2c0c57d2..7ba4ccc51 100644
--- a/src/Blog.res
+++ b/src/Blog.res
@@ -39,44 +39,34 @@ module Badge = {
}
}
-module CategorySelector = {
- type selection =
- | All
- | Archived
- let renderTab = (~text: string, ~isActive: bool, ~onClick) => {
- let active = "bg-gray-20 text-gray-80 rounded py-1"
-
- {React.string(text)}
-
- }
+type category =
+ | /** Actually only unarchived */ All
+ | Archived
+module CategorySelector = {
@react.component
- let make = (~selected: selection, ~onSelected: selection => unit) => {
+ let make = (~selected: category) => {
let tabs = [All, Archived]
- {Belt.Array.map(tabs, tab => {
- let onClick = evt => {
- evt->ReactEvent.Mouse.preventDefault
- onSelected(tab)
- }
-
+ {tabs
+ ->Belt.Array.map(tab => {
// Deep comparison here!
let isActive = selected == tab
-
- let text = switch tab {
- | All => "All"
- | Archived => "Archived"
+ let text = (tab :> string)
+ let href = switch tab {
+ | All => "/blog"
+ | Archived => "/blog/archived"
}
-
- renderTab(~isActive, ~text, ~onClick)
- })->React.array}
+ let className =
+ switch isActive {
+ | true => "bg-gray-20 text-gray-80 rounded py-1"
+ | false => "hover:cursor-pointer bg-white hover:text-gray-80"
+ } ++ " px-4 inline-block"
+ {React.string(text)}
+ })
+ ->React.array}
}
}
@@ -209,15 +199,10 @@ module FeatureCard = {
type params = {slug: string}
-type props = {
- posts: array,
- archived: array,
-}
+type props = {posts: array, category: category}
let default = (props: props): React.element => {
- let {posts, archived} = props
-
- let (currentSelection, setSelection) = React.useState(() => CategorySelector.All)
+ let {posts, category} = props
let content = if Belt.Array.length(posts) === 0 {
/* {React.string("Currently no posts available")}
; */
@@ -226,16 +211,11 @@ let default = (props: props): React.element => {
{React.string("This blog is currently in the works.")}
} else {
- let filtered = switch currentSelection {
- | All => posts
- | Archived => archived
- }
-
- let result = switch Belt.Array.length(filtered) {
+ let result = switch Belt.Array.length(posts) {
| 0 => {React.string("No posts for this category available...")}
| _ =>
- let first = Belt.Array.getExn(filtered, 0)
- let rest = Js.Array2.sliceFrom(filtered, 1)
+ let first = Belt.Array.getExn(posts, 0)
+ let rest = Js.Array2.sliceFrom(posts, 1)
let featureBox =
@@ -280,9 +260,7 @@ let default = (props: props): React.element => {
<>
- setSelection(_ => selection)} selected=currentSelection
- />
+
result
@@ -316,12 +294,19 @@ let default = (props: props): React.element => {
>
}
-let getStaticProps: Next.GetStaticProps.t
= async _ctx => {
- let (archived, nonArchived) = BlogApi.getAllPosts()->Belt.Array.partition(data => data.archived)
+let getStaticProps_All: Next.GetStaticProps.t = async _ctx => {
+ let props = {
+ posts: BlogApi.getLivePosts(),
+ category: All,
+ }
+
+ {"props": props}
+}
+let getStaticProps_Archived: Next.GetStaticProps.t = async _ctx => {
let props = {
- posts: nonArchived,
- archived,
+ posts: BlogApi.getArchivedPosts(),
+ category: Archived,
}
{"props": props}
diff --git a/src/Blog.resi b/src/Blog.resi
index f49000d26..21b92e49c 100644
--- a/src/Blog.resi
+++ b/src/Blog.resi
@@ -3,6 +3,9 @@ let defaultPreviewImg: string
type params
type props
+type category = All | Archived
+
let default: props => React.element
-let getStaticProps: Next.GetStaticProps.t
+let getStaticProps_All: Next.GetStaticProps.t
+let getStaticProps_Archived: Next.GetStaticProps.t
diff --git a/src/common/BlogApi.res b/src/common/BlogApi.res
index 5a02de7be..a7f512244 100644
--- a/src/common/BlogApi.res
+++ b/src/common/BlogApi.res
@@ -42,14 +42,14 @@ let blogPathToSlug = path => {
path->Js.String2.replaceByRe(%re(`/^(archive\/)?\d\d\d\d-\d\d-\d\d-(.+)\.mdx$/`), "$2")
}
+let mdxFiles = dir => {
+ Node.Fs.readdirSync(dir)->Js.Array2.filter(path => Node.Path.extname(path) === ".mdx")
+}
+
let getAllPosts = () => {
let postsDirectory = Node.Path.join2(Node.Process.cwd(), "_blogposts")
let archivedPostsDirectory = Node.Path.join2(postsDirectory, "archive")
- let mdxFiles = dir => {
- Node.Fs.readdirSync(dir)->Js.Array2.filter(path => Node.Path.extname(path) === ".mdx")
- }
-
let nonArchivedPosts = mdxFiles(postsDirectory)->Js.Array2.map(path => {
let {GrayMatter.data: data} =
Node.Path.join2(postsDirectory, path)->Node.Fs.readFileSync->GrayMatter.matter
@@ -81,6 +81,49 @@ let getAllPosts = () => {
})
}
+let getLivePosts = () => {
+ let postsDirectory = Node.Path.join2(Node.Process.cwd(), "_blogposts")
+
+ let livePosts = mdxFiles(postsDirectory)->Js.Array2.map(path => {
+ let {GrayMatter.data: data} =
+ Node.Path.join2(postsDirectory, path)->Node.Fs.readFileSync->GrayMatter.matter
+ switch BlogFrontmatter.decode(data) {
+ | Error(msg) => Js.Exn.raiseError(msg)
+ | Ok(d) => {
+ path,
+ frontmatter: d,
+ archived: false,
+ }
+ }
+ })
+
+ livePosts->Js.Array2.sortInPlaceWith((a, b) => {
+ String.compare(Node.Path.basename(b.path), Node.Path.basename(a.path))
+ })
+}
+
+let getArchivedPosts = () => {
+ let postsDirectory = Node.Path.join2(Node.Process.cwd(), "_blogposts")
+ let archivedPostsDirectory = Node.Path.join2(postsDirectory, "archive")
+
+ let archivedPosts = mdxFiles(archivedPostsDirectory)->Js.Array2.map(path => {
+ let {GrayMatter.data: data} =
+ Node.Path.join2(archivedPostsDirectory, path)->Node.Fs.readFileSync->GrayMatter.matter
+ switch BlogFrontmatter.decode(data) {
+ | Error(msg) => Js.Exn.raiseError(msg)
+ | Ok(d) => {
+ path: Node.Path.join2("archive", path),
+ frontmatter: d,
+ archived: true,
+ }
+ }
+ })
+
+ archivedPosts->Js.Array2.sortInPlaceWith((a, b) => {
+ String.compare(Node.Path.basename(b.path), Node.Path.basename(a.path))
+ })
+}
+
module RssFeed = {
// Module inspired by
// https://gist.github.com/fredrikbergqvist/36704828353ebf5379a5c08c7583fe2d
diff --git a/src/common/BlogApi.resi b/src/common/BlogApi.resi
index f4542492f..02482047f 100644
--- a/src/common/BlogApi.resi
+++ b/src/common/BlogApi.resi
@@ -5,6 +5,8 @@ type post = {
}
let getAllPosts: unit => array
+let getLivePosts: unit => array
+let getArchivedPosts: unit => array
let blogPathToSlug: string => string
module RssFeed: {