From 27a8c22e9f5d1801eb25f62b93ddffac9cf540d0 Mon Sep 17 00:00:00 2001 From: Adam Piontek Date: Mon, 5 Apr 2021 21:40:43 -0400 Subject: [PATCH] numerous fixes, blog index, paging, tag index, post show - all liveview --- assets/css/app.scss | 15 ++- lib/home73k/blog.ex | 24 ++-- lib/home73k_web.ex | 3 - lib/home73k_web/live/blog_live.ex | 111 +++++++++++++----- lib/home73k_web/live/blog_live.html.leex | 84 +++++++++---- lib/home73k_web/live/post_live.ex | 58 --------- lib/home73k_web/live/post_live.html.leex | 36 ------ lib/home73k_web/router.ex | 8 +- lib/home73k_web/views/date_helpers.ex | 9 -- ...lana-del-arr-ultrapirates-parody-lyrics.md | 7 +- 10 files changed, 178 insertions(+), 177 deletions(-) delete mode 100644 lib/home73k_web/live/post_live.ex delete mode 100644 lib/home73k_web/live/post_live.html.leex delete mode 100644 lib/home73k_web/views/date_helpers.ex diff --git a/assets/css/app.scss b/assets/css/app.scss index 7754710..bb6ce2d 100644 --- a/assets/css/app.scss +++ b/assets/css/app.scss @@ -47,12 +47,21 @@ body { height: 100%; } a { - color: $secondary; + color: $gray-100; + border-bottom: $secondary 2px solid; + text-decoration: none; + &.navbar-brand { + border-bottom: none; + } &:visited { color: $info; + .post-title & { + color: $gray-100; + } } &:hover { color: $primary; + text-decoration: none; } } .border-gray-900 { @@ -94,6 +103,7 @@ a { /* social icons */ #social-icons .link-light { + border-bottom: none; color: $gray-100; &:hover { color: $primary; @@ -128,9 +138,10 @@ a { .post-title a { color: $gray-100; text-decoration: none; + border-bottom: none; &:hover { color: $primary; - text-decoration: underline; + border-bottom: $secondary 3px solid; } } .post-lede, diff --git a/lib/home73k/blog.ex b/lib/home73k/blog.ex index 7f002f6..db9ba4b 100644 --- a/lib/home73k/blog.ex +++ b/lib/home73k/blog.ex @@ -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 diff --git a/lib/home73k_web.ex b/lib/home73k_web.ex index 6da50d5..29f5403 100644 --- a/lib/home73k_web.ex +++ b/lib/home73k_web.ex @@ -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 diff --git a/lib/home73k_web/live/blog_live.ex b/lib/home73k_web/live/blog_live.ex index 6100d73..ac160be 100644 --- a/lib/home73k_web/live/blog_live.ex +++ b/lib/home73k_web/live/blog_live.ex @@ -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 diff --git a/lib/home73k_web/live/blog_live.html.leex b/lib/home73k_web/live/blog_live.html.leex index 5dd8a55..f41c5af 100644 --- a/lib/home73k_web/live/blog_live.html.leex +++ b/lib/home73k_web/live/blog_live.html.leex @@ -2,38 +2,74 @@
- <%= for post <- @posts do %> + <%= if is_nil(@posts) do %> -
+
-

- <%= live_redirect "#{post.title}", to: Routes.post_path(@socket, :show, post) %> -

+

Nothing found.

- - <%= if length(post.tags) > 0 do %> - - + <%= if @page_next do %> + <%= live_patch to: @page_next == 1 && Routes.blog_path(@socket, :index) || Routes.blog_path(@socket, :page, @page_next) do %> + Newer → + <% end %> + <% end %> + <% end %>
diff --git a/lib/home73k_web/live/post_live.ex b/lib/home73k_web/live/post_live.ex deleted file mode 100644 index 781322f..0000000 --- a/lib/home73k_web/live/post_live.ex +++ /dev/null @@ -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 diff --git a/lib/home73k_web/live/post_live.html.leex b/lib/home73k_web/live/post_live.html.leex deleted file mode 100644 index 3b2b9d1..0000000 --- a/lib/home73k_web/live/post_live.html.leex +++ /dev/null @@ -1,36 +0,0 @@ -
- -
- -
- -

<%= raw @post.title %>

- - - - <%= if length(@post.tags) > 0 do %> - - <% end %> - -
- <%= raw @post.lede %> -
- -
- <%= raw @post.body %> -
- - -
- -
- -
diff --git a/lib/home73k_web/router.ex b/lib/home73k_web/router.ex index 352684e..2f1be2b 100644 --- a/lib/home73k_web/router.ex +++ b/lib/home73k_web/router.ex @@ -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. diff --git a/lib/home73k_web/views/date_helpers.ex b/lib/home73k_web/views/date_helpers.ex deleted file mode 100644 index c795cff..0000000 --- a/lib/home73k_web/views/date_helpers.ex +++ /dev/null @@ -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 diff --git a/priv/content/2018/11/2018-11-09_lana-del-arr-ultrapirates-parody-lyrics.md b/priv/content/2018/11/2018-11-09_lana-del-arr-ultrapirates-parody-lyrics.md index c67bbfd..b383bb2 100644 --- a/priv/content/2018/11/2018-11-09_lana-del-arr-ultrapirates-parody-lyrics.md +++ b/priv/content/2018/11/2018-11-09_lana-del-arr-ultrapirates-parody-lyrics.md @@ -21,10 +21,11 @@ Naturally I ended up writing some alternate lyrics. There's only two; I never go - ["Florida Cargo" (to the tune of "Florida Kilos")](#florida-cargo) - ["The Other Schooner" (to the tune of "The Other Woman")](#other-schooner) -#### "Florida Cargo" (to the tune of "Florida Kilos") +#### "Florida Cargo" (to the tune of "Florida Kilos") + White shine, royal sailor, doubloons, Don't you see them gleam, They're special, just for you. @@ -103,10 +104,10 @@ White shine, royal sailor, Gold teeth, royal sailor, yeah, Drink the night away. -#### "The Other Schooner" (to the tune of "The Other Woman") - +#### "The Other Schooner" (to the tune of "The Other Woman") + The other schooner has time to trim and furl her sails The other schooner is perfect where her rival fails And she's never seen with caulking in her hull anywhere