Add backlinks
This commit is contained in:
parent
4ba50f9fb5
commit
28cd37966a
|
@ -56,6 +56,19 @@ defmodule Wiki.Content do
|
||||||
%Page{}
|
%Page{}
|
||||||
|> Page.changeset(attrs)
|
|> Page.changeset(attrs)
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
|
|> case do
|
||||||
|
{:ok, page} ->
|
||||||
|
content = Map.get(attrs, "content") || Map.get(attrs, :content)
|
||||||
|
|
||||||
|
unless is_nil(content) do
|
||||||
|
Page.update_page_links(%Page{page | content: content})
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, page}
|
||||||
|
|
||||||
|
{:error, reason} ->
|
||||||
|
{:error, reason}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -74,6 +87,19 @@ defmodule Wiki.Content do
|
||||||
page
|
page
|
||||||
|> Page.changeset(attrs)
|
|> Page.changeset(attrs)
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
|
|> case do
|
||||||
|
{:ok, page} ->
|
||||||
|
content = Map.get(attrs, "content") || Map.get(attrs, :content)
|
||||||
|
|
||||||
|
unless is_nil(content) do
|
||||||
|
Page.update_page_links(%Page{page | content: content})
|
||||||
|
end
|
||||||
|
|
||||||
|
{:ok, page}
|
||||||
|
|
||||||
|
{:error, reason} ->
|
||||||
|
{:error, reason}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
defmodule Wiki.Content.Page do
|
defmodule Wiki.Content.Page do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
import Ecto.Query
|
||||||
|
alias Wiki.Repo
|
||||||
|
alias Wiki.Content.PageLink
|
||||||
|
|
||||||
@type t() :: %__MODULE__{
|
@type t() :: %__MODULE__{
|
||||||
encrypted_content: binary(),
|
encrypted_content: binary(),
|
||||||
|
@ -32,6 +35,14 @@ defmodule Wiki.Content.Page do
|
||||||
belongs_to :user, Wiki.Accounts.User
|
belongs_to :user, Wiki.Accounts.User
|
||||||
has_many :uploads, Wiki.Content.Upload
|
has_many :uploads, Wiki.Content.Upload
|
||||||
|
|
||||||
|
# Pages that this page links to
|
||||||
|
has_many :_pages_linked_to, PageLink, foreign_key: :from_id
|
||||||
|
has_many :pages_linked_to, through: [:_pages_linked_to, :to]
|
||||||
|
|
||||||
|
# Pages that link to this page
|
||||||
|
has_many :_pages_linked_from, PageLink, foreign_key: :to_id
|
||||||
|
has_many :pages_linked_from, through: [:_pages_linked_from, :from]
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,7 +76,7 @@ defmodule Wiki.Content.Page do
|
||||||
{encrypted_content, tag, iv} = do_encrypt(content, key)
|
{encrypted_content, tag, iv} = do_encrypt(content, key)
|
||||||
|
|
||||||
user_id = get_field(changeset, :user_id)
|
user_id = get_field(changeset, :user_id)
|
||||||
{html, _linked_pages} = Wiki.Content.Renderer.render(content, user_id)
|
html = Wiki.Content.Renderer.render(content, user_id)
|
||||||
{encrypted_html, html_tag, html_iv} = do_encrypt(html, key)
|
{encrypted_html, html_tag, html_iv} = do_encrypt(html, key)
|
||||||
|
|
||||||
changeset
|
changeset
|
||||||
|
@ -122,4 +133,22 @@ defmodule Wiki.Content.Page do
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec update_page_links(page :: __MODULE__.t()) :: :ok
|
||||||
|
def update_page_links(%__MODULE__{content: content, id: id} = page) when is_binary(content) do
|
||||||
|
linked_page_ids = Wiki.Content.Renderer.get_linked_pages(page)
|
||||||
|
|
||||||
|
if length(linked_page_ids) == 0 do
|
||||||
|
Repo.delete_all(from link in PageLink, where: link.from_id == ^id)
|
||||||
|
else
|
||||||
|
Repo.delete_all(
|
||||||
|
from link in PageLink, where: link.from_id == ^id and not (link.to_id in ^linked_page_ids)
|
||||||
|
)
|
||||||
|
|
||||||
|
values = Enum.map(linked_page_ids, fn to_id -> [from_id: id, to_id: to_id] end)
|
||||||
|
Repo.insert_all(PageLink, values, on_conflict: :nothing)
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
defmodule Wiki.Content.PageLink do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "page_links" do
|
||||||
|
belongs_to :from, Wiki.Content.Page
|
||||||
|
belongs_to :to, Wiki.Content.Page
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(page_link, attrs) do
|
||||||
|
page_link
|
||||||
|
|> cast(attrs, [:from_id, :to_id])
|
||||||
|
|> validate_required([:from_id, :to_id])
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,14 +5,18 @@ defmodule Wiki.Content.Renderer do
|
||||||
alias WikiWeb.Endpoint
|
alias WikiWeb.Endpoint
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
@spec render(String.t(), integer()) :: {String.t(), [integer()]}
|
@spec render(String.t(), integer()) :: String.t()
|
||||||
def render(content, user_id) do
|
def render(content, user_id) do
|
||||||
{content, linked_pages} = replace_page_links(content, user_id)
|
{content, _linked_pages} = replace_page_links(content, user_id)
|
||||||
|
|
||||||
{
|
content
|
||||||
render_markdown(content),
|
|> render_markdown()
|
||||||
Enum.uniq(linked_pages)
|
end
|
||||||
}
|
|
||||||
|
@spec get_linked_pages(page :: Page.t()) :: [integer()]
|
||||||
|
def get_linked_pages(%Page{content: content, user_id: user_id}) do
|
||||||
|
{_content, linked_pages} = replace_page_links(content, user_id)
|
||||||
|
Enum.uniq(linked_pages)
|
||||||
end
|
end
|
||||||
|
|
||||||
@page_link_regex ~r/\[\[.*?\]\]/
|
@page_link_regex ~r/\[\[.*?\]\]/
|
||||||
|
|
|
@ -85,7 +85,7 @@ defmodule WikiWeb.PageController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(conn, _params) do
|
def show(conn, _params) do
|
||||||
page = Repo.preload(conn.assigns.page, :uploads)
|
page = Repo.preload(conn.assigns.page, [:uploads, :pages_linked_from])
|
||||||
render(conn, "show.html", page: page)
|
render(conn, "show.html", page: page)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,3 +20,14 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<h2>Backlinks</h2>
|
||||||
|
<ul>
|
||||||
|
<%= for page <- @page.pages_linked_from do %>
|
||||||
|
<li>
|
||||||
|
<a href="<%= Routes.page_path(@conn, :show, page.id) %>">
|
||||||
|
<%= page.title %>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
defmodule Wiki.Repo.Migrations.CreatePageLinks do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:page_links) do
|
||||||
|
add :from_id, references(:pages, on_delete: :nothing), primary_key: true
|
||||||
|
add :to_id, references(:pages, on_delete: :nothing), primary_key: true
|
||||||
|
end
|
||||||
|
|
||||||
|
create index(:page_links, [:from_id])
|
||||||
|
create index(:page_links, [:to_id])
|
||||||
|
|
||||||
|
create unique_index(:page_links, [:from_id, :to_id],
|
||||||
|
name: :page_link_from_id_to_id_unique_index
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue