My space on the web https://inhji.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

138 lines
2.8 KiB

defmodule Mirage.Notes.Tags do
import Ecto.Query, warn: false
alias Mirage.Repo
alias Mirage.Notes.{Note, Topic, NoteTopic}
@doc utils: :tag
@doc """
Updates tags of a given note.
## Examples
iex> Tags.update_tags(note, "foo,bar")
"""
def update_tags(note, new_tags) when is_binary(new_tags) do
old_tags = tags_loaded(note) |> split_tags()
new_tags = new_tags |> split_tags()
note
|> add_tags(new_tags -- old_tags)
|> remove_tags(old_tags -- new_tags)
end
@doc """
Retrieves a string of tags for a given note.
## Examples
iex> Tags.get_tags(note)
"foo,bar"
"""
def get_tags(note), do: tags_loaded(note)
@doc utils: :tag
defp add_tag(note, topic_text) when is_binary(topic_text) do
slug =
topic_text
|> Slugger.slugify()
|> String.downcase()
topic =
case Repo.get_by(Topic, %{text_slug: slug}) do
nil ->
%Topic{}
|> Topic.changeset(%{text: topic_text})
|> Repo.insert!()
topic ->
topic
end
add_tag(note, topic.id)
end
@doc utils: :tag
defp add_tag(%{note_id: note_id}, topic_id) do
add_tag(note_id, topic_id)
end
@doc utils: :tag
defp add_tag(%Note{} = note, topic_id) do
add_tag(note.id, topic_id)
end
@doc utils: :tag
defp add_tag(note_id, topic_id) do
%NoteTopic{}
|> NoteTopic.changeset(%{note_id: note_id, topic_id: topic_id})
|> Repo.insert()
end
@doc utils: :tag
defp add_tags(content, tags) when is_binary(tags) do
Enum.each(split_tags(tags), &add_tag(content, &1))
content
end
@doc utils: :tag
defp add_tags(content, tags) do
Enum.each(tags, &add_tag(content, &1))
content
end
@doc utils: :tag
defp remove_tag(content, topic_text) when is_binary(topic_text) do
case Repo.get_by(Topic, %{text: topic_text}) do
nil -> nil
topic -> remove_tag(content, topic.id)
end
end
@doc utils: :tag
defp remove_tag(%{note_id: note_id}, topic_id) do
remove_tag(note_id, topic_id)
end
@doc utils: :tag
defp remove_tag(%Note{} = note, topic_id) do
remove_tag(note.id, topic_id)
end
@doc utils: :tag
defp remove_tag(note_id, topic_id) do
case Repo.get_by(NoteTopic, %{note_id: note_id, topic_id: topic_id}) do
nil -> nil
tag -> Repo.delete(tag)
end
end
@doc utils: :tag
defp remove_tags(content, tags) when is_binary(tags) do
Enum.each(split_tags(tags), &remove_tag(content, &1))
content
end
@doc utils: :tag
defp remove_tags(content, tags) do
Enum.each(tags, &remove_tag(content, &1))
content
end
@doc utils: :tag
defp tags_loaded(%{topics: topics}) when is_list(topics) do
topics |> Enum.map_join(", ", & &1.text)
end
defp tags_loaded(_), do: ""
@doc utils: :tag
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
end