From 780a645feea962f747fee6dc9ff2acaa45a8c50e Mon Sep 17 00:00:00 2001 From: Inhji Date: Wed, 13 Sep 2023 20:59:15 +0200 Subject: [PATCH] autotagging --- assets/css/app.css | 23 +++++++++ lib/chiya/notes.ex | 6 ++- lib/chiya/notes/note_tag.ex | 1 + lib/chiya/tags.ex | 3 +- lib/chiya/tags/tag_updater.ex | 47 ++++++++++--------- lib/chiya_web/controllers/page_controller.ex | 31 ++++++------ lib/chiya_web/controllers/page_html.ex | 2 +- lib/chiya_web/controllers/tag_controller.ex | 21 +++++++-- .../tag_html/apply_prepare.html.heex | 14 +++--- .../controllers/tag_html/index.html.heex | 36 ++++++++++++-- lib/chiya_web/router.ex | 3 +- 11 files changed, 128 insertions(+), 59 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index 480a3c8..afeef84 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -189,6 +189,29 @@ @apply hidden; } } + + /* === CARD LIST (ADMIN) === */ + + .card-list { + @apply flex flex-col gap-3 mt-6; + } + + /* === CARD (ADMIN) === */ + .card { + @apply bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 p-3 rounded; + + & header { + & h2 { + @apply text-xl leading-normal; + } + } + + & footer { + @apply flex gap-3 text-sm; + } + } + + } /* diff --git a/lib/chiya/notes.ex b/lib/chiya/notes.ex index e09cf0b..d4d978b 100644 --- a/lib/chiya/notes.ex +++ b/lib/chiya/notes.ex @@ -58,9 +58,11 @@ defmodule Chiya.Notes do Chiya.Flop.validate_and_run(q, params, for: Chiya.Notes.Note) end - def list_apply_notes(regex) do + def list_apply_notes(%Chiya.Tags.Tag{} = tag) do Note - |> where([n], fragment("? ~ ?", n.name, ^regex)) + |> where([n], fragment("? ~ ?", n.name, ^tag.regex)) + |> or_where([n], fragment("? ~ ?", n.url, ^tag.regex)) + |> or_where([n], fragment("? ~ ?", n.content, ^tag.regex)) |> Repo.all() end diff --git a/lib/chiya/notes/note_tag.ex b/lib/chiya/notes/note_tag.ex index fe27e3e..00054ac 100644 --- a/lib/chiya/notes/note_tag.ex +++ b/lib/chiya/notes/note_tag.ex @@ -15,5 +15,6 @@ defmodule Chiya.Notes.NoteTag do note_tag |> cast(attrs, [:note_id, :tag_id]) |> validate_required([:note_id, :tag_id]) + |> unique_constraint([:note_id, :tag_id]) end end diff --git a/lib/chiya/tags.ex b/lib/chiya/tags.ex index a3d16bc..4f8e111 100644 --- a/lib/chiya/tags.ex +++ b/lib/chiya/tags.ex @@ -38,9 +38,10 @@ defmodule Chiya.Tags do |> Repo.all() end - def list_admin_tags(params) do + def list_admin_tags() do q = Tag + |> order_by(:name) |> with_preloads() Repo.all(q) diff --git a/lib/chiya/tags/tag_updater.ex b/lib/chiya/tags/tag_updater.ex index dedfb8a..4272502 100644 --- a/lib/chiya/tags/tag_updater.ex +++ b/lib/chiya/tags/tag_updater.ex @@ -8,6 +8,13 @@ defmodule Chiya.Tags.TagUpdater do alias Chiya.{Notes, Tags} alias Chiya.Notes.Note + @doc """ + Updates a tag for the given note. + + ## Examples + + iex> update_tags({:ok, note}, "foo,bar") + """ def update_tags({:ok, %Note{} = note}, attrs) do note |> Notes.preload_note() @@ -20,27 +27,19 @@ defmodule Chiya.Tags.TagUpdater do {:error, changeset} end - @doc """ - Updates the tags for the given note - - ## Examples - - iex> update_tags(note, "foo,bar") - - """ - def update_tags(note, %{tags_string: new_tags} = attrs) when is_map(attrs) do + def update_tags(%Note{} = note, %{tags_string: new_tags} = attrs) when is_map(attrs) do update_tags(note, new_tags) end - def update_tags(note, %{"tags_string" => new_tags} = attrs) when is_map(attrs) do + def update_tags(%Note{} = note, %{"tags_string" => new_tags} = attrs) when is_map(attrs) do update_tags(note, new_tags) end - def update_tags(note, attrs) when is_map(attrs) do + def update_tags(%Note{} = note, attrs) when is_map(attrs) do note end - def update_tags(note, new_tags) when is_binary(new_tags) do + def update_tags(%Note{} = note, new_tags) when is_binary(new_tags) do update_tags(note, split_tags(new_tags)) end @@ -62,14 +61,7 @@ defmodule Chiya.Tags.TagUpdater do |> remove_tags(old_tags -- new_tags) end - defp split_tags(tags_string) when is_binary(tags_string) do - tags_string - |> String.split(",") - |> Enum.map(&String.trim/1) - |> Enum.filter(&(String.length(&1) > 0)) - end - - defp add_tags(note, tags) do + def add_tags(note, tags) do tags |> Enum.uniq() |> Enum.each(&add_tag(note, &1)) @@ -77,6 +69,13 @@ defmodule Chiya.Tags.TagUpdater do note end + defp split_tags(tags_string) when is_binary(tags_string) do + tags_string + |> String.split(",") + |> Enum.map(&String.trim/1) + |> Enum.filter(&(String.length(&1) > 0)) + end + defp add_tag(%{id: note_id} = note, tag) when is_binary(tag) do slug = Slugger.slugify_downcase(tag) @@ -100,7 +99,13 @@ defmodule Chiya.Tags.TagUpdater do tag_id: tag.id } - {:ok, _note_tag} = Notes.create_note_tag(attrs) + case Notes.create_note_tag(attrs) do + {:ok, _note_tag} -> + true + + {:error, changeset} -> + Logger.warn(inspect(changeset)) + end end end diff --git a/lib/chiya_web/controllers/page_controller.ex b/lib/chiya_web/controllers/page_controller.ex index 86e8cd8..9109e23 100644 --- a/lib/chiya_web/controllers/page_controller.ex +++ b/lib/chiya_web/controllers/page_controller.ex @@ -8,29 +8,26 @@ defmodule ChiyaWeb.PageController do defp put_assigns(conn, opts) do conn |> assign(:page_header, true) + |> assign(:page_title, "no title") end def home(conn, params) do settings = conn.assigns.settings - {channel, notes, meta} = - case settings.home_channel_id do - nil -> - nil + if settings.home_channel_id do + channel = Channels.get_channel!(settings.home_channel_id) + {:ok, {notes, meta}} = Chiya.Notes.list_home_notes(channel, params) - id -> - channel = Channels.get_channel!(id) - {:ok, {notes, meta}} = Chiya.Notes.list_home_notes(channel, params) - {channel, notes, meta} - end - - render(conn, :home, - channel: channel, - notes: notes, - meta: meta, - page_title: "Home", - page_header: false - ) + render(conn, :home, + channel: channel, + notes: notes, + meta: meta, + page_title: "Home", + page_header: false + ) + else + render_error(conn, :not_found) + end end def channel(conn, %{"slug" => channel_slug}) do diff --git a/lib/chiya_web/controllers/page_html.ex b/lib/chiya_web/controllers/page_html.ex index d95c03b..64edeba 100644 --- a/lib/chiya_web/controllers/page_html.ex +++ b/lib/chiya_web/controllers/page_html.ex @@ -1,6 +1,6 @@ defmodule ChiyaWeb.PageHTML do use ChiyaWeb, :html_public - import ChiyaWeb.Format, only: [pretty_datetime: 1, pretty_date: 1, datetime: 1] + import ChiyaWeb.Format, only: [pretty_datetime: 1, pretty_date: 1] embed_templates "page_html/*" diff --git a/lib/chiya_web/controllers/tag_controller.ex b/lib/chiya_web/controllers/tag_controller.ex index 08bc249..781a98f 100644 --- a/lib/chiya_web/controllers/tag_controller.ex +++ b/lib/chiya_web/controllers/tag_controller.ex @@ -2,8 +2,8 @@ defmodule ChiyaWeb.TagController do use ChiyaWeb, :controller alias Chiya.Tags - def index(conn, params) do - tags = Chiya.Tags.list_admin_tags(params) + def index(conn, _params) do + tags = Chiya.Tags.list_admin_tags() render(conn, :index, tags: tags) end @@ -13,13 +13,26 @@ defmodule ChiyaWeb.TagController do render(conn, :show, tag: tag) end - def apply(conn, %{"id" => id}) do + def apply_prepare(conn, %{"id" => id}) do tag = Tags.get_tag!(id) - notes = Chiya.Notes.list_apply_notes(tag.regex) + notes = Chiya.Notes.list_apply_notes(tag) render(conn, :apply_prepare, tag: tag, notes: notes) end + def apply_run(conn, %{"id" => id}) do + tag = Tags.get_tag!(id) + notes = Chiya.Notes.list_apply_notes(tag) + + Enum.each(notes, fn note -> + IO.inspect("Updating note: #{note.name}") + Chiya.Tags.TagUpdater.add_tags(note, [tag.slug]) + end) + + notes = Chiya.Notes.list_apply_notes(tag) + render(conn, :apply_prepare, tag: tag, notes: notes) + end + def edit(conn, %{"id" => id}) do IO.inspect(id) tag = Tags.get_tag!(id) diff --git a/lib/chiya_web/controllers/tag_html/apply_prepare.html.heex b/lib/chiya_web/controllers/tag_html/apply_prepare.html.heex index 22d8dcf..19ee56c 100644 --- a/lib/chiya_web/controllers/tag_html/apply_prepare.html.heex +++ b/lib/chiya_web/controllers/tag_html/apply_prepare.html.heex @@ -1,25 +1,25 @@ <.header> Apply Tag <%= @tag.name %> - <:subtitle>These notes will get the tag. + <:subtitle><%= Enum.count(@notes) %> notes will get the tag. <:actions> - <.link href={~p"/admin/tags/#{@tag}/apply"}> + <.link href={~p"/admin/tags/#{@tag}/apply/run"}> <.button>Apply tag -
+
<%= for note <- @notes do %> -
+
-

+

<%= note.name %>

-
+
Updated <%= from_now(note.updated_at) %> Published <%= from_now(note.published_at) %>
<% end %> -
\ No newline at end of file +
diff --git a/lib/chiya_web/controllers/tag_html/index.html.heex b/lib/chiya_web/controllers/tag_html/index.html.heex index d16959a..baadf2a 100644 --- a/lib/chiya_web/controllers/tag_html/index.html.heex +++ b/lib/chiya_web/controllers/tag_html/index.html.heex @@ -3,17 +3,43 @@ <:subtitle>Tags are tags. -
- <%= for tag <- @tags do %> -
+
+

With Regex

+ + <%= for tag <- Enum.filter(@tags, fn t -> !!t.regex end) do %> +
-

+

<%= tag.name %>

-
+
<%= Enum.count(tag.notes) %> notes Updated <%= from_now(tag.updated_at) %> + <%= if String.length(tag.regex || "") > 0 do %> + Regex: <%= tag.regex %> + <% end %> +
+
+ <% end %> +
+ +
+

Without Regex

+ + <%= for tag <- Enum.filter(@tags, fn t -> !t.regex end) do %> +
+
+

+ <%= tag.name %> +

+
+
<% end %> diff --git a/lib/chiya_web/router.ex b/lib/chiya_web/router.ex index d0f30c3..5f95378 100644 --- a/lib/chiya_web/router.ex +++ b/lib/chiya_web/router.ex @@ -77,7 +77,8 @@ defmodule ChiyaWeb.Router do resources "/tokens", TokenController, only: [:index, :show, :new, :create, :delete] resources "/tags", TagController, only: [:index, :edit, :update, :show] - get "/tags/:id/apply", TagController, :apply + get "/tags/:id/apply", TagController, :apply_prepare + get "/tags/:id/apply/run", TagController, :apply_run get "/notes/import", NoteController, :import_prepare post "/notes/import", NoteController, :import_run