numerous fixes, blog index, paging, tag index, post show - all liveview

This commit is contained in:
Adam Piontek 2021-04-05 21:40:43 -04:00
parent 2218a678b1
commit 27a8c22e9f
10 changed files with 178 additions and 177 deletions

View file

@ -3,21 +3,29 @@ defmodule Home73k.Blog do
Application.ensure_all_started(:earmark)
posts_paths = "#{Home73k.app_blog_content()}/**/*.md" |> Path.wildcard()
post_paths = "#{Home73k.app_blog_content()}/**/*.md" |> Path.wildcard()
post_paths_hash = :erlang.md5(post_paths)
posts =
for post_path <- posts_paths do
for post_path <- post_paths do
@external_resource Path.relative_to_cwd(post_path)
Post.parse!(post_path)
end
def __mix_recompile__?() do
Path.wildcard("#{Home73k.app_blog_content()}/**/*.md") |> :erlang.md5() != unquote(post_paths_hash)
end
@posts Enum.sort_by(posts, & &1.date, {:desc, Date})
@post_count length(@posts)
@tags posts |> Stream.flat_map(& &1.tags) |> Stream.uniq() |> Enum.sort()
def list_posts, do: @posts
def list_tags, do: @tags
def post_count, do: @post_count
defmodule NotFoundError do
defexception [:message, plug_status: 404]
end
@ -29,10 +37,10 @@ defmodule Home73k.Blog do
end
end
# def get_posts_by_tag!(tag) do
# case Enum.filter(list_posts(), &(tag in &1.tags)) do
# [] -> raise NotFoundError, "posts with tag=#{tag} not found"
# posts -> posts
# end
# end
def get_posts_by_tag!(tag) do
case Enum.filter(list_posts(), &(tag in &1.tags)) do
[] -> raise NotFoundError, "posts with tag=#{tag} not found"
posts -> posts
end
end
end

View file

@ -93,9 +93,6 @@ defmodule Home73kWeb do
# Import SVG Icon helper
import Home73kWeb.IconHelpers
# Import Date formatter helper
import Home73kWeb.DateHelpers
import Home73kWeb.ErrorHelpers
import Home73kWeb.Gettext
alias Home73kWeb.Router.Helpers, as: Routes

View file

@ -3,49 +3,96 @@ defmodule Home73kWeb.BlogLive do
alias Home73k.Blog
@page_size 7
@impl true
def mount(_params, _session, socket) do
socket
|> live_okreply()
{:ok, socket}
end
@impl true
def handle_params(_params, _url, socket) do
socket
|> assign(:page_title, "Blog")
|> assign(:posts, Blog.list_posts())
def handle_params(params, _url, socket) do
socket.assigns.live_action
|> init_per_live_action(socket, params)
|> live_noreply()
end
# @impl true
# def handle_event("suggest", %{"q" => query}, socket) do
# {:noreply, assign(socket, results: search(query), query: query)}
# end
defp page_param_as_int(page) do
try do
String.to_integer(page)
rescue
_ -> nil
end
end
# @impl true
# def handle_event("search", %{"q" => query}, socket) do
# case search(query) do
# %{^query => vsn} ->
# {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")}
defp raise_not_found(msg), do: raise Home73k.Blog.NotFoundError, msg
# _ ->
# {:noreply,
# socket
# |> put_flash(:error, "No dependencies found matching \"#{query}\"")
# |> assign(results: %{}, query: query)}
# end
# end
defp init_per_live_action(:index, socket, _params) do
socket
|> assign(:page_title, "Blog")
|> assign(:posts, get_posts_for_page!(1))
|> assign(:page_count, get_page_count())
|> assign_prev_next(1)
end
# defp search(query) do
# if not Home73kWeb.Endpoint.config(:code_reloader) do
# raise "action disabled when not in development"
# end
defp init_per_live_action(:page, socket, %{"page" => page}) do
page_int = page_param_as_int(page)
page_count = get_page_count()
# for {app, desc, vsn} <- Application.started_applications(),
# app = to_string(app),
# String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"),
# into: %{},
# do: {app, vsn}
# end
cond do
is_nil(page_int) || page_int <= 1 ->
push_patch(socket, to: Routes.blog_path(socket, :index))
page_int > page_count ->
raise_not_found("there are only #{page_count} pages of posts")
true ->
posts = get_posts_for_page!(page_int)
socket
|> assign(:page_title, "Blog \\ Page #{page}")
|> assign(:posts, posts)
|> assign(:page_count, page_count)
|> assign_prev_next(page_int)
end
end
defp init_per_live_action(:show, socket, %{"id" => id}) do
post = Blog.get_post_by_id!(id)
socket
|> assign(:page_title, "Blog \\ post.title")
|> assign(:posts, [post])
|> assign(:page_count, nil)
|> assign_prev_next(0)
end
defp init_per_live_action(:tag, socket, %{"tag" => tag}) do
socket
|> assign(:page_title, "Blog \\ ##{tag}")
|> assign(:posts, Blog.get_posts_by_tag!(tag))
|> assign(:page_count, get_page_count())
|> assign_prev_next(1)
end
defp get_posts_for_page!(1), do: Blog.list_posts() |> Enum.take(@page_size)
defp get_posts_for_page!(page_int) do
Blog.list_posts()
|> Stream.chunk_every(@page_size)
|> Enum.at(page_int - 1)
end
defp get_page_count, do: Integer.floor_div(Blog.post_count(), @page_size) + rem(Blog.post_count(), @page_size)
defp assign_prev_next(socket, page_int) do
socket
|> assign(:page_prev, page_int < socket.assigns.page_count && page_int + 1 || nil)
|> assign(:page_next, page_int > 1 && page_int - 1 || nil)
end
def format_date(date) do
Calendar.strftime(date, "%B %-d, %Y")
end
end

View file

@ -2,38 +2,74 @@
<div class="col-12 col-md-10 col-lg-9 col-xl-8 col-xxl-7 pb-2 mb-4 mt-3">
<%= for post <- @posts do %>
<%= if is_nil(@posts) do %>
<div class="post border-bottom border-gray pb-4 mb-3">
<div class="post border-bottom border-gray pb-4 mb-3">
<h2 class="post-title fs-2 fw-600 mb-2">
<%= live_redirect "#{post.title}", to: Routes.post_path(@socket, :show, post) %>
</h2>
<h2 class="post-title fs-2 fw-600 mb-2">Nothing found.</h2>
<div class="post-date font-monospace text-gray-400 <%= if length(post.tags) == 0, do: "mb-3" %>">
<%= icon_div @socket, "mdi-calendar-clock", [class: "icon baseline me-2"] %><%= post.date |> format_date() %>
by <%= icon_div @socket, "mdi-account", [class: "icon baseline me-1"] %>Adam Piontek
</div>
<%= if length(post.tags) > 0 do %>
<div class="post-tags fs-smaller mb-3">
<%= icon_div @socket, "mdi-tag-multiple", [class: "icon baseline"] %>
<%= for {tag, i} <- Enum.with_index(post.tags) do %>
#<%= tag %><%= i < (length(post.tags) - 1) && "," || "" %>
<% end %>
<% else %>
<%= for post <- @posts do %>
<div class="post border-bottom border-gray pb-4 mb-3">
<h2 class="post-title fs-2 fw-600 mb-2">
<%= live_redirect "#{post.title}", to: Routes.blog_path(@socket, :show, post) %>
</h2>
<div class="post-date font-monospace text-gray-400 <%= if length(post.tags) == 0, do: "mb-3" %>">
<%= icon_div @socket, "mdi-calendar-clock", [class: "icon baseline me-2"] %><%= format_date(post.date) %>
by <%= icon_div @socket, "mdi-account", [class: "icon baseline me-1"] %>Adam Piontek
</div>
<%= if length(post.tags) > 0 do %>
<div class="post-tags fs-smaller mb-3">
<%= icon_div @socket, "mdi-tag-multiple", [class: "icon baseline text-gray-400"] %>
<%= for {tag, i} <- Enum.with_index(post.tags) do %>
<span class="text-gray-400">#</span><%= live_redirect tag, to: Routes.blog_path(@socket, :tag, tag) %><%= i < (length(post.tags) - 1) && "," || "" %>
<% end %>
</div>
<% end %>
<div class="post-lede">
<%= raw post.lede %>
</div>
<%= if @live_action == :show do %>
<div class="post-body">
<%= raw post.body %>
</div>
<% else %>
<p>
<%= live_redirect raw("Read more&hellip;"), to: Routes.blog_path(@socket, :show, post), class: "fs-6" %>
</p>
<% end %>
</div>
<% end %>
<% end %>
<%= if @live_action in [:index, :page] do %>
<nav class="d-flex justify-content-between" aria-label="Page navigation">
<%= if @page_prev do %>
<%= live_patch to: Routes.blog_path(@socket, :page, @page_prev) do %>
&larr; Older
<% end %>
<% else %>
<div class="d-block"></div>
<% end %>
<div class="post-lede">
<%= raw post.lede %>
</div>
<p>
<%= live_redirect raw("Read more&hellip;"), to: Routes.post_path(@socket, :show, post), class: "fs-6" %>
</p>
</div>
<%= if @page_next do %>
<%= live_patch to: @page_next == 1 && Routes.blog_path(@socket, :index) || Routes.blog_path(@socket, :page, @page_next) do %>
Newer &rarr;
<% end %>
<% end %>
</nav>
<% end %>
</div>

View file

@ -1,58 +0,0 @@
defmodule Home73kWeb.PostLive do
use Home73kWeb, :live_view
alias Home73k.Blog
@impl true
def mount(%{"id" => id}, session, socket) do
# IO.inspect(params, label: "postlive params")
IO.inspect(session, label: "postlive session")
post = Blog.get_post_by_id!(id)
socket
|> assign(:page_title, "Blog \\ #{post.title}")
|> assign(:post, post)
|> live_okreply()
end
# @impl true
# def handle_params(params, _url, socket) do
# socket
# |> assign(:page_title, "Blog")
# |> assign(:posts, Blog.list_posts())
# |> live_noreply()
# end
# @impl true
# def handle_event("suggest", %{"q" => query}, socket) do
# {:noreply, assign(socket, results: search(query), query: query)}
# end
# @impl true
# def handle_event("search", %{"q" => query}, socket) do
# case search(query) do
# %{^query => vsn} ->
# {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")}
# _ ->
# {:noreply,
# socket
# |> put_flash(:error, "No dependencies found matching \"#{query}\"")
# |> assign(results: %{}, query: query)}
# end
# end
# defp search(query) do
# if not Home73kWeb.Endpoint.config(:code_reloader) do
# raise "action disabled when not in development"
# end
# for {app, desc, vsn} <- Application.started_applications(),
# app = to_string(app),
# String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"),
# into: %{},
# do: {app, vsn}
# end
end

View file

@ -1,36 +0,0 @@
<main class="container d-flex justify-content-center">
<div class="col-12 col-md-10 col-lg-9 col-xl-8 col-xxl-7 pb-2 mb-4 mt-3">
<div class="post border-bottom border-gray pb-4 mb-3">
<h2 class="post-title fs-2 fw-normal mb-2"><%= raw @post.title %></h2>
<div class="post-date font-monospace text-gray-400 <%= if length(@post.tags) == 0, do: "mb-3" %>">
<%= icon_div @socket, "mdi-calendar-clock", [class: "icon baseline me-2"] %><%= @post.date |> format_date() %>
by <%= icon_div @socket, "mdi-account", [class: "icon baseline me-1"] %>Adam Piontek
</div>
<%= if length(@post.tags) > 0 do %>
<div class="post-tags fs-smaller mb-3">
<%= icon_div @socket, "mdi-tag-multiple", [class: "icon baseline"] %>
<%= for {tag, i} <- Enum.with_index(@post.tags) do %>
#<%= tag %><%= i < (length(@post.tags) - 1) && "," || "" %>
<% end %>
</div>
<% end %>
<div class="post-lede">
<%= raw @post.lede %>
</div>
<div class="post-body">
<%= raw @post.body %>
</div>
</div>
</div>
</main>

View file

@ -17,13 +17,17 @@ defmodule Home73kWeb.Router do
scope "/", Home73kWeb do
pipe_through :browser
# Pages
get "/", HomeController, :index
get "/about", HomeController, :about
get "/resume", HomeController, :resume
get "/folio", HomeController, :folio
# Blog
live "/blog", BlogLive, :index
# live "/blog/page/:page", BlogLive, :older
live "/blog/:id", PostLive, :show
live "/blog/page/:page", BlogLive, :page
live "/blog/tag/:tag", BlogLive, :tag
live "/blog/:id", BlogLive, :show
end
# Other scopes may use custom stacks.

View file

@ -1,9 +0,0 @@
defmodule Home73kWeb.DateHelpers do
@moduledoc """
Formatters for dates
"""
def format_date(date) do
Calendar.strftime(date, "%B %-d, %Y")
end
end