From 89b93cf231ca8b906343f4f840bb5d6d1440f618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Engl=C3=B6f=20Ytterstr=C3=B6m?= Date: Thu, 3 Oct 2024 14:38:56 +0200 Subject: [PATCH] List shared links (#15) * Exclude not published items in directus client * Add link view to page controller * Add page controller links list view to router * Add links list view CSS * Add permalink view for link * Improve page titles * Let user copy link permalink to clipboard if alt, shift or ctrl are pressed, fallback to default behavior. --- assets/app.css | 40 +++++----- assets/js/app.js | 8 +- assets/js/copy-to-clipboard.js | 26 +++++-- lib/mse25/directus.ex | 8 ++ .../components/layouts/root.html.heex | 2 +- lib/mse25_web/controllers/item_controller.ex | 26 ++++--- .../controllers/item_html/link.html.heex | 45 +++++++++--- lib/mse25_web/controllers/page_controller.ex | 18 ++++- .../controllers/page_html/links.html.heex | 73 +++++++++++++++++++ lib/mse25_web/router.ex | 3 +- 10 files changed, 200 insertions(+), 49 deletions(-) create mode 100644 lib/mse25_web/controllers/page_html/links.html.heex diff --git a/assets/app.css b/assets/app.css index 55bb4fb..11d454e 100644 --- a/assets/app.css +++ b/assets/app.css @@ -118,23 +118,6 @@ main { font-size: large; box-sizing: border-box; - > pre { - margin: 2em 0; - background-color: #022; - overflow-y: auto; - padding: 0.33em; - box-shadow: 4px 4px 0 #333; - position: relative; - line-height: 1.2; - font-size: 0.8em; - - > button { - position: absolute; - top: 0.25em; - right: 0.25em; - } - } - > footer { font-style: italic; text-align: right; @@ -142,6 +125,23 @@ main { } } +pre { + margin: 2em 0; + background-color: #022; + overflow-y: auto; + padding: 0.33em; + box-shadow: 4px 4px 0 #333; + position: relative; + line-height: 1.2; + font-size: 0.8em; + + > button { + position: absolute; + top: 0.25em; + right: 0.25em; + } +} + code { font-family: "JetBrains mono", monaco, menlo, meslo, "Courier New", Courier, monospace; @@ -193,3 +193,9 @@ section > h2 { padding: 0.25em 0.5em; } } + +.links { + > :is(h2, h3) { + margin-top: 3em; + } +} diff --git a/assets/js/app.js b/assets/js/app.js index 8fc7e57..3d91e67 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -44,6 +44,10 @@ import "../app.css"; -import copyToClipboard from "./copy-to-clipboard.js"; +import { + copyCodeToClipboard, + copyUrlToClipboard, +} from "./copy-to-clipboard.js"; -copyToClipboard(); +copyCodeToClipboard(); +copyUrlToClipboard(); diff --git a/assets/js/copy-to-clipboard.js b/assets/js/copy-to-clipboard.js index fa5d2db..5db1d66 100644 --- a/assets/js/copy-to-clipboard.js +++ b/assets/js/copy-to-clipboard.js @@ -1,14 +1,30 @@ -export default () => { +export const copyCodeToClipboard = () => { const codeblocks = document.querySelectorAll("pre>code"); - for (const b of codeblocks) { const button = document.createElement("button"); button.innerHTML = "Kopiera"; - button.addEventListener("click", function ({target}) { + button.addEventListener("click", function ({ target }) { const text = target.previousSibling.innerHTML; navigator.clipboard.writeText(text); - }) + }); b.parentNode.appendChild(button); } -} +}; +export const copyUrlToClipboard = () => { + const permalinks = document.querySelectorAll(".permalink"); + for (const pl of permalinks) { + pl.setAttribute( + "title", + pl.getAttribute("title") + ", klicka för att kopiera", + ); + pl.addEventListener("click", function (evt) { + const { target, shiftKey, ctrlKey, altKey } = evt; + if (!shiftKey && !ctrlKey && !altKey) { + evt.preventDefault(); + const text = target.href; + navigator.clipboard.writeText(text); + } + }); + } +}; diff --git a/lib/mse25/directus.ex b/lib/mse25/directus.ex index a6b4952..fc8fcbd 100644 --- a/lib/mse25/directus.ex +++ b/lib/mse25/directus.ex @@ -1,4 +1,6 @@ defmodule Mse25.Directus do + @draft_filter "filter[status][_eq]=published" + def get_article(slug) do get_item(:articles, slug) end @@ -173,6 +175,12 @@ defmodule Mse25.Directus do [base_url: base_url, token: token] = Application.fetch_env!(:mse25, :directus) req = Req.new(base_url: base_url <> "/items") + resource = + case String.contains?(resource, "?") do + true -> resource <> "&" <> @draft_filter + false -> resource <> "?" <> @draft_filter + end + case Req.get!(req, url: resource, auth: {:bearer, token}) |> payload do {:ok, payload} -> payload diff --git a/lib/mse25_web/components/layouts/root.html.heex b/lib/mse25_web/components/layouts/root.html.heex index bdb8948..6274a51 100644 --- a/lib/mse25_web/components/layouts/root.html.heex +++ b/lib/mse25_web/components/layouts/root.html.heex @@ -4,7 +4,7 @@ - <%= assigns[:page_title] || "Anders Englöf Ytterström" %> + <%= assigns[:page_title] || "Anders Englöf Ytterström" %> | madr.se diff --git a/lib/mse25_web/controllers/item_controller.ex b/lib/mse25_web/controllers/item_controller.ex index 6b3fe76..ed456bb 100644 --- a/lib/mse25_web/controllers/item_controller.ex +++ b/lib/mse25_web/controllers/item_controller.ex @@ -50,17 +50,16 @@ defmodule Mse25Web.ItemController do "pubDate" => published_at, "date_updated" => updated_at }) do - updated = - case updated_at do - nil -> published_at - s -> String.slice(s, 0..9) - end - [ + page_title: heading, heading: heading, contents: Earmark.as_html!(contents), published_at: published_at, - updated_at: updated, + updated_at: + case updated_at do + nil -> published_at + ua -> String.slice(ua, 0..9) + end, year: String.slice(published_at, 0..3) ] end @@ -72,11 +71,12 @@ defmodule Mse25Web.ItemController do "lead" => lead }) do [ + page_title: heading, heading: heading, contents: Earmark.as_html!(contents), published_at: published_at, lead: lead, - year: 2024 + year: String.slice(published_at, 0..3) ] end @@ -84,15 +84,23 @@ defmodule Mse25Web.ItemController do "title" => heading, "contents" => contents, "pubDate" => published_at, + "date_updated" => updated_at, "source" => url, "h1" => title }) do [ + page_title: heading, heading: heading, contents: Earmark.as_html!(contents), published_at: published_at, url: url, - title: title + title: title, + year: String.slice(published_at, 0..3), + updated_at: + case updated_at do + nil -> published_at + ua -> String.slice(ua, 0..9) + end ] end diff --git a/lib/mse25_web/controllers/item_html/link.html.heex b/lib/mse25_web/controllers/item_html/link.html.heex index fa5d489..0df57c5 100644 --- a/lib/mse25_web/controllers/item_html/link.html.heex +++ b/lib/mse25_web/controllers/item_html/link.html.heex @@ -1,14 +1,35 @@ -
-
-<%= @published_at %> -

<%= @heading %>

-
+ diff --git a/lib/mse25_web/controllers/page_controller.ex b/lib/mse25_web/controllers/page_controller.ex index a71ac7e..b1af2d8 100644 --- a/lib/mse25_web/controllers/page_controller.ex +++ b/lib/mse25_web/controllers/page_controller.ex @@ -10,7 +10,7 @@ defmodule Mse25Web.PageController do brutal_legends = Directus.get_albums!(limit: 1) render(conn, :home, - page_title: "Anders Englöf Ytterström @ madr.se", + page_title: "Anders Englöf Ytterström", layout: false, recent_article: most_recent_article, older_article: older_article, @@ -29,10 +29,26 @@ defmodule Mse25Web.PageController do ) end + def links(conn, _params) do + links = Directus.get_links!(limit: 9999) |> group_by_date + + render(conn, :links, + page_title: "Delningar", + links: links + ) + end + defp group_annually(items) do items |> Enum.group_by(fn %{"slug" => slug} -> String.slice(slug, 0..3) end) |> Map.to_list() |> Enum.sort(fn {a, _a}, {b, _b} -> b < a end) end + + defp group_by_date(items) do + items + |> Enum.group_by(fn %{"pubDate" => pub_date} -> pub_date end) + |> Map.to_list() + |> Enum.sort(fn {a, _a}, {b, _b} -> b < a end) + end end diff --git a/lib/mse25_web/controllers/page_html/links.html.heex b/lib/mse25_web/controllers/page_html/links.html.heex new file mode 100644 index 0000000..4e000a9 --- /dev/null +++ b/lib/mse25_web/controllers/page_html/links.html.heex @@ -0,0 +1,73 @@ +
+ +

Delningar

+

+ Länkar som är värda att uppmärksammas och lämna åsikt om. +

+ <%= for {date, links} <- @links do %> +
date}> + +
+ <% end %> +
diff --git a/lib/mse25_web/router.ex b/lib/mse25_web/router.ex index 062178a..636a273 100644 --- a/lib/mse25_web/router.ex +++ b/lib/mse25_web/router.ex @@ -24,8 +24,7 @@ defmodule Mse25Web.Router do # get "/event-map.js", EventController, :interactive_map get "/webblogg", PageController, :articles - - # get "/delningar", ShareController, :index + get "/delningar", PageController, :links # get "/:year", TimelineController, :annual # get "/prenumerera.xml", TimelineController, :feed