add backlinks
This commit is contained in:
@ -88,6 +88,42 @@ defmodule Memex.Contexts do
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of contexts that link to a particular slug.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> backlink(%User{id: 123})
|
||||
[%Context{}, ...]
|
||||
|
||||
iex> backlink("[other-context]", %User{id: 123})
|
||||
[%Context{content: "[other-context]"}, ...]
|
||||
|
||||
"""
|
||||
@spec backlink(String.t(), User.t()) :: [Context.t()]
|
||||
def backlink(link, %{id: user_id}) when user_id |> is_binary() do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from c in Context,
|
||||
where: fragment("? ~ ?", c.content, ^link_regex),
|
||||
order_by: c.slug
|
||||
)
|
||||
end
|
||||
|
||||
def backlink(link, _invalid_user) do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from c in Context,
|
||||
where: fragment("? ~ ?", c.content, ^link_regex),
|
||||
where: c.visibility == :public,
|
||||
order_by: c.slug
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single context.
|
||||
|
||||
|
@ -86,6 +86,42 @@ defmodule Memex.Notes do
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of notes that link to a particular slug.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> backlink(%User{id: 123})
|
||||
[%Note{}, ...]
|
||||
|
||||
iex> backlink("[other-note]", %User{id: 123})
|
||||
[%Note{content: "[other-note]"}, ...]
|
||||
|
||||
"""
|
||||
@spec backlink(String.t(), User.t()) :: [Note.t()]
|
||||
def backlink(link, %{id: user_id}) when user_id |> is_binary() do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from n in Note,
|
||||
where: fragment("? ~ ?", n.content, ^link_regex),
|
||||
order_by: n.slug
|
||||
)
|
||||
end
|
||||
|
||||
def backlink(link, _invalid_user) do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from n in Note,
|
||||
where: fragment("? ~ ?", n.content, ^link_regex),
|
||||
where: n.visibility == :public,
|
||||
order_by: n.slug
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single note.
|
||||
|
||||
|
@ -142,6 +142,50 @@ defmodule Memex.Pipelines do
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the list of pipelines that link to a particular slug.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> backlink(%User{id: 123})
|
||||
[%Pipeline{}, ...]
|
||||
|
||||
iex> backlink("[other-pipeline]", %User{id: 123})
|
||||
[%Pipeline{description: "[other-pipeline]"}, ...]
|
||||
|
||||
"""
|
||||
@spec backlink(String.t(), User.t()) :: [Pipeline.t()]
|
||||
def backlink(link, %{id: user_id}) when user_id |> is_binary() do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from p in Pipeline,
|
||||
left_join: s in assoc(p, :steps),
|
||||
where:
|
||||
fragment("? ~ ?", p.description, ^link_regex) or
|
||||
fragment("? ~ ?", s.content, ^link_regex),
|
||||
distinct: true,
|
||||
order_by: p.slug
|
||||
)
|
||||
end
|
||||
|
||||
def backlink(link, _invalid_user) do
|
||||
link = link |> String.replace("[", "\\[") |> String.replace("]", "\\]")
|
||||
link_regex = "(^|[^\[])#{link}($|[^\]])"
|
||||
|
||||
Repo.all(
|
||||
from p in Pipeline,
|
||||
left_join: s in assoc(p, :steps),
|
||||
where:
|
||||
fragment("? ~ ?", p.description, ^link_regex) or
|
||||
fragment("? ~ ?", s.content, ^link_regex),
|
||||
where: p.visibility == :public,
|
||||
distinct: true,
|
||||
order_by: p.slug
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a pipeline.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule MemexWeb.ContextLive.Show do
|
||||
use MemexWeb, :live_view
|
||||
alias Memex.Contexts
|
||||
alias Memex.{Contexts, Pipelines}
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
@ -23,7 +23,9 @@ defmodule MemexWeb.ContextLive.Show do
|
||||
socket
|
||||
|> assign(
|
||||
context: context,
|
||||
page_title: page_title(live_action, context)
|
||||
page_title: page_title(live_action, context),
|
||||
context_backlinks: Contexts.backlink("[#{context.slug}]", current_user),
|
||||
pipeline_backlinks: Pipelines.backlink("[[#{context.slug}]]", current_user)
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
|
@ -11,6 +11,27 @@
|
||||
|
||||
<.context_content context={@context} />
|
||||
|
||||
<div
|
||||
:if={@context_backlinks ++ @pipeline_backlinks != []}
|
||||
class="flex flex-wrap justify-end items-center self-end"
|
||||
>
|
||||
<p><%= gettext("Backlinked by:") %></p>
|
||||
<.link
|
||||
:for={backlink <- @context_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/context/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[%{slug}]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
<.link
|
||||
:for={backlink <- @pipeline_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/pipeline/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[[%{slug}]]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<p class="self-end">
|
||||
<%= gettext("Visibility: %{visibility}", visibility: @context.visibility) %>
|
||||
</p>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="mx-auto flex flex-col justify-center items-stretch space-y-4 max-w-lg">
|
||||
<h1 class="title text-primary-400 text-xl">
|
||||
<div class="flex flex-col justify-center items-stretch mx-auto space-y-4 max-w-lg">
|
||||
<h1 class="text-xl title text-primary-400">
|
||||
<%= gettext("memEx") %>
|
||||
</h1>
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li class="flex flex-col justify-center items-center text-right space-y-2">
|
||||
<li class="flex flex-col justify-center items-center space-y-2 text-right">
|
||||
<.link navigate={~p"/faq"} class="btn btn-primary">
|
||||
<%= gettext("read more on how to use memEx") %>
|
||||
</.link>
|
||||
@ -41,7 +41,7 @@
|
||||
<hr class="hr" />
|
||||
|
||||
<ul class="flex flex-col space-y-4">
|
||||
<h2 class="title text-primary-400 text-lg">
|
||||
<h2 class="text-lg title text-primary-400">
|
||||
<%= gettext("features") %>
|
||||
</h2>
|
||||
|
||||
@ -71,12 +71,21 @@
|
||||
<%= gettext("accessible from any internet-capable device") %>
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li class="flex flex-col justify-center items-center space-y-2">
|
||||
<b class="whitespace-nowrap">
|
||||
<%= gettext("backlinks:") %>
|
||||
</b>
|
||||
<p>
|
||||
<%= gettext("view referencing items from the referenced item") %>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr class="hr" />
|
||||
|
||||
<ul class="flex flex-col justify-center space-y-4">
|
||||
<h2 class="title text-primary-400 text-lg">
|
||||
<h2 class="text-lg title text-primary-400">
|
||||
<%= gettext("instance information") %>
|
||||
</h2>
|
||||
|
||||
@ -124,7 +133,7 @@
|
||||
<hr class="hr" />
|
||||
|
||||
<ul class="flex flex-col space-y-2">
|
||||
<h2 class="title text-primary-400 text-lg">
|
||||
<h2 class="text-lg title text-primary-400">
|
||||
<%= gettext("get involved") %>
|
||||
</h2>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule MemexWeb.NoteLive.Show do
|
||||
use MemexWeb, :live_view
|
||||
alias Memex.Notes
|
||||
alias Memex.{Contexts, Notes, Pipelines}
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
@ -22,8 +22,11 @@ defmodule MemexWeb.NoteLive.Show do
|
||||
socket =
|
||||
socket
|
||||
|> assign(
|
||||
context_backlinks: Contexts.backlink("[[#{note.slug}]]", current_user),
|
||||
note_backlinks: Notes.backlink("[#{note.slug}]", current_user),
|
||||
note: note,
|
||||
page_title: page_title(live_action, note)
|
||||
page_title: page_title(live_action, note),
|
||||
pipeline_backlinks: Pipelines.backlink("[[[#{note.slug}]]]", current_user)
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
|
@ -11,6 +11,34 @@
|
||||
|
||||
<.note_content note={@note} />
|
||||
|
||||
<div
|
||||
:if={@note_backlinks ++ @context_backlinks ++ @pipeline_backlinks != []}
|
||||
class="flex flex-wrap justify-end items-center self-end"
|
||||
>
|
||||
<p><%= gettext("Backlinked by:") %></p>
|
||||
<.link
|
||||
:for={backlink <- @note_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/note/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[%{slug}]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
<.link
|
||||
:for={backlink <- @context_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/context/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[[%{slug}]]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
<.link
|
||||
:for={backlink <- @pipeline_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/pipeline/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[[[%{slug}]]]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<p class="self-end">
|
||||
<%= gettext("Visibility: %{visibility}", visibility: @note.visibility) %>
|
||||
</p>
|
||||
|
@ -23,6 +23,7 @@ defmodule MemexWeb.PipelineLive.Show do
|
||||
socket
|
||||
|> assign(
|
||||
page_title: page_title(live_action, pipeline),
|
||||
pipeline_backlinks: Pipelines.backlink("[#{pipeline.slug}]", current_user),
|
||||
pipeline: pipeline,
|
||||
steps: pipeline |> Steps.list_steps(current_user)
|
||||
)
|
||||
|
@ -11,6 +11,17 @@
|
||||
|
||||
<.pipeline_content pipeline={@pipeline} />
|
||||
|
||||
<div :if={@pipeline_backlinks != []} class="flex flex-wrap justify-end items-center self-end">
|
||||
<p><%= gettext("Backlinked by:") %></p>
|
||||
<.link
|
||||
:for={backlink <- @pipeline_backlinks}
|
||||
class="m-1 hover:underline"
|
||||
patch={~p"/pipeline/#{backlink}"}
|
||||
>
|
||||
<%= gettext("[%{slug}]", slug: backlink.slug) %>
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<p class="self-end">
|
||||
<%= gettext("Visibility: %{visibility}", visibility: @pipeline.visibility) %>
|
||||
</p>
|
||||
|
Reference in New Issue
Block a user