From 02e6340c0adcd369dcf2a357d3162636ffdab6be Mon Sep 17 00:00:00 2001 From: Thelonius Kort Date: Tue, 28 Feb 2023 23:38:56 +0100 Subject: [PATCH] Add embedded schema for Artikel --- lib/outlook/public.ex | 64 +++++++++++++++++++ lib/outlook/public/artikel.ex | 43 +++++++++++++ .../components/public_components.ex | 4 +- .../controllers/artikel_controller.ex | 6 +- .../controllers/artikel_html/show.html.heex | 2 +- .../controllers/autor_html/show.html.heex | 2 +- 6 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 lib/outlook/public.ex create mode 100644 lib/outlook/public/artikel.ex diff --git a/lib/outlook/public.ex b/lib/outlook/public.ex new file mode 100644 index 0000000..73675b0 --- /dev/null +++ b/lib/outlook/public.ex @@ -0,0 +1,64 @@ +defmodule Outlook.Public do +@moduledoc """ +This should replace Outlook.Artikel and Outlook.Autoren for +both of which embedded schemas should be created, for Artikel the schema should +implement to_param protocol (no more needed for Outlook.Translations.Translation then). +""" + + alias Outlook.Translations.Translation + alias Outlook.Articles.Article + alias Outlook.Authors.Author + alias Outlook.Public.Artikel + + import Ecto.Query, warn: false + alias Outlook.Repo + + def list_artikel(language \\ "DE") do + q = from t in Translation, + join: a in Article, on: t.article_id == a.id, + join: au in Author, on: a.author_id == au.id, + select: [ + title: t.title, + date: t.date, + teaser: t.teaser, + id: t.id, + date_org: a.date, + autor_name: au.name, + ], + where: t.public == true and t.language == ^language, + order_by: [desc: t.date] + Repo.all(q) + |> Enum.map(fn rec -> Enum.into(rec, %{}) end) + |> Enum.map(fn map -> struct(Artikel, map) end) + end + + def get_artikel!(artikel) when is_struct(artikel), do: get_artikel!(artikel.id) + def get_artikel!(id) do + q = from t in Translation, + join: a in Article, on: t.article_id == a.id, + join: au in Author, on: a.author_id == au.id, + select: [ + title: t.title, + date: t.date, + public_content: t.public_content, + title_org: a.title, + url_org: a.url, + date_org: a.date, + author: au.name, + author_id: au.id + ], + where: t.id == ^id and t.public == true + case Repo.one(q) do + nil -> {:error, "Artikel does not exist, or isn't public."} + artikel -> {:ok, struct(Artikel, artikel |> Enum.into(%{}))} + end + end + + def get_artikel_by_tid(tid) do + tid + |> String.split(~r/--(?=[0-9A-Za-z])/) + |> List.last() + |> String.to_integer(36) + |> get_artikel!() + end +end diff --git a/lib/outlook/public/artikel.ex b/lib/outlook/public/artikel.ex new file mode 100644 index 0000000..2c803c7 --- /dev/null +++ b/lib/outlook/public/artikel.ex @@ -0,0 +1,43 @@ +defmodule Outlook.Public.Artikel do + use Ecto.Schema + + alias Outlook.Public.Artikel + + embedded_schema do + field :title, :string + field :date, :utc_datetime + field :public_content, :string + field :title_org, :string + field :url_org, :string + field :date_org, :utc_datetime + field :autor_name, :string + field :author_id, :integer + field :teaser, :string + # field :autor, Autor + end + + def translate_unicode(str) do + mapping = %{"Ä" => "Ae", + "Ö" => "Oe", + "Ü" => "Ue", + "ä" => "ae", + "ö" => "oe", + "ü" => "ue", + "ß" => "ss"} + {:ok, re} = "[#{Map.keys(mapping) |> Enum.join}]" |> Regex.compile("u") + Regex.replace(re, str, fn(c) -> mapping[c] end) + end + + def spit_title(title) do + title + |> translate_unicode() + |> String.replace(~r/[^\w\s-]/u, "") + |> String.replace(~r/(\s|-)+/u, "-") + end + + defimpl Phoenix.Param, for: Artikel do + def to_param(%{id: id, title: title}) do + "#{Artikel.spit_title(title)}--#{Integer.to_string(id, 36) |> String.downcase()}" + end + end +end diff --git a/lib/outlook_web/components/public_components.ex b/lib/outlook_web/components/public_components.ex index 5a467db..1205a8e 100644 --- a/lib/outlook_web/components/public_components.ex +++ b/lib/outlook_web/components/public_components.ex @@ -23,14 +23,14 @@ defmodule OutlookWeb.PublicComponents do end attr :artikel, :any, required: true - attr :show_author, :boolean, default: true + attr :show_autor, :boolean, default: true def artikel(assigns) do ~H""" <.link navigate={~p"/artikel/#{@artikel}"}>

<%= @artikel.title %>

-
<%= @artikel.article.author.name %>
+
<%= @artikel.autor_name %>
<%= @artikel.date |> Calendar.strftime("%d.%m.%Y") %>
<%= @artikel.teaser |> tidy_raw %>
diff --git a/lib/outlook_web/controllers/artikel_controller.ex b/lib/outlook_web/controllers/artikel_controller.ex index 125996c..ef65c83 100644 --- a/lib/outlook_web/controllers/artikel_controller.ex +++ b/lib/outlook_web/controllers/artikel_controller.ex @@ -1,15 +1,15 @@ defmodule OutlookWeb.ArtikelController do use OutlookWeb, :controller - alias Outlook.Artikel + alias Outlook.Public def index(conn, _params) do - artikel = Artikel.list_artikel() + artikel = Public.list_artikel() render(conn, :index, artikel: artikel, page_title: "Artikel") end def show(conn, %{"tid" => tid} = params) do - case Artikel.get_artikel_by_tid(tid) do + case Public.get_artikel_by_tid(tid) do {:ok, artikel} -> render(conn, :show, artikel: artikel, page_title: artikel.title) {:error, message} -> conn |> put_status(404) diff --git a/lib/outlook_web/controllers/artikel_html/show.html.heex b/lib/outlook_web/controllers/artikel_html/show.html.heex index 82cac5e..fa2390b 100644 --- a/lib/outlook_web/controllers/artikel_html/show.html.heex +++ b/lib/outlook_web/controllers/artikel_html/show.html.heex @@ -1,6 +1,6 @@

<%= @artikel.title %>

-

<.link href={~p"/autoren/#{@artikel.author_id}"}><%= @artikel.author %> +

<.link href={~p"/autoren/#{@artikel.author_id}"}><%= @artikel.autor_name %>     —    <%= Calendar.strftime(@artikel.date_org, "%d.%m.%Y") %>

Original Artikel: <.link class="hover:text-sky-700" href={@artikel.url_org} > diff --git a/lib/outlook_web/controllers/autor_html/show.html.heex b/lib/outlook_web/controllers/autor_html/show.html.heex index c335f06..5272e73 100644 --- a/lib/outlook_web/controllers/autor_html/show.html.heex +++ b/lib/outlook_web/controllers/autor_html/show.html.heex @@ -7,7 +7,7 @@ <%= for article <- @autor.articles do %> - <.artikel :for={translation <- article.translations} artikel={translation} show_author={false} /> + <.artikel :for={translation <- article.translations} artikel={translation} show_autor={false} /> <% end %> <.back navigate={~p"/autoren"}>Back to autoren