From fc1b264f1bcc8460749c521a2171c0ee2bed1ae3 Mon Sep 17 00:00:00 2001 From: Jessica Phoenix Canady Date: Tue, 4 Jun 2024 14:09:14 -0400 Subject: [PATCH] Add controllers/templates to show blog posts. --- config/dev.exs | 3 ++- lib/jol/blog.ex | 27 ++++++++++++++++--- lib/jol/blog/parser.ex | 3 ++- lib/jol/blog/post.ex | 4 +-- lib/jol_web/controllers/blog_controller.ex | 13 +++++++++ lib/jol_web/controllers/blog_html.ex | 5 ++++ lib/jol_web/controllers/blog_html/index.heex | 7 +++++ lib/jol_web/controllers/blog_html/show.heex | 13 +++++++++ lib/jol_web/router.ex | 3 +++ priv/posts/blog/lan-voice-chat.md | 1 + priv/posts/blog/odyssey-gen2-kvm.md | 1 + priv/posts/blog/steam-deck-touchscreen-fix.md | 1 + priv/posts/blog/the-names-we-discard.md | 1 + test/lib/blog/parser_test.exs | 5 ++++ 14 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 lib/jol_web/controllers/blog_controller.ex create mode 100644 lib/jol_web/controllers/blog_html.ex create mode 100644 lib/jol_web/controllers/blog_html/index.heex create mode 100644 lib/jol_web/controllers/blog_html/show.heex diff --git a/config/dev.exs b/config/dev.exs index 2cdfb60..0f0ac39 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -58,7 +58,8 @@ config :jol, JOLWeb.Endpoint, patterns: [ ~r"priv/static/(?!uploads/).*(js|css|png|jpeg|jpg|gif|svg)$", ~r"priv/gettext/.*(po)$", - ~r"lib/jol_web/(controllers|live|components)/.*(ex|heex)$" + ~r"lib/jol_web/(controllers|live|components)/.*(ex|heex)$", + ~r"posts/*/.*(md)$" ] ] diff --git a/lib/jol/blog.ex b/lib/jol/blog.ex index cab132e..63deb8a 100644 --- a/lib/jol/blog.ex +++ b/lib/jol/blog.ex @@ -1,6 +1,12 @@ defmodule JOL.Blog do +<<<<<<< HEAD alias JOL.Blog.Post alias JOL.Blog.Parser +======= + defmodule NotFoundError do + defexception [:message, plug_status: 404] + end +>>>>>>> 77c7828 (Add controllers/templates to show blog posts.) use NimblePublisher, build: JOL.Blog.Post, @@ -11,9 +17,22 @@ defmodule JOL.Blog do @posts Enum.sort_by(@posts, & &1.date, {:desc, Date}) @tags @posts |> Enum.flat_map(& &1.tags) |> Enum.uniq() |> Enum.sort() - @spec posts() :: [] - def posts, do: @posts - - @spec unique_tag_list() :: [] + def all_posts, do: @posts def unique_tag_list, do: @tags + + def recent_posts(num \\ 10) do + Enum.take(all_posts(), num) + end + + def get_post_by_slug!(slug) do + Enum.find(all_posts(), &(&1.slug == slug)) || + raise NotFoundError, "post ``slug=#{slug}` not found" + end + + def get_posts_by_tag!(tag) do + case Enum.filter(all_posts(), &(tag in &1.tags)) do + [] -> raise NotFoundError, "posts tagged `#{tag}` not found" + posts -> posts + end + end end diff --git a/lib/jol/blog/parser.ex b/lib/jol/blog/parser.ex index 4b191d4..f265ba5 100644 --- a/lib/jol/blog/parser.ex +++ b/lib/jol/blog/parser.ex @@ -24,7 +24,8 @@ defmodule JOL.Blog.Parser do title: toml_attrs["title"], draft: toml_attrs["draft"], tags: toml_attrs["taxonomies"]["tags"], - date: toml_attrs["date"] + date: toml_attrs["date"], + slug: toml_attrs["slug"] } parsed_body = String.trim(body) diff --git a/lib/jol/blog/post.ex b/lib/jol/blog/post.ex index 71a95a4..fe35a33 100644 --- a/lib/jol/blog/post.ex +++ b/lib/jol/blog/post.ex @@ -1,6 +1,6 @@ defmodule JOL.Blog.Post do - @enforce_keys [:author, :draft, :title, :body, :tags, :date] - defstruct [:author, :draft, :title, :body, :tags, :date] + @enforce_keys [:author, :title, :body, :tags, :date, :slug] + defstruct [:author, :draft, :title, :body, :tags, :date, :slug] def build(_filename, attrs, body) do struct!(__MODULE__, [author: "Jessica Phoenix Canady", body: body] ++ Map.to_list(attrs)) diff --git a/lib/jol_web/controllers/blog_controller.ex b/lib/jol_web/controllers/blog_controller.ex new file mode 100644 index 0000000..265c246 --- /dev/null +++ b/lib/jol_web/controllers/blog_controller.ex @@ -0,0 +1,13 @@ +defmodule JOLWeb.BlogController do + use JOLWeb, :controller + + alias JOL.Blog + + def index(conn, _params) do + render(conn, "index.html", posts: Blog.recent_posts()) + end + + def show(conn, %{"slug" => slug}) do + render(conn, "show.html", post: Blog.get_post_by_slug!(slug)) + end +end diff --git a/lib/jol_web/controllers/blog_html.ex b/lib/jol_web/controllers/blog_html.ex new file mode 100644 index 0000000..65978d6 --- /dev/null +++ b/lib/jol_web/controllers/blog_html.ex @@ -0,0 +1,5 @@ +defmodule JOLWeb.BlogHTML do + use JOLWeb, :html + + embed_templates "blog_html/*" +end diff --git a/lib/jol_web/controllers/blog_html/index.heex b/lib/jol_web/controllers/blog_html/index.heex new file mode 100644 index 0000000..60c57c6 --- /dev/null +++ b/lib/jol_web/controllers/blog_html/index.heex @@ -0,0 +1,7 @@ +

The Blog

+ + diff --git a/lib/jol_web/controllers/blog_html/show.heex b/lib/jol_web/controllers/blog_html/show.heex new file mode 100644 index 0000000..ee07900 --- /dev/null +++ b/lib/jol_web/controllers/blog_html/show.heex @@ -0,0 +1,13 @@ +<.link href={~p"/blog"}>← All posts + +

<%= @post.title %>

+ +

+ by <%= @post.author %> +

+ +

+ Tagged as <%= Enum.join(@post.tags, ", ") %> +

+ +<%= raw @post.body %> diff --git a/lib/jol_web/router.ex b/lib/jol_web/router.ex index 13fcefe..3d58969 100644 --- a/lib/jol_web/router.ex +++ b/lib/jol_web/router.ex @@ -23,6 +23,9 @@ defmodule JOLWeb.Router do get "/about", PageController, :about get "/now", PageController, :now get "/code", PageController, :code + + get "/blog", BlogController, :index + get "/blog/:slug", BlogController, :show end # Other scopes may use custom stacks. diff --git a/priv/posts/blog/lan-voice-chat.md b/priv/posts/blog/lan-voice-chat.md index 4b537c3..ce46ffc 100644 --- a/priv/posts/blog/lan-voice-chat.md +++ b/priv/posts/blog/lan-voice-chat.md @@ -1,4 +1,5 @@ +++ +slug = "mumble_voice_chat" title = "LAN Voice Chat with Mumble" date = 2024-04-16 11:51:33-04:00 draft = false diff --git a/priv/posts/blog/odyssey-gen2-kvm.md b/priv/posts/blog/odyssey-gen2-kvm.md index f43ad25..71b0945 100644 --- a/priv/posts/blog/odyssey-gen2-kvm.md +++ b/priv/posts/blog/odyssey-gen2-kvm.md @@ -1,4 +1,5 @@ +++ +slug = "odyssey_ark_gen2_kvm" title = "HOWTO: Use the KVM in the Odyssey Ark Gen2" draft = false date = 2024-01-02 14:00:00-05:00 diff --git a/priv/posts/blog/steam-deck-touchscreen-fix.md b/priv/posts/blog/steam-deck-touchscreen-fix.md index 663b9a1..e3954f6 100644 --- a/priv/posts/blog/steam-deck-touchscreen-fix.md +++ b/priv/posts/blog/steam-deck-touchscreen-fix.md @@ -1,5 +1,6 @@ +++ title = "HOWTO: Fix Steam Deck Unresponsive Touchscreen" +slug = "fix_steam_deck_touchscreen" date = 2024-01-07 13:40:00-05:00 [taxonomies] diff --git a/priv/posts/blog/the-names-we-discard.md b/priv/posts/blog/the-names-we-discard.md index 4914c16..f6e7153 100644 --- a/priv/posts/blog/the-names-we-discard.md +++ b/priv/posts/blog/the-names-we-discard.md @@ -1,5 +1,6 @@ +++ title = "The Names We Discard" +slug = "names_we_discard" date = 2024-01-30 15:53:22-05:00 [taxonomies] diff --git a/test/lib/blog/parser_test.exs b/test/lib/blog/parser_test.exs index 219db4a..23b5564 100644 --- a/test/lib/blog/parser_test.exs +++ b/test/lib/blog/parser_test.exs @@ -6,6 +6,7 @@ defmodule JOL.Blog.ParserTest do content = """ +++ title = "test post" + slug = "test_post" draft = false date = 2024-01-02 14:00:00-05:00 @@ -29,6 +30,10 @@ defmodule JOL.Blog.ParserTest do assert post.attrs.title == "test post" end + test "parses the title from zola-style posts", post do + assert post.attrs.title == "test_post" + end + test "parses the tags from zola-style posts", post do assert post.attrs.tags == ["howto", "hardware"] end