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.
 
 
 
 
 

296 lines
5.5 KiB

defmodule Mirage.Notes do
@moduledoc """
The Notes context.
"""
import Ecto.Query, warn: false
alias Mirage.Repo
alias Mirage.Notes.{Note, Topic, NoteNote, NoteLink}
@note_preloads [:links, :topics, :backlinks]
@topic_preloads [notes: @note_preloads]
@doc """
Returns the list of notes.
## Examples
iex> list_notes()
[%Note{}, ...]
"""
def list_notes do
Note
|> limit(10)
|> order_by(desc: :inserted_at)
|> Repo.all()
|> Repo.preload(@note_preloads)
end
def list_notes(:last_edited) do
Note
|> limit(3)
|> order_by(desc: :updated_at)
|> Repo.all()
|> Repo.preload(@note_preloads)
end
def list_notes(:unlinked) do
q =
from n in Note,
full_join: nn in NoteNote,
on: nn.target_id == n.id or nn.source_id == n.id,
where: not like(n.title, "@%"),
where: is_nil(nn.target_id) or is_nil(nn.source_id),
select: n,
limit: 3,
preload: ^@note_preloads
q
|> Repo.all()
|> Repo.preload(@note_preloads)
end
@doc """
Gets a single note.
Raises `Ecto.NoResultsError` if the Note does not exist.
## Examples
iex> get_note!(123)
%Note{}
iex> get_note!(456)
** (Ecto.NoResultsError)
"""
def get_note!(id), do: Repo.get!(Note, id)
def get_note(id), do: Repo.get(Note, id)
def get_note_by_title(title), do: Repo.get_by(Note, title: title)
def preload_note(note), do: Repo.preload(note, @note_preloads)
@doc """
Creates a note.
## Examples
iex> create_note(%{field: value})
{:ok, %Note{}}
iex> create_note(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_note(attrs \\ %{}) do
%Note{}
|> Note.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a note.
## Examples
iex> update_note(note, %{field: new_value})
{:ok, %Note{}}
iex> update_note(note, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_note(%Note{} = note, attrs) do
note
|> Note.changeset(attrs)
|> Repo.update()
end
def update_note!(%Note{} = note, attrs) do
note
|> Note.changeset(attrs)
|> Repo.update!()
|> preload_note()
end
@doc """
Deletes a note.
## Examples
iex> delete_note(note)
{:ok, %Note{}}
iex> delete_note(note)
{:error, %Ecto.Changeset{}}
"""
def delete_note(%Note{} = note) do
Repo.delete(note)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking note changes.
## Examples
iex> change_note(note)
%Ecto.Changeset{data: %Note{}}
"""
def change_note(%Note{} = note, attrs \\ %{}) do
Note.changeset(note, attrs)
end
@doc """
Links a note to all references notes in the content-field
## Examples
A content field with the following content:
```
This is a link to [[42|some other note]]
```
will link this note to the note with id 42.
"""
def link_note(%Note{} = note) do
multi = Ecto.Multi.new()
query = from(n in NoteNote, where: n.source_id == ^note.id)
refs =
note
|> Mirage.Markdown.get_references()
|> Enum.map(&String.to_integer/1)
# Delete all old references for this note
multi =
multi
|> Ecto.Multi.delete_all(:delete_links, query)
# Create a link to all referenced notes
multi =
refs
|> Enum.map(fn ref -> %NoteNote{source_id: note.id, target_id: ref} end)
|> Enum.reduce(multi, fn link_struct, multi ->
Ecto.Multi.insert(multi, {:link, link_struct.target_id}, link_struct)
end)
Repo.transaction(multi)
end
def get_note_link!(id), do: Repo.get!(NoteLink, id)
def create_note_link(attrs \\ %{}) do
%NoteLink{}
|> NoteLink.changeset(attrs)
|> Repo.insert()
end
def delete_note_link(%NoteLink{} = note_link) do
Repo.delete(note_link)
end
@doc """
Returns the list of topics.
## Examples
iex> list_topics()
[%Topic{}, ...]
"""
def list_topics do
Repo.all(Topic)
|> Repo.preload(@topic_preloads)
end
@doc """
Gets a single topic.
Raises `Ecto.NoResultsError` if the Note topic does not exist.
## Examples
iex> get_topic!(123)
%Topic{}
iex> get_topic!(456)
** (Ecto.NoResultsError)
"""
def get_topic!(id), do: Repo.get!(Topic, id)
def preload_topic(topic), do: Repo.preload(topic, @topic_preloads)
@doc """
Creates a topic.
## Examples
iex> create_topic(%{field: value})
{:ok, %Topic{}}
iex> create_topic(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_topic(attrs \\ %{}) do
%Topic{}
|> Topic.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a topic.
## Examples
iex> update_topic(topic, %{field: new_value})
{:ok, %Topic{}}
iex> update_topic(topic, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_topic(%Topic{} = topic, attrs) do
topic
|> Topic.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a topic.
## Examples
iex> delete_topic(topic)
{:ok, %Topic{}}
iex> delete_topic(topic)
{:error, %Ecto.Changeset{}}
"""
def delete_topic(%Topic{} = topic) do
Repo.delete(topic)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking topic changes.
## Examples
iex> change_topic(topic)
%Ecto.Changeset{data: %Topic{}}
"""
def change_topic(%Topic{} = topic, attrs \\ %{}) do
Topic.changeset(topic, attrs)
end
end