From 8bbe8a1b244e5b32706ab1d1b7dca74fe9758fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Engl=C3=B6f=20Ytterstr=C3=B6m?= Date: Fri, 6 Sep 2024 22:41:12 +0200 Subject: [PATCH] Item views (#7) * Add Earmark dependency For markdown to HTML conversion * Display items by slug: articles, pages * Handle 401 Forbidden responses in Directus * Add item controller as pokemon route * Strip out generated layouts * Plan future routes * Look for item in order: article, link, event, album * Add item templates --- lib/mse25/directus.ex | 77 ++++++++------ .../components/layouts/app.html.heex | 64 +++++------ .../components/layouts/root.html.heex | 12 +-- lib/mse25_web/controllers/item_controller.ex | 100 ++++++++++++++++++ lib/mse25_web/controllers/item_html.ex | 5 + .../controllers/item_html/article.html.heex | 12 +++ .../controllers/item_html/event.html.heex | 9 ++ .../controllers/item_html/link.html.heex | 14 +++ .../controllers/item_html/page.html.heex | 11 ++ .../controllers/item_html/show.html.heex | 12 +++ lib/mse25_web/router.ex | 14 +++ mix.exs | 3 +- mix.lock | 1 + 13 files changed, 264 insertions(+), 70 deletions(-) create mode 100644 lib/mse25_web/controllers/item_controller.ex create mode 100644 lib/mse25_web/controllers/item_html.ex create mode 100644 lib/mse25_web/controllers/item_html/article.html.heex create mode 100644 lib/mse25_web/controllers/item_html/event.html.heex create mode 100644 lib/mse25_web/controllers/item_html/link.html.heex create mode 100644 lib/mse25_web/controllers/item_html/page.html.heex create mode 100644 lib/mse25_web/controllers/item_html/show.html.heex diff --git a/lib/mse25/directus.ex b/lib/mse25/directus.ex index ff9235d..c5c1bbd 100644 --- a/lib/mse25/directus.ex +++ b/lib/mse25/directus.ex @@ -7,12 +7,16 @@ defmodule Mse25.Directus do params = [ "sort=-pubDate", - "fields=" <> Enum.join([ - "slug", - "title", - "date_updated", - "pubDate" - ], ",") + "fields=" <> + Enum.join( + [ + "slug", + "title", + "date_updated", + "pubDate" + ], + "," + ) ] |> query_params_string(options) @@ -41,18 +45,22 @@ defmodule Mse25.Directus do params = [ "sort=-started_at", - #"filter={\"upcoming\":{\"_eq\":true}}", - "fields=" <> Enum.join([ - "started_at", - "ended_at", - "title", - "lead", - "poster.filename_download", - "poster.width", - "poster.height", - "bands.artists_id.name", - "mia.artists_id.name" - ], ",") + # "filter={\"upcoming\":{\"_eq\":true}}", + "fields=" <> + Enum.join( + [ + "started_at", + "ended_at", + "title", + "lead", + "poster.filename_download", + "poster.width", + "poster.height", + "bands.artists_id.name", + "mia.artists_id.name" + ], + "," + ) ] |> query_params_string(options) @@ -67,15 +75,19 @@ defmodule Mse25.Directus do params = [ "sort=-pubDate", - "fields=" <> Enum.join([ - "slug", - "title", - "date_updated", - "pubDate", - "h1", - "source", - "contents" - ], ",") + "fields=" <> + Enum.join( + [ + "slug", + "title", + "date_updated", + "pubDate", + "h1", + "source", + "contents" + ], + "," + ) ] |> query_params_string(options) @@ -99,11 +111,16 @@ defmodule Mse25.Directus do [base_url: base_url, token: token] = Application.fetch_env!(:mse25, :directus) req = Req.new(base_url: base_url <> "/items") - Req.get!(req, url: resource, auth: {:bearer, token}) - |> payload + case Req.get!(req, url: resource, auth: {:bearer, token}) + |> payload do + {:ok, payload} -> payload + {:forbidden, message} -> message + end end - defp payload(%Req.Response{body: %{"data" => payload}}), do: payload + defp payload(%Req.Response{status: 200, body: %{"data" => payload}}), do: {:ok, payload} + + defp payload(%Req.Response{status: 401}), do: {:forbidden, "Invalid Directus credentials"} defp query_params_string(params, options), do: diff --git a/lib/mse25_web/components/layouts/app.html.heex b/lib/mse25_web/components/layouts/app.html.heex index e23bfc8..a4f3d66 100644 --- a/lib/mse25_web/components/layouts/app.html.heex +++ b/lib/mse25_web/components/layouts/app.html.heex @@ -1,32 +1,32 @@ -
-
-
- - - -

- v<%= Application.spec(:phoenix, :vsn) %> -

-
- -
-
-
-
- <.flash_group flash={@flash} /> - <%= @inner_content %> -
-
+madr
+|> Hårdrock
+|> Programmering
+|> Ljudteknik
+|> Åsikter + + + +
+ +
+ + + +<%= @inner_content %> + + diff --git a/lib/mse25_web/components/layouts/root.html.heex b/lib/mse25_web/components/layouts/root.html.heex index 0ee8d40..4ef074f 100644 --- a/lib/mse25_web/components/layouts/root.html.heex +++ b/lib/mse25_web/components/layouts/root.html.heex @@ -1,15 +1,13 @@ - + - - - + + + <.live_title suffix=" · Phoenix Framework"> <%= assigns[:page_title] || "Mse25" %> - - + <%= @inner_content %> diff --git a/lib/mse25_web/controllers/item_controller.ex b/lib/mse25_web/controllers/item_controller.ex new file mode 100644 index 0000000..26532c6 --- /dev/null +++ b/lib/mse25_web/controllers/item_controller.ex @@ -0,0 +1,100 @@ +defmodule Mse25Web.ItemController do + use Mse25Web, :controller + alias Mse25.Directus + + def index(conn, _params) do + case conn.path_info |> fetch do + {:ok, item_type, item_data} -> + render(conn, item_type, assigns(item_type, item_data)) + + {:not_found, message} -> + render(conn, message) + end + end + + defp fetch([year, slug], :article) do + case Directus.get_article(year <> "/" <> slug) do + {:ok, response} -> {:ok, :article, response} + _ -> fetch([year, slug], :link) + end + end + + defp fetch([year, slug], :link) do + case Directus.get_link(year <> "/" <> slug) do + {:ok, response} -> {:ok, :link, response} + _ -> fetch([year, slug], :event) + end + end + + defp fetch([year, slug], :event) do + case Directus.get_event(year <> "/" <> slug) do + {:ok, response} -> {:ok, :event, response} + not_found -> not_found + end + end + + defp fetch([year, slug]) do + fetch([year, slug], :article) + end + + defp fetch([slug]) do + case Directus.get_page(slug) do + {:ok, response} -> {:ok, :page, response} + not_found -> not_found + end + end + + defp assigns(:article, %{ + "title" => heading, + "contents" => contents, + "pubDate" => published_at, + "date_updated" => updated_at + }) do + [ + heading: heading, + contents: Earmark.as_html!(contents), + published_at: published_at, + updated_at: updated_at + ] + end + + defp assigns(:event, %{ + "title" => heading, + "contents" => contents, + "started_at" => published_at + }) do + [ + heading: heading, + contents: Earmark.as_html!(contents), + published_at: published_at + ] + end + + defp assigns(:link, %{ + "title" => heading, + "contents" => contents, + "pubDate" => published_at, + "source" => url, + "h1" => title + }) do + [ + heading: heading, + contents: Earmark.as_html!(contents), + published_at: published_at, + url: url, + title: title + ] + end + + defp assigns(:page, %{ + "title" => heading, + "contents" => contents, + "date_updated" => updated_at + }) do + [ + heading: heading, + contents: Earmark.as_html!(contents), + updated_at: updated_at + ] + end +end diff --git a/lib/mse25_web/controllers/item_html.ex b/lib/mse25_web/controllers/item_html.ex new file mode 100644 index 0000000..3d61b61 --- /dev/null +++ b/lib/mse25_web/controllers/item_html.ex @@ -0,0 +1,5 @@ +defmodule Mse25Web.ItemHTML do + use Mse25Web, :html + + embed_templates "item_html/*" +end diff --git a/lib/mse25_web/controllers/item_html/article.html.heex b/lib/mse25_web/controllers/item_html/article.html.heex new file mode 100644 index 0000000..4f64043 --- /dev/null +++ b/lib/mse25_web/controllers/item_html/article.html.heex @@ -0,0 +1,12 @@ +
+
+<%= @published_at %> +

<%= @heading %>

+
+ +<%= raw @contents %> + +
+

Skribent: Anders Englöf Ytterström. Publicerad <%= @published_at %> och senast uppdaterad <%= @updated_at %>.

+
+
diff --git a/lib/mse25_web/controllers/item_html/event.html.heex b/lib/mse25_web/controllers/item_html/event.html.heex new file mode 100644 index 0000000..0a60fbf --- /dev/null +++ b/lib/mse25_web/controllers/item_html/event.html.heex @@ -0,0 +1,9 @@ +
+
+<%= @published_at %> +

<%= @heading %>

+
+ +<%= raw @contents %> + +
diff --git a/lib/mse25_web/controllers/item_html/link.html.heex b/lib/mse25_web/controllers/item_html/link.html.heex new file mode 100644 index 0000000..fa5d489 --- /dev/null +++ b/lib/mse25_web/controllers/item_html/link.html.heex @@ -0,0 +1,14 @@ +
+
+<%= @published_at %> +

<%= @heading %>

+
+ +<%= raw @contents %> +

+Källa: <%= @title %> +

+
+

Skribent: Anders Englöf Ytterström. Publicerad <%= @published_at %>.

+
+
diff --git a/lib/mse25_web/controllers/item_html/page.html.heex b/lib/mse25_web/controllers/item_html/page.html.heex new file mode 100644 index 0000000..ce0d64a --- /dev/null +++ b/lib/mse25_web/controllers/item_html/page.html.heex @@ -0,0 +1,11 @@ +
+
+

<%= @heading %>

+
+ +<%= raw @contents %> + +
+

Skribent: Anders Englöf Ytterström. Senast uppdaterad <%= @updated_at %>.

+
+
diff --git a/lib/mse25_web/controllers/item_html/show.html.heex b/lib/mse25_web/controllers/item_html/show.html.heex new file mode 100644 index 0000000..4f64043 --- /dev/null +++ b/lib/mse25_web/controllers/item_html/show.html.heex @@ -0,0 +1,12 @@ +
+
+<%= @published_at %> +

<%= @heading %>

+
+ +<%= raw @contents %> + + +
diff --git a/lib/mse25_web/router.ex b/lib/mse25_web/router.ex index e50d9cf..bc0203d 100644 --- a/lib/mse25_web/router.ex +++ b/lib/mse25_web/router.ex @@ -18,6 +18,20 @@ defmodule Mse25Web.Router do pipe_through :browser get "/", PageController, :home + + # get "/evenemang", EventController, :index + # get "/kommande-evenemang.ics", EventController, :calendar + # get "/event-map.js", EventController, :interactive_map + + # get "/webblogg", ArticleController, :index + # get "/webblogg/prenumerera.xml", ArticleController, :feed + + # get "/delningar", ShareController, :index + # get "/delningar/prenumerera.xml", ShareController, :feed + + # get "/:year", TimelineController, :annual + # get "/prenumerera.xml", TimelineController, :feed + get "/*path", ItemController, :index end # Other scopes may use custom stacks. diff --git a/mix.exs b/mix.exs index 5eceae4..900df28 100644 --- a/mix.exs +++ b/mix.exs @@ -45,7 +45,8 @@ defmodule Mse25.MixProject do {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.1.1"}, {:bandit, "~> 1.5"}, - {:req, "~> 0.5.0"} + {:req, "~> 0.5.0"}, + {:earmark, "~> 1.4"} ] end diff --git a/mix.lock b/mix.lock index cfac2f4..a7c66ad 100644 --- a/mix.lock +++ b/mix.lock @@ -2,6 +2,7 @@ "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, + "earmark": {:hex, :earmark, "1.4.47", "7e7596b84fe4ebeb8751e14cbaeaf4d7a0237708f2ce43630cfd9065551f94ca", [:mix], [], "hexpm", "3e96bebea2c2d95f3b346a7ff22285bc68a99fbabdad9b655aa9c6be06c698f8"}, "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"}, "expo": {:hex, :expo, "1.0.1", "f9e2f984f5b8d195815d52d0ba264798c12c8d2f2606f76fa4c60e8ebe39474d", [:mix], [], "hexpm", "f250b33274e3e56513644858c116f255d35c767c2b8e96a512fe7839ef9306a1"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},