diff --git a/assets/js/app.js b/assets/js/app.js
index 1c8f365..8b98397 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -29,7 +29,9 @@ import topbar from '../vendor/topbar'
import MaintainAttrs from './maintain_attrs'
import Alpine from 'alpinejs'
-const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute('content')
+const csrfTokenElement = document.querySelector("meta[name='csrf-token']")
+let csrfToken
+if (csrfTokenElement) { csrfToken = csrfTokenElement.getAttribute('content') }
const liveSocket = new LiveSocket('/live', Socket, {
dom: {
onBeforeElUpdated (from, to) {
diff --git a/lib/memex/contexts.ex b/lib/memex/contexts.ex
index f173d29..fdf1062 100644
--- a/lib/memex/contexts.ex
+++ b/lib/memex/contexts.ex
@@ -16,7 +16,7 @@ defmodule Memex.Contexts do
[%Context{}, ...]
iex> list_contexts("my context", %User{id: 123})
- [%Context{title: "my context"}, ...]
+ [%Context{slug: "my context"}, ...]
"""
@spec list_contexts(User.t()) :: [Context.t()]
@@ -24,7 +24,7 @@ defmodule Memex.Contexts do
def list_contexts(search \\ nil, user)
def list_contexts(search, %{id: user_id}) when search |> is_nil() or search == "" do
- Repo.all(from c in Context, where: c.user_id == ^user_id, order_by: c.title)
+ Repo.all(from c in Context, where: c.user_id == ^user_id, order_by: c.slug)
end
def list_contexts(search, %{id: user_id}) when search |> is_binary() do
@@ -57,7 +57,7 @@ defmodule Memex.Contexts do
[%Context{}, ...]
iex> list_public_contexts("my context")
- [%Context{title: "my context"}, ...]
+ [%Context{slug: "my context"}, ...]
"""
@spec list_public_contexts() :: [Context.t()]
@@ -65,7 +65,7 @@ defmodule Memex.Contexts do
def list_public_contexts(search \\ nil)
def list_public_contexts(search) when search |> is_nil() or search == "" do
- Repo.all(from c in Context, where: c.visibility == :public, order_by: c.title)
+ Repo.all(from c in Context, where: c.visibility == :public, order_by: c.slug)
end
def list_public_contexts(search) when search |> is_binary() do
@@ -120,6 +120,37 @@ defmodule Memex.Contexts do
)
end
+ @doc """
+ Gets a single context by a slug.
+
+ Raises `Ecto.NoResultsError` if the Context does not exist.
+
+ ## Examples
+
+ iex> get_context_by_slug("my-context", %User{id: 123})
+ %Context{}
+
+ iex> get_context_by_slug("my-context", %User{id: 123})
+ ** (Ecto.NoResultsError)
+
+ """
+ @spec get_context_by_slug(Context.slug(), User.t()) :: Context.t() | nil
+ def get_context_by_slug(slug, %{id: user_id}) do
+ Repo.one(
+ from c in Context,
+ where: c.slug == ^slug,
+ where: c.user_id == ^user_id or c.visibility in [:public, :unlisted]
+ )
+ end
+
+ def get_context_by_slug(slug, _invalid_user) do
+ Repo.one(
+ from c in Context,
+ where: c.slug == ^slug,
+ where: c.visibility in [:public, :unlisted]
+ )
+ end
+
@doc """
Creates a context.
diff --git a/lib/memex/contexts/context.ex b/lib/memex/contexts/context.ex
index d8e0801..0c895d2 100644
--- a/lib/memex/contexts/context.ex
+++ b/lib/memex/contexts/context.ex
@@ -3,19 +3,19 @@ defmodule Memex.Contexts.Context do
Represents a document that synthesizes multiple concepts as defined by notes
into a single consideration
"""
-
use Ecto.Schema
import Ecto.Changeset
+ import MemexWeb.Gettext
alias Ecto.{Changeset, UUID}
alias Memex.Accounts.User
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "contexts" do
+ field :slug, :string
field :content, :string
field :tags, {:array, :string}
field :tags_string, :string, virtual: true
- field :title, :string
field :visibility, Ecto.Enum, values: [:public, :private, :unlisted]
belongs_to :user, User
@@ -24,7 +24,7 @@ defmodule Memex.Contexts.Context do
end
@type t :: %__MODULE__{
- title: String.t(),
+ slug: slug(),
content: String.t(),
tags: [String.t()] | nil,
tags_string: String.t(),
@@ -35,24 +35,31 @@ defmodule Memex.Contexts.Context do
updated_at: NaiveDateTime.t()
}
@type id :: UUID.t()
+ @type slug :: String.t()
@type changeset :: Changeset.t(t())
@doc false
@spec create_changeset(attrs :: map(), User.t()) :: changeset()
def create_changeset(attrs, %User{id: user_id}) do
%__MODULE__{}
- |> cast(attrs, [:title, :content, :tags, :visibility])
+ |> cast(attrs, [:slug, :content, :tags, :visibility])
|> change(user_id: user_id)
|> cast_tags_string(attrs)
- |> validate_required([:title, :content, :user_id, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :content, :user_id, :visibility])
end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
def update_changeset(%{user_id: user_id} = note, attrs, %User{id: user_id}) do
note
- |> cast(attrs, [:title, :content, :tags, :visibility])
+ |> cast(attrs, [:slug, :content, :tags, :visibility])
|> cast_tags_string(attrs)
- |> validate_required([:title, :content, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :content, :visibility])
end
defp cast_tags_string(changeset, %{"tags_string" => tags_string})
diff --git a/lib/memex/notes.ex b/lib/memex/notes.ex
index ef04f80..34b2ea5 100644
--- a/lib/memex/notes.ex
+++ b/lib/memex/notes.ex
@@ -16,7 +16,7 @@ defmodule Memex.Notes do
[%Note{}, ...]
iex> list_notes("my note", %User{id: 123})
- [%Note{title: "my note"}, ...]
+ [%Note{slug: "my note"}, ...]
"""
@spec list_notes(User.t()) :: [Note.t()]
@@ -24,7 +24,7 @@ defmodule Memex.Notes do
def list_notes(search \\ nil, user)
def list_notes(search, %{id: user_id}) when search |> is_nil() or search == "" do
- Repo.all(from n in Note, where: n.user_id == ^user_id, order_by: n.title)
+ Repo.all(from n in Note, where: n.user_id == ^user_id, order_by: n.slug)
end
def list_notes(search, %{id: user_id}) when search |> is_binary() do
@@ -57,14 +57,14 @@ defmodule Memex.Notes do
[%Note{}, ...]
iex> list_public_notes("my note")
- [%Note{title: "my note"}, ...]
+ [%Note{slug: "my note"}, ...]
"""
@spec list_public_notes() :: [Note.t()]
@spec list_public_notes(search :: String.t() | nil) :: [Note.t()]
def list_public_notes(search \\ nil)
def list_public_notes(search) when search |> is_nil() or search == "" do
- Repo.all(from n in Note, where: n.visibility == :public, order_by: n.title)
+ Repo.all(from n in Note, where: n.visibility == :public, order_by: n.slug)
end
def list_public_notes(search) when search |> is_binary() do
@@ -119,6 +119,37 @@ defmodule Memex.Notes do
)
end
+ @doc """
+ Gets a single note by slug.
+
+ Raises `Ecto.NoResultsError` if the Note does not exist.
+
+ ## Examples
+
+ iex> get_note_by_slug("my-note", %User{id: 123})
+ %Note{}
+
+ iex> get_note_by_slug("my-note", %User{id: 123})
+ ** (Ecto.NoResultsError)
+
+ """
+ @spec get_note_by_slug(Note.slug(), User.t()) :: Note.t() | nil
+ def get_note_by_slug(slug, %{id: user_id}) do
+ Repo.one(
+ from n in Note,
+ where: n.slug == ^slug,
+ where: n.user_id == ^user_id or n.visibility in [:public, :unlisted]
+ )
+ end
+
+ def get_note_by_slug(slug, _invalid_user) do
+ Repo.one(
+ from n in Note,
+ where: n.slug == ^slug,
+ where: n.visibility in [:public, :unlisted]
+ )
+ end
+
@doc """
Creates a note.
@@ -189,7 +220,7 @@ defmodule Memex.Notes do
iex> change_note(note, %User{id: 123})
%Ecto.Changeset{data: %Note{}}
- iex> change_note(note, %{title: "new title"}, %User{id: 123})
+ iex> change_note(note, %{slug: "new slug"}, %User{id: 123})
%Ecto.Changeset{data: %Note{}}
"""
diff --git a/lib/memex/notes/note.ex b/lib/memex/notes/note.ex
index 641c8a2..e6ec37c 100644
--- a/lib/memex/notes/note.ex
+++ b/lib/memex/notes/note.ex
@@ -4,13 +4,14 @@ defmodule Memex.Notes.Note do
"""
use Ecto.Schema
import Ecto.Changeset
+ import MemexWeb.Gettext
alias Ecto.{Changeset, UUID}
alias Memex.Accounts.User
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "notes" do
- field :title, :string
+ field :slug, :string
field :content, :string
field :tags, {:array, :string}
field :tags_string, :string, virtual: true
@@ -22,7 +23,7 @@ defmodule Memex.Notes.Note do
end
@type t :: %__MODULE__{
- title: String.t(),
+ slug: slug(),
content: String.t(),
tags: [String.t()] | nil,
tags_string: String.t(),
@@ -33,24 +34,31 @@ defmodule Memex.Notes.Note do
updated_at: NaiveDateTime.t()
}
@type id :: UUID.t()
+ @type slug :: String.t()
@type changeset :: Changeset.t(t())
@doc false
@spec create_changeset(attrs :: map(), User.t()) :: changeset()
def create_changeset(attrs, %User{id: user_id}) do
%__MODULE__{}
- |> cast(attrs, [:title, :content, :tags, :visibility])
+ |> cast(attrs, [:slug, :content, :tags, :visibility])
|> change(user_id: user_id)
|> cast_tags_string(attrs)
- |> validate_required([:title, :content, :user_id, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :content, :user_id, :visibility])
end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
def update_changeset(%{user_id: user_id} = note, attrs, %User{id: user_id}) do
note
- |> cast(attrs, [:title, :content, :tags, :visibility])
+ |> cast(attrs, [:slug, :content, :tags, :visibility])
|> cast_tags_string(attrs)
- |> validate_required([:title, :content, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :content, :visibility])
end
defp cast_tags_string(changeset, %{"tags_string" => tags_string})
diff --git a/lib/memex/pipelines.ex b/lib/memex/pipelines.ex
index 995f3ba..09384d7 100644
--- a/lib/memex/pipelines.ex
+++ b/lib/memex/pipelines.ex
@@ -16,7 +16,7 @@ defmodule Memex.Pipelines do
[%Pipeline{}, ...]
iex> list_pipelines("my pipeline", %User{id: 123})
- [%Pipeline{title: "my pipeline"}, ...]
+ [%Pipeline{slug: "my pipeline"}, ...]
"""
@spec list_pipelines(User.t()) :: [Pipeline.t()]
@@ -24,7 +24,7 @@ defmodule Memex.Pipelines do
def list_pipelines(search \\ nil, user)
def list_pipelines(search, %{id: user_id}) when search |> is_nil() or search == "" do
- Repo.all(from p in Pipeline, where: p.user_id == ^user_id, order_by: p.title)
+ Repo.all(from p in Pipeline, where: p.user_id == ^user_id, order_by: p.slug)
end
def list_pipelines(search, %{id: user_id}) when search |> is_binary() do
@@ -57,14 +57,14 @@ defmodule Memex.Pipelines do
[%Pipeline{}, ...]
iex> list_public_pipelines("my pipeline")
- [%Pipeline{title: "my pipeline"}, ...]
+ [%Pipeline{slug: "my pipeline"}, ...]
"""
@spec list_public_pipelines() :: [Pipeline.t()]
@spec list_public_pipelines(search :: String.t() | nil) :: [Pipeline.t()]
def list_public_pipelines(search \\ nil)
def list_public_pipelines(search) when search |> is_nil() or search == "" do
- Repo.all(from p in Pipeline, where: p.visibility == :public, order_by: p.title)
+ Repo.all(from p in Pipeline, where: p.visibility == :public, order_by: p.slug)
end
def list_public_pipelines(search) when search |> is_binary() do
@@ -119,6 +119,37 @@ defmodule Memex.Pipelines do
)
end
+ @doc """
+ Gets a single pipeline by it's slug.
+
+ Raises `Ecto.NoResultsError` if the Pipeline does not exist.
+
+ ## Examples
+
+ iex> get_pipeline_by_slug("my-pipeline", %User{id: 123})
+ %Pipeline{}
+
+ iex> get_pipeline_by_slug("my-pipeline", %User{id: 123})
+ ** (Ecto.NoResultsError)
+
+ """
+ @spec get_pipeline_by_slug(Pipeline.slug(), User.t()) :: Pipeline.t() | nil
+ def get_pipeline_by_slug(slug, %{id: user_id}) do
+ Repo.one(
+ from p in Pipeline,
+ where: p.slug == ^slug,
+ where: p.user_id == ^user_id or p.visibility in [:public, :unlisted]
+ )
+ end
+
+ def get_pipeline_by_slug(slug, _invalid_user) do
+ Repo.one(
+ from p in Pipeline,
+ where: p.slug == ^slug,
+ where: p.visibility in [:public, :unlisted]
+ )
+ end
+
@doc """
Creates a pipeline.
@@ -191,7 +222,7 @@ defmodule Memex.Pipelines do
iex> change_pipeline(pipeline, %User{id: 123})
%Ecto.Changeset{data: %Pipeline{}}
- iex> change_pipeline(pipeline, %{title: "new title"}, %User{id: 123})
+ iex> change_pipeline(pipeline, %{slug: "new slug"}, %User{id: 123})
%Ecto.Changeset{data: %Pipeline{}}
"""
diff --git a/lib/memex/pipelines/pipeline.ex b/lib/memex/pipelines/pipeline.ex
index 6ef0505..17b0d71 100644
--- a/lib/memex/pipelines/pipeline.ex
+++ b/lib/memex/pipelines/pipeline.ex
@@ -4,13 +4,14 @@ defmodule Memex.Pipelines.Pipeline do
"""
use Ecto.Schema
import Ecto.Changeset
+ import MemexWeb.Gettext
alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Pipelines.Step}
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "pipelines" do
- field :title, :string
+ field :slug, :string
field :description, :string
field :tags, {:array, :string}
field :tags_string, :string, virtual: true
@@ -24,7 +25,7 @@ defmodule Memex.Pipelines.Pipeline do
end
@type t :: %__MODULE__{
- title: String.t(),
+ slug: slug(),
description: String.t(),
tags: [String.t()] | nil,
tags_string: String.t(),
@@ -35,24 +36,31 @@ defmodule Memex.Pipelines.Pipeline do
updated_at: NaiveDateTime.t()
}
@type id :: UUID.t()
+ @type slug :: String.t()
@type changeset :: Changeset.t(t())
@doc false
@spec create_changeset(attrs :: map(), User.t()) :: changeset()
def create_changeset(attrs, %User{id: user_id}) do
%__MODULE__{}
- |> cast(attrs, [:title, :description, :tags, :visibility])
+ |> cast(attrs, [:slug, :description, :tags, :visibility])
|> change(user_id: user_id)
|> cast_tags_string(attrs)
- |> validate_required([:title, :user_id, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :user_id, :visibility])
end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
def update_changeset(%{user_id: user_id} = pipeline, attrs, %User{id: user_id}) do
pipeline
- |> cast(attrs, [:title, :description, :tags, :visibility])
+ |> cast(attrs, [:slug, :description, :tags, :visibility])
|> cast_tags_string(attrs)
- |> validate_required([:title, :visibility])
+ |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
+ message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
+ )
+ |> validate_required([:slug, :visibility])
end
defp cast_tags_string(changeset, %{"tags_string" => tags_string})
diff --git a/lib/memex_web/components/contexts_table_component.ex b/lib/memex_web/components/contexts_table_component.ex
index 30b6ae3..1443366 100644
--- a/lib/memex_web/components/contexts_table_component.ex
+++ b/lib/memex_web/components/contexts_table_component.ex
@@ -44,7 +44,7 @@ defmodule MemexWeb.Components.ContextsTableComponent do
end
columns = [
- %{label: gettext("title"), key: :title},
+ %{label: gettext("slug"), key: :slug},
%{label: gettext("content"), key: :content},
%{label: gettext("tags"), key: :tags},
%{label: gettext("visibility"), key: :visibility}
@@ -89,20 +89,20 @@ defmodule MemexWeb.Components.ContextsTableComponent do
@spec get_value_for_key(atom(), Context.t(), additional_data :: map()) ::
any() | {any(), Rendered.t()}
- defp get_value_for_key(:title, %{id: id, title: title}, _additional_data) do
- assigns = %{id: id, title: title}
+ defp get_value_for_key(:slug, %{slug: slug}, _additional_data) do
+ assigns = %{slug: slug}
- title_block = ~H"""
+ slug_block = ~H"""
<.link
- navigate={Routes.context_show_path(Endpoint, :show, @id)}
+ navigate={Routes.context_show_path(Endpoint, :show, @slug)}
class="link"
- data-qa={"context-show-#{@id}"}
+ data-qa={"context-show-#{@slug}"}
>
- <%= @title %>
+ <%= @slug %>
"""
- {title, title_block}
+ {slug, slug_block}
end
defp get_value_for_key(:content, %{content: content}, _additional_data) do
diff --git a/lib/memex_web/components/notes_table_component.ex b/lib/memex_web/components/notes_table_component.ex
index 21a595d..081f981 100644
--- a/lib/memex_web/components/notes_table_component.ex
+++ b/lib/memex_web/components/notes_table_component.ex
@@ -44,7 +44,7 @@ defmodule MemexWeb.Components.NotesTableComponent do
end
columns = [
- %{label: gettext("title"), key: :title},
+ %{label: gettext("slug"), key: :slug},
%{label: gettext("content"), key: :content},
%{label: gettext("tags"), key: :tags},
%{label: gettext("visibility"), key: :visibility}
@@ -89,20 +89,20 @@ defmodule MemexWeb.Components.NotesTableComponent do
@spec get_value_for_key(atom(), Note.t(), additional_data :: map()) ::
any() | {any(), Rendered.t()}
- defp get_value_for_key(:title, %{id: id, title: title}, _additional_data) do
- assigns = %{id: id, title: title}
+ defp get_value_for_key(:slug, %{slug: slug}, _additional_data) do
+ assigns = %{slug: slug}
- title_block = ~H"""
+ slug_block = ~H"""
<.link
- navigate={Routes.note_show_path(Endpoint, :show, @id)}
+ navigate={Routes.note_show_path(Endpoint, :show, @slug)}
class="link"
- data-qa={"note-show-#{@id}"}
+ data-qa={"note-show-#{@slug}"}
>
- <%= @title %>
+ <%= @slug %>
"""
- {title, title_block}
+ {slug, slug_block}
end
defp get_value_for_key(:content, %{content: content}, _additional_data) do
diff --git a/lib/memex_web/components/pipelines_table_component.ex b/lib/memex_web/components/pipelines_table_component.ex
index 9f49a6d..f3a9afd 100644
--- a/lib/memex_web/components/pipelines_table_component.ex
+++ b/lib/memex_web/components/pipelines_table_component.ex
@@ -44,7 +44,7 @@ defmodule MemexWeb.Components.PipelinesTableComponent do
end
columns = [
- %{label: gettext("title"), key: :title},
+ %{label: gettext("slug"), key: :slug},
%{label: gettext("description"), key: :description},
%{label: gettext("tags"), key: :tags},
%{label: gettext("visibility"), key: :visibility}
@@ -89,20 +89,20 @@ defmodule MemexWeb.Components.PipelinesTableComponent do
@spec get_value_for_key(atom(), Pipeline.t(), additional_data :: map()) ::
any() | {any(), Rendered.t()}
- defp get_value_for_key(:title, %{id: id, title: title}, _additional_data) do
- assigns = %{id: id, title: title}
+ defp get_value_for_key(:slug, %{slug: slug}, _additional_data) do
+ assigns = %{slug: slug}
- title_block = ~H"""
+ slug_block = ~H"""
<.link
- navigate={Routes.pipeline_show_path(Endpoint, :show, @id)}
+ navigate={Routes.pipeline_show_path(Endpoint, :show, @slug)}
class="link"
- data-qa={"pipeline-show-#{@id}"}
+ data-qa={"pipeline-show-#{@slug}"}
>
- <%= @title %>
+ <%= @slug %>
"""
- {title, title_block}
+ {slug, slug_block}
end
defp get_value_for_key(:description, %{description: description}, _additional_data) do
diff --git a/lib/memex_web/live/context_live/form_component.ex b/lib/memex_web/live/context_live/form_component.ex
index 9dec24a..9e188c1 100644
--- a/lib/memex_web/live/context_live/form_component.ex
+++ b/lib/memex_web/live/context_live/form_component.ex
@@ -38,10 +38,10 @@ defmodule MemexWeb.ContextLive.FormComponent do
context_params
) do
case Contexts.update_context(context, context_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} saved", title: title))
+ |> put_flash(:info, gettext("%{slug} saved", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
@@ -55,10 +55,10 @@ defmodule MemexWeb.ContextLive.FormComponent do
context_params
) do
case Contexts.create_context(context_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} created", title: title))
+ |> put_flash(:info, gettext("%{slug} created", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
diff --git a/lib/memex_web/live/context_live/form_component.html.heex b/lib/memex_web/live/context_live/form_component.html.heex
index e2ba8e9..65c209a 100644
--- a/lib/memex_web/live/context_live/form_component.html.heex
+++ b/lib/memex_web/live/context_live/form_component.html.heex
@@ -9,11 +9,11 @@
phx-debounce="300"
class="flex flex-col justify-start items-stretch space-y-4"
>
- <%= text_input(f, :title,
+ <%= text_input(f, :slug,
class: "input input-primary",
- placeholder: gettext("title")
+ placeholder: gettext("slug")
) %>
- <%= error_tag(f, :title) %>
+ <%= error_tag(f, :slug) %>
<%= textarea(f, :content,
id: "context-form-content",
diff --git a/lib/memex_web/live/context_live/index.ex b/lib/memex_web/live/context_live/index.ex
index e9efdaa..db991d6 100644
--- a/lib/memex_web/live/context_live/index.ex
+++ b/lib/memex_web/live/context_live/index.ex
@@ -16,11 +16,11 @@ defmodule MemexWeb.ContextLive.Index do
{:noreply, apply_action(socket, live_action, params)}
end
- defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do
- %{title: title} = context = Contexts.get_context!(id, current_user)
+ defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"slug" => slug}) do
+ %{slug: slug} = context = Contexts.get_context_by_slug(slug, current_user)
socket
- |> assign(page_title: gettext("edit %{title}", title: title))
+ |> assign(page_title: gettext("edit %{slug}", slug: slug))
|> assign(context: context)
end
@@ -49,12 +49,12 @@ defmodule MemexWeb.ContextLive.Index do
@impl true
def handle_event("delete", %{"id" => id}, %{assigns: %{current_user: current_user}} = socket) do
context = Contexts.get_context!(id, current_user)
- {:ok, %{title: title}} = Contexts.delete_context(context, current_user)
+ {:ok, %{slug: slug}} = Contexts.delete_context(context, current_user)
socket =
socket
|> assign(contexts: Contexts.list_contexts(current_user))
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
{:noreply, socket}
end
diff --git a/lib/memex_web/live/context_live/index.html.heex b/lib/memex_web/live/context_live/index.html.heex
index 4e8bdbb..dd0bc8b 100644
--- a/lib/memex_web/live/context_live/index.html.heex
+++ b/lib/memex_web/live/context_live/index.html.heex
@@ -32,7 +32,7 @@
<:actions :let={context}>
<%= if is_owner?(context, @current_user) do %>
<.link
- patch={Routes.context_index_path(@socket, :edit, context)}
+ patch={Routes.context_index_path(@socket, :edit, context.slug)}
data-qa={"context-edit-#{context.id}"}
>
<%= dgettext("actions", "edit") %>
diff --git a/lib/memex_web/live/context_live/show.ex b/lib/memex_web/live/context_live/show.ex
index 66f6940..f478022 100644
--- a/lib/memex_web/live/context_live/show.ex
+++ b/lib/memex_web/live/context_live/show.ex
@@ -10,11 +10,15 @@ defmodule MemexWeb.ContextLive.Show do
@impl true
def handle_params(
- %{"id" => id},
+ %{"slug" => slug},
_,
%{assigns: %{live_action: live_action, current_user: current_user}} = socket
) do
- context = Contexts.get_context!(id, current_user)
+ context =
+ case Contexts.get_context_by_slug(slug, current_user) do
+ nil -> raise MemexWeb.NotFoundError, gettext("%{slug} could not be found", slug: slug)
+ context -> context
+ end
socket =
socket
@@ -30,18 +34,18 @@ defmodule MemexWeb.ContextLive.Show do
_params,
%{assigns: %{context: context, current_user: current_user}} = socket
) do
- {:ok, %{title: title}} = Contexts.delete_context(context, current_user)
+ {:ok, %{slug: slug}} = Contexts.delete_context(context, current_user)
socket =
socket
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
|> push_navigate(to: Routes.context_index_path(Endpoint, :index))
{:noreply, socket}
end
- defp page_title(:show, %{title: title}), do: title
- defp page_title(:edit, %{title: title}), do: gettext("edit %{title}", title: title)
+ defp page_title(:show, %{slug: slug}), do: slug
+ defp page_title(:edit, %{slug: slug}), do: gettext("edit %{slug}", slug: slug)
@spec is_owner_or_admin?(Context.t(), User.t()) :: boolean()
defp is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
diff --git a/lib/memex_web/live/context_live/show.html.heex b/lib/memex_web/live/context_live/show.html.heex
index 716cd07..ac7000e 100644
--- a/lib/memex_web/live/context_live/show.html.heex
+++ b/lib/memex_web/live/context_live/show.html.heex
@@ -1,6 +1,6 @@
- <%= @context.title %>
+ <%= @context.slug %>
<%= if @context.tags, do: @context.tags |> Enum.join(", ") %>
@@ -23,7 +23,10 @@
<%= dgettext("actions", "back") %>
<%= if is_owner?(@context, @current_user) do %>
- <.link class="btn btn-primary" patch={Routes.context_show_path(@socket, :edit, @context)}>
+ <.link
+ class="btn btn-primary"
+ patch={Routes.context_show_path(@socket, :edit, @context.slug)}
+ >
<%= dgettext("actions", "edit") %>
<% end %>
@@ -42,7 +45,7 @@
<%= if @live_action in [:edit] do %>
- <.modal return_to={Routes.context_show_path(@socket, :show, @context)}>
+ <.modal return_to={Routes.context_show_path(@socket, :show, @context.slug)}>
<.live_component
module={MemexWeb.ContextLive.FormComponent}
id={@context.id}
@@ -50,7 +53,7 @@
title={@page_title}
action={@live_action}
context={@context}
- return_to={Routes.context_show_path(@socket, :show, @context)}
+ return_to={Routes.context_show_path(@socket, :show, @context.slug)}
/>
<% end %>
diff --git a/lib/memex_web/live/note_live/form_component.ex b/lib/memex_web/live/note_live/form_component.ex
index 01833f5..1153927 100644
--- a/lib/memex_web/live/note_live/form_component.ex
+++ b/lib/memex_web/live/note_live/form_component.ex
@@ -37,10 +37,10 @@ defmodule MemexWeb.NoteLive.FormComponent do
note_params
) do
case Notes.update_note(note, note_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} saved", title: title))
+ |> put_flash(:info, gettext("%{slug} saved", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
@@ -54,10 +54,10 @@ defmodule MemexWeb.NoteLive.FormComponent do
note_params
) do
case Notes.create_note(note_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} created", title: title))
+ |> put_flash(:info, gettext("%{slug} created", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
diff --git a/lib/memex_web/live/note_live/form_component.html.heex b/lib/memex_web/live/note_live/form_component.html.heex
index 75b588d..e2cc50d 100644
--- a/lib/memex_web/live/note_live/form_component.html.heex
+++ b/lib/memex_web/live/note_live/form_component.html.heex
@@ -9,11 +9,11 @@
phx-debounce="300"
class="flex flex-col justify-start items-stretch space-y-4"
>
- <%= text_input(f, :title,
+ <%= text_input(f, :slug,
class: "input input-primary",
- placeholder: gettext("title")
+ placeholder: gettext("slug")
) %>
- <%= error_tag(f, :title) %>
+ <%= error_tag(f, :slug) %>
<%= textarea(f, :content,
id: "note-form-content",
diff --git a/lib/memex_web/live/note_live/index.ex b/lib/memex_web/live/note_live/index.ex
index 18f328c..88e9511 100644
--- a/lib/memex_web/live/note_live/index.ex
+++ b/lib/memex_web/live/note_live/index.ex
@@ -16,11 +16,11 @@ defmodule MemexWeb.NoteLive.Index do
{:noreply, apply_action(socket, live_action, params)}
end
- defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do
- %{title: title} = note = Notes.get_note!(id, current_user)
+ defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"slug" => slug}) do
+ %{slug: slug} = note = Notes.get_note_by_slug(slug, current_user)
socket
- |> assign(page_title: gettext("edit %{title}", title: title))
+ |> assign(page_title: gettext("edit %{slug}", slug: slug))
|> assign(note: note)
end
@@ -49,12 +49,12 @@ defmodule MemexWeb.NoteLive.Index do
@impl true
def handle_event("delete", %{"id" => id}, %{assigns: %{current_user: current_user}} = socket) do
note = Notes.get_note!(id, current_user)
- {:ok, %{title: title}} = Notes.delete_note(note, current_user)
+ {:ok, %{slug: slug}} = Notes.delete_note(note, current_user)
socket =
socket
|> assign(notes: Notes.list_notes(current_user))
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
{:noreply, socket}
end
diff --git a/lib/memex_web/live/note_live/index.html.heex b/lib/memex_web/live/note_live/index.html.heex
index 5be724d..f2bf01d 100644
--- a/lib/memex_web/live/note_live/index.html.heex
+++ b/lib/memex_web/live/note_live/index.html.heex
@@ -32,7 +32,7 @@
<:actions :let={note}>
<%= if is_owner?(note, @current_user) do %>
<.link
- patch={Routes.note_index_path(@socket, :edit, note)}
+ patch={Routes.note_index_path(@socket, :edit, note.slug)}
data-qa={"note-edit-#{note.id}"}
>
<%= dgettext("actions", "edit") %>
diff --git a/lib/memex_web/live/note_live/show.ex b/lib/memex_web/live/note_live/show.ex
index de20ce7..65f63b4 100644
--- a/lib/memex_web/live/note_live/show.ex
+++ b/lib/memex_web/live/note_live/show.ex
@@ -10,11 +10,15 @@ defmodule MemexWeb.NoteLive.Show do
@impl true
def handle_params(
- %{"id" => id},
+ %{"slug" => slug},
_,
%{assigns: %{live_action: live_action, current_user: current_user}} = socket
) do
- note = Notes.get_note!(id, current_user)
+ note =
+ case Notes.get_note_by_slug(slug, current_user) do
+ nil -> raise MemexWeb.NotFoundError, gettext("%{slug} could not be found", slug: slug)
+ note -> note
+ end
socket =
socket
@@ -30,18 +34,18 @@ defmodule MemexWeb.NoteLive.Show do
_params,
%{assigns: %{note: note, current_user: current_user}} = socket
) do
- {:ok, %{title: title}} = Notes.delete_note(note, current_user)
+ {:ok, %{slug: slug}} = Notes.delete_note(note, current_user)
socket =
socket
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
|> push_navigate(to: Routes.note_index_path(Endpoint, :index))
{:noreply, socket}
end
- defp page_title(:show, %{title: title}), do: title
- defp page_title(:edit, %{title: title}), do: gettext("edit %{title}", title: title)
+ defp page_title(:show, %{slug: slug}), do: slug
+ defp page_title(:edit, %{slug: slug}), do: gettext("edit %{slug}", slug: slug)
@spec is_owner_or_admin?(Note.t(), User.t()) :: boolean()
defp is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
diff --git a/lib/memex_web/live/note_live/show.html.heex b/lib/memex_web/live/note_live/show.html.heex
index bca7c55..73026b0 100644
--- a/lib/memex_web/live/note_live/show.html.heex
+++ b/lib/memex_web/live/note_live/show.html.heex
@@ -1,6 +1,6 @@
- <%= @note.title %>
+ <%= @note.slug %>
<%= if @note.tags, do: @note.tags |> Enum.join(", ") %>
@@ -23,7 +23,7 @@
<%= dgettext("actions", "back") %>
<%= if is_owner?(@note, @current_user) do %>
- <.link class="btn btn-primary" patch={Routes.note_show_path(@socket, :edit, @note)}>
+ <.link class="btn btn-primary" patch={Routes.note_show_path(@socket, :edit, @note.slug)}>
<%= dgettext("actions", "edit") %>
<% end %>
@@ -42,7 +42,7 @@
<%= if @live_action in [:edit] do %>
- <.modal return_to={Routes.note_show_path(@socket, :show, @note)}>
+ <.modal return_to={Routes.note_show_path(@socket, :show, @note.slug)}>
<.live_component
module={MemexWeb.NoteLive.FormComponent}
id={@note.id}
@@ -50,7 +50,7 @@
title={@page_title}
action={@live_action}
note={@note}
- return_to={Routes.note_show_path(@socket, :show, @note)}
+ return_to={Routes.note_show_path(@socket, :show, @note.slug)}
/>
<% end %>
diff --git a/lib/memex_web/live/pipeline_live/form_component.ex b/lib/memex_web/live/pipeline_live/form_component.ex
index b55f00d..0479b91 100644
--- a/lib/memex_web/live/pipeline_live/form_component.ex
+++ b/lib/memex_web/live/pipeline_live/form_component.ex
@@ -42,10 +42,10 @@ defmodule MemexWeb.PipelineLive.FormComponent do
pipeline_params
) do
case Pipelines.update_pipeline(pipeline, pipeline_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} saved", title: title))
+ |> put_flash(:info, gettext("%{slug} saved", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
@@ -59,10 +59,10 @@ defmodule MemexWeb.PipelineLive.FormComponent do
pipeline_params
) do
case Pipelines.create_pipeline(pipeline_params, current_user) do
- {:ok, %{title: title}} ->
+ {:ok, %{slug: slug}} ->
{:noreply,
socket
- |> put_flash(:info, gettext("%{title} created", title: title))
+ |> put_flash(:info, gettext("%{slug} created", slug: slug))
|> push_navigate(to: return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
diff --git a/lib/memex_web/live/pipeline_live/form_component.html.heex b/lib/memex_web/live/pipeline_live/form_component.html.heex
index ad1e510..b4b3a65 100644
--- a/lib/memex_web/live/pipeline_live/form_component.html.heex
+++ b/lib/memex_web/live/pipeline_live/form_component.html.heex
@@ -9,11 +9,11 @@
phx-debounce="300"
class="flex flex-col justify-start items-stretch space-y-4"
>
- <%= text_input(f, :title,
+ <%= text_input(f, :slug,
class: "input input-primary",
- placeholder: gettext("title")
+ placeholder: gettext("slug")
) %>
- <%= error_tag(f, :title) %>
+ <%= error_tag(f, :slug) %>
<%= textarea(f, :description,
id: "pipeline-form-description",
diff --git a/lib/memex_web/live/pipeline_live/index.ex b/lib/memex_web/live/pipeline_live/index.ex
index c354a08..fb19084 100644
--- a/lib/memex_web/live/pipeline_live/index.ex
+++ b/lib/memex_web/live/pipeline_live/index.ex
@@ -16,11 +16,11 @@ defmodule MemexWeb.PipelineLive.Index do
{:noreply, apply_action(socket, live_action, params)}
end
- defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do
- %{title: title} = pipeline = Pipelines.get_pipeline!(id, current_user)
+ defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"slug" => slug}) do
+ %{slug: slug} = pipeline = Pipelines.get_pipeline_by_slug(slug, current_user)
socket
- |> assign(page_title: gettext("edit %{title}", title: title))
+ |> assign(page_title: gettext("edit %{slug}", slug: slug))
|> assign(pipeline: pipeline)
end
@@ -49,12 +49,12 @@ defmodule MemexWeb.PipelineLive.Index do
@impl true
def handle_event("delete", %{"id" => id}, %{assigns: %{current_user: current_user}} = socket) do
pipeline = Pipelines.get_pipeline!(id, current_user)
- {:ok, %{title: title}} = Pipelines.delete_pipeline(pipeline, current_user)
+ {:ok, %{slug: slug}} = Pipelines.delete_pipeline(pipeline, current_user)
socket =
socket
|> assign(pipelines: Pipelines.list_pipelines(current_user))
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
{:noreply, socket}
end
diff --git a/lib/memex_web/live/pipeline_live/index.html.heex b/lib/memex_web/live/pipeline_live/index.html.heex
index 58a774f..6ef21f3 100644
--- a/lib/memex_web/live/pipeline_live/index.html.heex
+++ b/lib/memex_web/live/pipeline_live/index.html.heex
@@ -32,7 +32,7 @@
<:actions :let={pipeline}>
<%= if is_owner?(pipeline, @current_user) do %>
<.link
- patch={Routes.pipeline_index_path(@socket, :edit, pipeline)}
+ patch={Routes.pipeline_index_path(@socket, :edit, pipeline.slug)}
data-qa={"pipeline-edit-#{pipeline.id}"}
>
<%= dgettext("actions", "edit") %>
diff --git a/lib/memex_web/live/pipeline_live/show.ex b/lib/memex_web/live/pipeline_live/show.ex
index 7e76ae1..bc2a609 100644
--- a/lib/memex_web/live/pipeline_live/show.ex
+++ b/lib/memex_web/live/pipeline_live/show.ex
@@ -10,11 +10,15 @@ defmodule MemexWeb.PipelineLive.Show do
@impl true
def handle_params(
- %{"id" => id},
+ %{"slug" => slug},
_,
%{assigns: %{live_action: live_action, current_user: current_user}} = socket
) do
- pipeline = Pipelines.get_pipeline!(id, current_user)
+ pipeline =
+ case Pipelines.get_pipeline_by_slug(slug, current_user) do
+ nil -> raise MemexWeb.NotFoundError, gettext("%{slug} could not be found", slug: slug)
+ pipeline -> pipeline
+ end
socket =
socket
@@ -30,18 +34,18 @@ defmodule MemexWeb.PipelineLive.Show do
_params,
%{assigns: %{pipeline: pipeline, current_user: current_user}} = socket
) do
- {:ok, %{title: title}} = Pipelines.delete_pipeline(pipeline, current_user)
+ {:ok, %{slug: slug}} = Pipelines.delete_pipeline(pipeline, current_user)
socket =
socket
- |> put_flash(:info, gettext("%{title} deleted", title: title))
+ |> put_flash(:info, gettext("%{slug} deleted", slug: slug))
|> push_navigate(to: Routes.pipeline_index_path(Endpoint, :index))
{:noreply, socket}
end
- defp page_title(:show, %{title: title}), do: title
- defp page_title(:edit, %{title: title}), do: gettext("edit %{title}", title: title)
+ defp page_title(:show, %{slug: slug}), do: slug
+ defp page_title(:edit, %{slug: slug}), do: gettext("edit %{slug}", slug: slug)
@spec is_owner_or_admin?(Pipeline.t(), User.t()) :: boolean()
defp is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
diff --git a/lib/memex_web/live/pipeline_live/show.html.heex b/lib/memex_web/live/pipeline_live/show.html.heex
index 3c9b041..102e4b4 100644
--- a/lib/memex_web/live/pipeline_live/show.html.heex
+++ b/lib/memex_web/live/pipeline_live/show.html.heex
@@ -1,6 +1,6 @@
- <%= @pipeline.title %>
+ <%= @pipeline.slug %>
<%= if @pipeline.tags, do: @pipeline.tags |> Enum.join(", ") %>
@@ -23,7 +23,10 @@
<%= dgettext("actions", "back") %>
<%= if is_owner?(@pipeline, @current_user) do %>
- <.link class="btn btn-primary" patch={Routes.pipeline_show_path(@socket, :edit, @pipeline)}>
+ <.link
+ class="btn btn-primary"
+ patch={Routes.pipeline_show_path(@socket, :edit, @pipeline.slug)}
+ >
<%= dgettext("actions", "edit") %>
<% end %>
@@ -42,7 +45,7 @@
<%= if @live_action in [:edit] do %>
- <.modal return_to={Routes.pipeline_show_path(@socket, :show, @pipeline)}>
+ <.modal return_to={Routes.pipeline_show_path(@socket, :show, @pipeline.slug)}>
<.live_component
module={MemexWeb.PipelineLive.FormComponent}
id={@pipeline.id}
@@ -50,7 +53,7 @@
title={@page_title}
action={@live_action}
pipeline={@pipeline}
- return_to={Routes.pipeline_show_path(@socket, :show, @pipeline)}
+ return_to={Routes.pipeline_show_path(@socket, :show, @pipeline.slug)}
/>
<% end %>
diff --git a/lib/memex_web/not_found_error.ex b/lib/memex_web/not_found_error.ex
new file mode 100644
index 0000000..0dd662b
--- /dev/null
+++ b/lib/memex_web/not_found_error.ex
@@ -0,0 +1,3 @@
+defmodule MemexWeb.NotFoundError do
+ defexception [:message, plug_status: 404]
+end
diff --git a/lib/memex_web/router.ex b/lib/memex_web/router.ex
index 092d626..2c070fc 100644
--- a/lib/memex_web/router.ex
+++ b/lib/memex_web/router.ex
@@ -58,16 +58,16 @@ defmodule MemexWeb.Router do
pipe_through [:browser, :require_authenticated_user]
live "/notes/new", NoteLive.Index, :new
- live "/notes/:id/edit", NoteLive.Index, :edit
- live "/note/:id/edit", NoteLive.Show, :edit
+ live "/notes/:slug/edit", NoteLive.Index, :edit
+ live "/note/:slug/edit", NoteLive.Show, :edit
live "/contexts/new", ContextLive.Index, :new
- live "/contexts/:id/edit", ContextLive.Index, :edit
- live "/context/:id/edit", ContextLive.Show, :edit
+ live "/contexts/:slug/edit", ContextLive.Index, :edit
+ live "/context/:slug/edit", ContextLive.Show, :edit
live "/pipelines/new", PipelineLive.Index, :new
- live "/pipelines/:id/edit", PipelineLive.Index, :edit
- live "/pipelines/:id/show/edit", PipelineLive.Show, :edit
+ live "/pipelines/:slug/edit", PipelineLive.Index, :edit
+ live "/pipeline/:slug/edit", PipelineLive.Show, :edit
get "/users/settings", UserSettingsController, :edit
put "/users/settings", UserSettingsController, :update
@@ -80,15 +80,15 @@ defmodule MemexWeb.Router do
live "/notes", NoteLive.Index, :index
live "/notes/:search", NoteLive.Index, :search
- live "/note/:id", NoteLive.Show, :show
+ live "/note/:slug", NoteLive.Show, :show
live "/contexts", ContextLive.Index, :index
live "/contexts/:search", ContextLive.Index, :search
- live "/context/:id", ContextLive.Show, :show
+ live "/context/:slug", ContextLive.Show, :show
live "/pipelines", PipelineLive.Index, :index
live "/pipelines/:search", PipelineLive.Index, :search
- live "/pipeline/:id", PipelineLive.Show, :show
+ live "/pipeline/:slug", PipelineLive.Show, :show
end
end
diff --git a/lib/memex_web/templates/error/error.html.heex b/lib/memex_web/templates/error/error.html.heex
index a9a3924..755e0d9 100644
--- a/lib/memex_web/templates/error/error.html.heex
+++ b/lib/memex_web/templates/error/error.html.heex
@@ -11,7 +11,7 @@
-
+
<.topbar current_user={assigns[:current_user]}>
@@ -25,7 +25,7 @@
- <%= dgettext("errors", "Go back home") %>
+ <%= dgettext("errors", "go back home") %>
diff --git a/lib/memex_web/views/error_view.ex b/lib/memex_web/views/error_view.ex
index 677eccd..7560511 100644
--- a/lib/memex_web/views/error_view.ex
+++ b/lib/memex_web/views/error_view.ex
@@ -6,9 +6,9 @@ defmodule MemexWeb.ErrorView do
def template_not_found(error_path, _assigns) do
error_string =
case error_path do
- "404.html" -> dgettext("errors", "Not found")
- "401.html" -> dgettext("errors", "Unauthorized")
- _ -> dgettext("errors", "Internal Server Error")
+ "404.html" -> dgettext("errors", "not found")
+ "401.html" -> dgettext("errors", "unauthorized")
+ _ -> dgettext("errors", "internal server error")
end
render("error.html", %{error_string: error_string})
diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot
index e45d3af..ac59067 100644
--- a/priv/gettext/actions.pot
+++ b/priv/gettext/actions.pot
@@ -68,11 +68,11 @@ msgid "create invite"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:49
-#: lib/memex_web/live/context_live/show.html.heex:38
+#: lib/memex_web/live/context_live/show.html.heex:41
#: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:49
-#: lib/memex_web/live/pipeline_live/show.html.heex:38
+#: lib/memex_web/live/pipeline_live/show.html.heex:41
#, elixir-autogen, elixir-format
msgid "delete"
msgstr ""
@@ -83,11 +83,11 @@ msgid "delete user"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:38
-#: lib/memex_web/live/context_live/show.html.heex:27
+#: lib/memex_web/live/context_live/show.html.heex:30
#: lib/memex_web/live/note_live/index.html.heex:38
#: lib/memex_web/live/note_live/show.html.heex:27
#: lib/memex_web/live/pipeline_live/index.html.heex:38
-#: lib/memex_web/live/pipeline_live/show.html.heex:27
+#: lib/memex_web/live/pipeline_live/show.html.heex:30
#, elixir-autogen, elixir-format
msgid "edit"
msgstr ""
diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot
index c7d922e..d57984b 100644
--- a/priv/gettext/default.pot
+++ b/priv/gettext/default.pot
@@ -10,30 +10,6 @@
msgid ""
msgstr ""
-#: lib/memex_web/live/context_live/form_component.ex:61
-#: lib/memex_web/live/note_live/form_component.ex:60
-#: lib/memex_web/live/pipeline_live/form_component.ex:65
-#, elixir-autogen, elixir-format
-msgid "%{title} created"
-msgstr ""
-
-#: lib/memex_web/live/context_live/index.ex:57
-#: lib/memex_web/live/context_live/show.ex:37
-#: lib/memex_web/live/note_live/index.ex:57
-#: lib/memex_web/live/note_live/show.ex:37
-#: lib/memex_web/live/pipeline_live/index.ex:57
-#: lib/memex_web/live/pipeline_live/show.ex:37
-#, elixir-autogen, elixir-format
-msgid "%{title} deleted"
-msgstr ""
-
-#: lib/memex_web/live/context_live/form_component.ex:44
-#: lib/memex_web/live/note_live/form_component.ex:43
-#: lib/memex_web/live/pipeline_live/form_component.ex:48
-#, elixir-autogen, elixir-format
-msgid "%{title} saved"
-msgstr ""
-
#: lib/memex_web/live/invite_live/index.html.heex:90
#, elixir-autogen, elixir-format
msgid "Admins"
@@ -183,16 +159,6 @@ msgstr ""
msgid "document your processes, attaching contexts to each step"
msgstr ""
-#: lib/memex_web/live/context_live/index.ex:23
-#: lib/memex_web/live/context_live/show.ex:44
-#: lib/memex_web/live/note_live/index.ex:23
-#: lib/memex_web/live/note_live/show.ex:44
-#: lib/memex_web/live/pipeline_live/index.ex:23
-#: lib/memex_web/live/pipeline_live/show.ex:44
-#, elixir-autogen, elixir-format
-msgid "edit %{title}"
-msgstr ""
-
#: lib/memex_web/live/invite_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "edit invite"
@@ -392,16 +358,6 @@ msgstr ""
msgid "tags"
msgstr ""
-#: lib/memex_web/components/contexts_table_component.ex:47
-#: lib/memex_web/components/notes_table_component.ex:47
-#: lib/memex_web/components/pipelines_table_component.ex:47
-#: lib/memex_web/live/context_live/form_component.html.heex:14
-#: lib/memex_web/live/note_live/form_component.html.heex:14
-#: lib/memex_web/live/pipeline_live/form_component.html.heex:14
-#, elixir-autogen, elixir-format
-msgid "title"
-msgstr ""
-
#: lib/memex_web/components/invite_card.ex:20
#, elixir-autogen, elixir-format
msgid "unlimited"
@@ -476,3 +432,54 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "no pipelines found"
msgstr ""
+
+#: lib/memex_web/live/context_live/form_component.ex:61
+#: lib/memex_web/live/note_live/form_component.ex:60
+#: lib/memex_web/live/pipeline_live/form_component.ex:65
+#, elixir-autogen, elixir-format
+msgid "%{slug} created"
+msgstr ""
+
+#: lib/memex_web/live/context_live/index.ex:57
+#: lib/memex_web/live/context_live/show.ex:41
+#: lib/memex_web/live/note_live/index.ex:57
+#: lib/memex_web/live/note_live/show.ex:41
+#: lib/memex_web/live/pipeline_live/index.ex:57
+#: lib/memex_web/live/pipeline_live/show.ex:41
+#, elixir-autogen, elixir-format
+msgid "%{slug} deleted"
+msgstr ""
+
+#: lib/memex_web/live/context_live/form_component.ex:44
+#: lib/memex_web/live/note_live/form_component.ex:43
+#: lib/memex_web/live/pipeline_live/form_component.ex:48
+#, elixir-autogen, elixir-format
+msgid "%{slug} saved"
+msgstr ""
+
+#: lib/memex_web/live/context_live/index.ex:23
+#: lib/memex_web/live/context_live/show.ex:48
+#: lib/memex_web/live/note_live/index.ex:23
+#: lib/memex_web/live/note_live/show.ex:48
+#: lib/memex_web/live/pipeline_live/index.ex:23
+#: lib/memex_web/live/pipeline_live/show.ex:48
+#, elixir-autogen, elixir-format
+msgid "edit %{slug}"
+msgstr ""
+
+#: lib/memex_web/components/contexts_table_component.ex:47
+#: lib/memex_web/components/notes_table_component.ex:47
+#: lib/memex_web/components/pipelines_table_component.ex:47
+#: lib/memex_web/live/context_live/form_component.html.heex:14
+#: lib/memex_web/live/note_live/form_component.html.heex:14
+#: lib/memex_web/live/pipeline_live/form_component.html.heex:14
+#, elixir-autogen, elixir-format
+msgid "slug"
+msgstr ""
+
+#: lib/memex_web/live/context_live/show.ex:19
+#: lib/memex_web/live/note_live/show.ex:19
+#: lib/memex_web/live/pipeline_live/show.ex:19
+#, elixir-autogen, elixir-format
+msgid "%{slug} could not be found"
+msgstr ""
diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot
index 0e5a4bd..837d41d 100644
--- a/priv/gettext/errors.pot
+++ b/priv/gettext/errors.pot
@@ -20,26 +20,11 @@ msgstr ""
msgid "Error"
msgstr ""
-#: lib/memex_web/templates/error/error.html.heex:28
-#, elixir-autogen, elixir-format
-msgid "Go back home"
-msgstr ""
-
-#: lib/memex_web/views/error_view.ex:11
-#, elixir-autogen, elixir-format
-msgid "Internal Server Error"
-msgstr ""
-
#: lib/memex_web/controllers/user_session_controller.ex:17
#, elixir-autogen, elixir-format
msgid "Invalid email or password"
msgstr ""
-#: lib/memex_web/views/error_view.ex:9
-#, elixir-autogen, elixir-format
-msgid "Not found"
-msgstr ""
-
#: lib/memex_web/templates/user_registration/new.html.heex:15
#: lib/memex_web/templates/user_reset_password/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:64
@@ -69,11 +54,6 @@ msgstr ""
msgid "Unable to delete user"
msgstr ""
-#: lib/memex_web/views/error_view.ex:10
-#, elixir-autogen, elixir-format
-msgid "Unauthorized"
-msgstr ""
-
#: lib/memex_web/controllers/user_confirmation_controller.ex:54
#, elixir-autogen, elixir-format
msgid "User confirmation link is invalid or it has expired."
@@ -120,3 +100,33 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! Please check the errors below"
msgstr ""
+
+#: lib/memex/contexts/context.ex:49
+#: lib/memex/contexts/context.ex:60
+#: lib/memex/notes/note.ex:48
+#: lib/memex/notes/note.ex:59
+#: lib/memex/pipelines/pipeline.ex:50
+#: lib/memex/pipelines/pipeline.ex:61
+#, elixir-autogen, elixir-format
+msgid "invalid format: only numbers, letters and hyphen are accepted"
+msgstr ""
+
+#: lib/memex_web/templates/error/error.html.heex:28
+#, elixir-autogen, elixir-format
+msgid "go back home"
+msgstr ""
+
+#: lib/memex_web/views/error_view.ex:11
+#, elixir-autogen, elixir-format
+msgid "internal server error"
+msgstr ""
+
+#: lib/memex_web/views/error_view.ex:9
+#, elixir-autogen, elixir-format
+msgid "not found"
+msgstr ""
+
+#: lib/memex_web/views/error_view.ex:10
+#, elixir-autogen, elixir-format
+msgid "unauthorized"
+msgstr ""
diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot
index 31359f8..00fbc40 100644
--- a/priv/gettext/prompts.pot
+++ b/priv/gettext/prompts.pot
@@ -142,11 +142,11 @@ msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:46
-#: lib/memex_web/live/context_live/show.html.heex:35
+#: lib/memex_web/live/context_live/show.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:35
#: lib/memex_web/live/pipeline_live/index.html.heex:46
-#: lib/memex_web/live/pipeline_live/show.html.heex:35
+#: lib/memex_web/live/pipeline_live/show.html.heex:38
#, elixir-autogen, elixir-format
msgid "are you sure?"
msgstr ""
diff --git a/priv/repo/migrations/20221126182210_use_slugs.exs b/priv/repo/migrations/20221126182210_use_slugs.exs
new file mode 100644
index 0000000..e08fb27
--- /dev/null
+++ b/priv/repo/migrations/20221126182210_use_slugs.exs
@@ -0,0 +1,14 @@
+defmodule Memex.Repo.Migrations.UseSlugs do
+ use Ecto.Migration
+
+ def change do
+ rename table(:notes), :title, to: :slug
+ create unique_index(:notes, [:slug])
+
+ rename table(:contexts), :title, to: :slug
+ create unique_index(:contexts, [:slug])
+
+ rename table(:pipelines), :title, to: :slug
+ create unique_index(:pipelines, [:slug])
+ end
+end
diff --git a/test/memex/contexts_test.exs b/test/memex/contexts_test.exs
index 69438dd..c4da056 100644
--- a/test/memex/contexts_test.exs
+++ b/test/memex/contexts_test.exs
@@ -3,7 +3,7 @@ defmodule Memex.ContextsTest do
import Memex.ContextsFixtures
alias Memex.{Contexts, Contexts.Context}
@moduletag :contexts_test
- @invalid_attrs %{content: nil, tag: nil, title: nil, visibility: nil}
+ @invalid_attrs %{content: nil, tag: nil, slug: nil, visibility: nil}
describe "contexts" do
setup do
@@ -11,9 +11,9 @@ defmodule Memex.ContextsTest do
end
test "list_contexts/1 returns all contexts for a user", %{user: user} do
- context_a = context_fixture(%{title: "a", visibility: :public}, user)
- context_b = context_fixture(%{title: "b", visibility: :unlisted}, user)
- context_c = context_fixture(%{title: "c", visibility: :private}, user)
+ context_a = context_fixture(%{slug: "a", visibility: :public}, user)
+ context_b = context_fixture(%{slug: "b", visibility: :unlisted}, user)
+ context_c = context_fixture(%{slug: "c", visibility: :private}, user)
assert Contexts.list_contexts(user) == [context_a, context_b, context_c]
end
@@ -50,18 +50,43 @@ defmodule Memex.ContextsTest do
end
end
+ test "get_context_by_slug/1 returns the context with given id", %{user: user} do
+ context = context_fixture(%{slug: "a", visibility: :public}, user)
+ assert Contexts.get_context_by_slug("a", user) == context
+
+ context = context_fixture(%{slug: "b", visibility: :unlisted}, user)
+ assert Contexts.get_context_by_slug("b", user) == context
+
+ context = context_fixture(%{slug: "c", visibility: :private}, user)
+ assert Contexts.get_context_by_slug("c", user) == context
+ end
+
+ test "get_context_by_slug/1 only returns unlisted or public contexts for other users", %{
+ user: user
+ } do
+ another_user = user_fixture()
+ context = context_fixture(%{slug: "a", visibility: :public}, another_user)
+ assert Contexts.get_context_by_slug("a", user) == context
+
+ context = context_fixture(%{slug: "b", visibility: :unlisted}, another_user)
+ assert Contexts.get_context_by_slug("b", user) == context
+
+ context_fixture(%{slug: "c", visibility: :private}, another_user)
+ assert Contexts.get_context_by_slug("c", user) |> is_nil()
+ end
+
test "create_context/1 with valid data creates a context", %{user: user} do
valid_attrs = %{
"content" => "some content",
"tags_string" => "tag1,tag2",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
assert {:ok, %Context{} = context} = Contexts.create_context(valid_attrs, user)
assert context.content == "some content"
assert context.tags == ["tag1", "tag2"]
- assert context.title == "some title"
+ assert context.slug == "some-slug"
assert context.visibility == :public
end
@@ -75,14 +100,14 @@ defmodule Memex.ContextsTest do
update_attrs = %{
"content" => "some updated content",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
assert {:ok, %Context{} = context} = Contexts.update_context(context, update_attrs, user)
assert context.content == "some updated content"
assert context.tags == ["tag1", "tag2"]
- assert context.title == "some updated title"
+ assert context.slug == "some-updated-slug"
assert context.visibility == :private
end
diff --git a/test/memex/notes_test.exs b/test/memex/notes_test.exs
index bbb2663..788505b 100644
--- a/test/memex/notes_test.exs
+++ b/test/memex/notes_test.exs
@@ -3,7 +3,7 @@ defmodule Memex.NotesTest do
import Memex.NotesFixtures
alias Memex.{Notes, Notes.Note}
@moduletag :notes_test
- @invalid_attrs %{content: nil, tag: nil, title: nil, visibility: nil}
+ @invalid_attrs %{content: nil, tag: nil, slug: nil, visibility: nil}
describe "notes" do
setup do
@@ -11,9 +11,9 @@ defmodule Memex.NotesTest do
end
test "list_notes/1 returns all notes for a user", %{user: user} do
- note_a = note_fixture(%{title: "a", visibility: :public}, user)
- note_b = note_fixture(%{title: "b", visibility: :unlisted}, user)
- note_c = note_fixture(%{title: "c", visibility: :private}, user)
+ note_a = note_fixture(%{slug: "a", visibility: :public}, user)
+ note_b = note_fixture(%{slug: "b", visibility: :unlisted}, user)
+ note_c = note_fixture(%{slug: "c", visibility: :private}, user)
assert Notes.list_notes(user) == [note_a, note_b, note_c]
end
@@ -50,18 +50,43 @@ defmodule Memex.NotesTest do
end
end
+ test "get_note_by_slug/1 returns the note with given id", %{user: user} do
+ note = note_fixture(%{slug: "a", visibility: :public}, user)
+ assert Notes.get_note_by_slug("a", user) == note
+
+ note = note_fixture(%{slug: "b", visibility: :unlisted}, user)
+ assert Notes.get_note_by_slug("b", user) == note
+
+ note = note_fixture(%{slug: "c", visibility: :private}, user)
+ assert Notes.get_note_by_slug("c", user) == note
+ end
+
+ test "get_note_by_slug/1 only returns unlisted or public notes for other users", %{
+ user: user
+ } do
+ another_user = user_fixture()
+ note = note_fixture(%{slug: "a", visibility: :public}, another_user)
+ assert Notes.get_note_by_slug("a", user) == note
+
+ note = note_fixture(%{slug: "b", visibility: :unlisted}, another_user)
+ assert Notes.get_note_by_slug("b", user) == note
+
+ note_fixture(%{slug: "c", visibility: :private}, another_user)
+ assert Notes.get_note_by_slug("c", user) |> is_nil()
+ end
+
test "create_note/1 with valid data creates a note", %{user: user} do
valid_attrs = %{
"content" => "some content",
"tags_string" => "tag1,tag2",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
assert {:ok, %Note{} = note} = Notes.create_note(valid_attrs, user)
assert note.content == "some content"
assert note.tags == ["tag1", "tag2"]
- assert note.title == "some title"
+ assert note.slug == "some-slug"
assert note.visibility == :public
end
@@ -75,14 +100,14 @@ defmodule Memex.NotesTest do
update_attrs = %{
"content" => "some updated content",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
assert {:ok, %Note{} = note} = Notes.update_note(note, update_attrs, user)
assert note.content == "some updated content"
assert note.tags == ["tag1", "tag2"]
- assert note.title == "some updated title"
+ assert note.slug == "some-updated-slug"
assert note.visibility == :private
end
diff --git a/test/memex/pipelines_test.exs b/test/memex/pipelines_test.exs
index 8746d6c..074a553 100644
--- a/test/memex/pipelines_test.exs
+++ b/test/memex/pipelines_test.exs
@@ -3,7 +3,7 @@ defmodule Memex.PipelinesTest do
import Memex.PipelinesFixtures
alias Memex.{Pipelines, Pipelines.Pipeline}
@moduletag :pipelines_test
- @invalid_attrs %{description: nil, tag: nil, title: nil, visibility: nil}
+ @invalid_attrs %{description: nil, tag: nil, slug: nil, visibility: nil}
describe "pipelines" do
setup do
@@ -11,9 +11,9 @@ defmodule Memex.PipelinesTest do
end
test "list_pipelines/1 returns all pipelines for a user", %{user: user} do
- pipeline_a = pipeline_fixture(%{title: "a", visibility: :public}, user)
- pipeline_b = pipeline_fixture(%{title: "b", visibility: :unlisted}, user)
- pipeline_c = pipeline_fixture(%{title: "c", visibility: :private}, user)
+ pipeline_a = pipeline_fixture(%{slug: "a", visibility: :public}, user)
+ pipeline_b = pipeline_fixture(%{slug: "b", visibility: :unlisted}, user)
+ pipeline_c = pipeline_fixture(%{slug: "c", visibility: :private}, user)
assert Pipelines.list_pipelines(user) == [pipeline_a, pipeline_b, pipeline_c]
end
@@ -52,18 +52,43 @@ defmodule Memex.PipelinesTest do
end
end
+ test "get_pipeline_by_slug/1 returns the pipeline with given id", %{user: user} do
+ pipeline = pipeline_fixture(%{slug: "a", visibility: :public}, user)
+ assert Pipelines.get_pipeline_by_slug("a", user) == pipeline
+
+ pipeline = pipeline_fixture(%{slug: "b", visibility: :unlisted}, user)
+ assert Pipelines.get_pipeline_by_slug("b", user) == pipeline
+
+ pipeline = pipeline_fixture(%{slug: "c", visibility: :private}, user)
+ assert Pipelines.get_pipeline_by_slug("c", user) == pipeline
+ end
+
+ test "get_pipeline_by_slug/1 only returns unlisted or public pipelines for other users", %{
+ user: user
+ } do
+ another_user = user_fixture()
+ pipeline = pipeline_fixture(%{slug: "a", visibility: :public}, another_user)
+ assert Pipelines.get_pipeline_by_slug("a", user) == pipeline
+
+ pipeline = pipeline_fixture(%{slug: "b", visibility: :unlisted}, another_user)
+ assert Pipelines.get_pipeline_by_slug("b", user) == pipeline
+
+ pipeline_fixture(%{slug: "c", visibility: :private}, another_user)
+ assert Pipelines.get_pipeline_by_slug("c", user) |> is_nil()
+ end
+
test "create_pipeline/1 with valid data creates a pipeline", %{user: user} do
valid_attrs = %{
"description" => "some description",
"tags_string" => "tag1,tag2",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
assert {:ok, %Pipeline{} = pipeline} = Pipelines.create_pipeline(valid_attrs, user)
assert pipeline.description == "some description"
assert pipeline.tags == ["tag1", "tag2"]
- assert pipeline.title == "some title"
+ assert pipeline.slug == "some-slug"
assert pipeline.visibility == :public
end
@@ -77,7 +102,7 @@ defmodule Memex.PipelinesTest do
update_attrs = %{
"description" => "some updated description",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
@@ -86,7 +111,7 @@ defmodule Memex.PipelinesTest do
assert pipeline.description == "some updated description"
assert pipeline.tags == ["tag1", "tag2"]
- assert pipeline.title == "some updated title"
+ assert pipeline.slug == "some-updated-slug"
assert pipeline.visibility == :private
end
diff --git a/test/memex_web/live/context_live_test.exs b/test/memex_web/live/context_live_test.exs
index c2d83dc..5837cd7 100644
--- a/test/memex_web/live/context_live_test.exs
+++ b/test/memex_web/live/context_live_test.exs
@@ -7,19 +7,19 @@ defmodule MemexWeb.ContextLiveTest do
@create_attrs %{
"content" => "some content",
"tags_string" => "tag1",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
@update_attrs %{
"content" => "some updated content",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
@invalid_attrs %{
"content" => nil,
"tags_string" => "",
- "title" => nil,
+ "slug" => nil,
"visibility" => nil
}
@@ -55,7 +55,7 @@ defmodule MemexWeb.ContextLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.context_index_path(conn, :index))
- assert html =~ "#{@create_attrs |> Map.get("title")} created"
+ assert html =~ "#{@create_attrs |> Map.get("slug")} created"
assert html =~ "some content"
end
@@ -65,7 +65,7 @@ defmodule MemexWeb.ContextLiveTest do
assert index_live |> element("[data-qa=\"context-edit-#{context.id}\"]") |> render_click() =~
"edit"
- assert_patch(index_live, Routes.context_index_path(conn, :edit, context))
+ assert_patch(index_live, Routes.context_index_path(conn, :edit, context.slug))
assert index_live
|> form("#context-form", context: @invalid_attrs)
@@ -77,7 +77,7 @@ defmodule MemexWeb.ContextLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.context_index_path(conn, :index))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{@update_attrs |> Map.get("slug")} saved"
assert html =~ "some updated content"
end
@@ -93,18 +93,18 @@ defmodule MemexWeb.ContextLiveTest do
setup [:register_and_log_in_user, :create_context]
test "displays context", %{conn: conn, context: context} do
- {:ok, _show_live, html} = live(conn, Routes.context_show_path(conn, :show, context))
+ {:ok, _show_live, html} = live(conn, Routes.context_show_path(conn, :show, context.slug))
assert html =~ "context"
assert html =~ context.content
end
test "updates context within modal", %{conn: conn, context: context} do
- {:ok, show_live, _html} = live(conn, Routes.context_show_path(conn, :show, context))
+ {:ok, show_live, _html} = live(conn, Routes.context_show_path(conn, :show, context.slug))
assert show_live |> element("a", "edit") |> render_click() =~ "edit"
- assert_patch(show_live, Routes.context_show_path(conn, :edit, context))
+ assert_patch(show_live, Routes.context_show_path(conn, :edit, context.slug))
assert show_live
|> form("#context-form", context: @invalid_attrs)
@@ -112,16 +112,16 @@ defmodule MemexWeb.ContextLiveTest do
{:ok, _, html} =
show_live
- |> form("#context-form", context: @update_attrs)
+ |> form("#context-form", context: Map.put(@update_attrs, "slug", context.slug))
|> render_submit()
- |> follow_redirect(conn, Routes.context_show_path(conn, :show, context))
+ |> follow_redirect(conn, Routes.context_show_path(conn, :show, context.slug))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{context.slug} saved"
assert html =~ "some updated content"
end
test "deletes context", %{conn: conn, context: context} do
- {:ok, show_live, _html} = live(conn, Routes.context_show_path(conn, :show, context))
+ {:ok, show_live, _html} = live(conn, Routes.context_show_path(conn, :show, context.slug))
{:ok, index_live, _html} =
show_live
diff --git a/test/memex_web/live/note_live_test.exs b/test/memex_web/live/note_live_test.exs
index 46a9716..d93aebc 100644
--- a/test/memex_web/live/note_live_test.exs
+++ b/test/memex_web/live/note_live_test.exs
@@ -7,19 +7,19 @@ defmodule MemexWeb.NoteLiveTest do
@create_attrs %{
"content" => "some content",
"tags_string" => "tag1",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
@update_attrs %{
"content" => "some updated content",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
@invalid_attrs %{
"content" => nil,
"tags_string" => "",
- "title" => nil,
+ "slug" => nil,
"visibility" => nil
}
@@ -55,7 +55,7 @@ defmodule MemexWeb.NoteLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.note_index_path(conn, :index))
- assert html =~ "#{@create_attrs |> Map.get("title")} created"
+ assert html =~ "#{@create_attrs |> Map.get("slug")} created"
assert html =~ "some content"
end
@@ -65,7 +65,7 @@ defmodule MemexWeb.NoteLiveTest do
assert index_live |> element("[data-qa=\"note-edit-#{note.id}\"]") |> render_click() =~
"edit"
- assert_patch(index_live, Routes.note_index_path(conn, :edit, note))
+ assert_patch(index_live, Routes.note_index_path(conn, :edit, note.slug))
assert index_live
|> form("#note-form", note: @invalid_attrs)
@@ -77,7 +77,7 @@ defmodule MemexWeb.NoteLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.note_index_path(conn, :index))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{@update_attrs |> Map.get("slug")} saved"
assert html =~ "some updated content"
end
@@ -93,18 +93,18 @@ defmodule MemexWeb.NoteLiveTest do
setup [:register_and_log_in_user, :create_note]
test "displays note", %{conn: conn, note: note} do
- {:ok, _show_live, html} = live(conn, Routes.note_show_path(conn, :show, note))
+ {:ok, _show_live, html} = live(conn, Routes.note_show_path(conn, :show, note.slug))
assert html =~ "note"
assert html =~ note.content
end
test "updates note within modal", %{conn: conn, note: note} do
- {:ok, show_live, _html} = live(conn, Routes.note_show_path(conn, :show, note))
+ {:ok, show_live, _html} = live(conn, Routes.note_show_path(conn, :show, note.slug))
assert show_live |> element("a", "edit") |> render_click() =~ "edit"
- assert_patch(show_live, Routes.note_show_path(conn, :edit, note))
+ assert_patch(show_live, Routes.note_show_path(conn, :edit, note.slug))
assert show_live
|> form("#note-form", note: @invalid_attrs)
@@ -112,16 +112,16 @@ defmodule MemexWeb.NoteLiveTest do
{:ok, _, html} =
show_live
- |> form("#note-form", note: @update_attrs)
+ |> form("#note-form", note: Map.put(@update_attrs, "slug", note.slug))
|> render_submit()
- |> follow_redirect(conn, Routes.note_show_path(conn, :show, note))
+ |> follow_redirect(conn, Routes.note_show_path(conn, :show, note.slug))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{note.slug} saved"
assert html =~ "some updated content"
end
test "deletes note", %{conn: conn, note: note} do
- {:ok, show_live, _html} = live(conn, Routes.note_show_path(conn, :show, note))
+ {:ok, show_live, _html} = live(conn, Routes.note_show_path(conn, :show, note.slug))
{:ok, index_live, _html} =
show_live
diff --git a/test/memex_web/live/pipeline_live_test.exs b/test/memex_web/live/pipeline_live_test.exs
index 587192f..afa41c3 100644
--- a/test/memex_web/live/pipeline_live_test.exs
+++ b/test/memex_web/live/pipeline_live_test.exs
@@ -7,19 +7,19 @@ defmodule MemexWeb.PipelineLiveTest do
@create_attrs %{
"description" => "some description",
"tags_string" => "tag1",
- "title" => "some title",
+ "slug" => "some-slug",
"visibility" => :public
}
@update_attrs %{
"description" => "some updated description",
"tags_string" => "tag1,tag2",
- "title" => "some updated title",
+ "slug" => "some-updated-slug",
"visibility" => :private
}
@invalid_attrs %{
"description" => nil,
"tags_string" => "",
- "title" => nil,
+ "slug" => nil,
"visibility" => nil
}
@@ -55,7 +55,7 @@ defmodule MemexWeb.PipelineLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.pipeline_index_path(conn, :index))
- assert html =~ "#{@create_attrs |> Map.get("title")} created"
+ assert html =~ "#{@create_attrs |> Map.get("slug")} created"
assert html =~ "some description"
end
@@ -65,7 +65,7 @@ defmodule MemexWeb.PipelineLiveTest do
assert index_live |> element("[data-qa=\"pipeline-edit-#{pipeline.id}\"]") |> render_click() =~
"edit"
- assert_patch(index_live, Routes.pipeline_index_path(conn, :edit, pipeline))
+ assert_patch(index_live, Routes.pipeline_index_path(conn, :edit, pipeline.slug))
assert index_live
|> form("#pipeline-form", pipeline: @invalid_attrs)
@@ -77,7 +77,7 @@ defmodule MemexWeb.PipelineLiveTest do
|> render_submit()
|> follow_redirect(conn, Routes.pipeline_index_path(conn, :index))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{@update_attrs |> Map.get("slug")} saved"
assert html =~ "some updated description"
end
@@ -96,18 +96,18 @@ defmodule MemexWeb.PipelineLiveTest do
setup [:register_and_log_in_user, :create_pipeline]
test "displays pipeline", %{conn: conn, pipeline: pipeline} do
- {:ok, _show_live, html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline))
+ {:ok, _show_live, html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
assert html =~ "pipeline"
assert html =~ pipeline.description
end
test "updates pipeline within modal", %{conn: conn, pipeline: pipeline} do
- {:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline))
+ {:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
assert show_live |> element("a", "edit") |> render_click() =~ "edit"
- assert_patch(show_live, Routes.pipeline_show_path(conn, :edit, pipeline))
+ assert_patch(show_live, Routes.pipeline_show_path(conn, :edit, pipeline.slug))
assert show_live
|> form("#pipeline-form", pipeline: @invalid_attrs)
@@ -115,16 +115,16 @@ defmodule MemexWeb.PipelineLiveTest do
{:ok, _, html} =
show_live
- |> form("#pipeline-form", pipeline: @update_attrs)
+ |> form("#pipeline-form", pipeline: Map.put(@update_attrs, "slug", pipeline.slug))
|> render_submit()
- |> follow_redirect(conn, Routes.pipeline_show_path(conn, :show, pipeline))
+ |> follow_redirect(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
- assert html =~ "#{@update_attrs |> Map.get("title")} saved"
+ assert html =~ "#{pipeline.slug} saved"
assert html =~ "some updated description"
end
test "deletes pipeline", %{conn: conn, pipeline: pipeline} do
- {:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline))
+ {:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
{:ok, index_live, _html} =
show_live
diff --git a/test/memex_web/views/error_view_test.exs b/test/memex_web/views/error_view_test.exs
index f2ecd03..b4c0a4f 100644
--- a/test/memex_web/views/error_view_test.exs
+++ b/test/memex_web/views/error_view_test.exs
@@ -13,11 +13,11 @@ defmodule MemexWeb.ErrorViewTest do
test "renders 404.html" do
assert render_to_string(MemexWeb.ErrorView, "404.html", []) =~
- dgettext("errors", "Not found")
+ dgettext("errors", "not found")
end
test "renders 500.html" do
assert render_to_string(MemexWeb.ErrorView, "500.html", []) =~
- dgettext("errors", "Internal Server Error")
+ dgettext("errors", "internal server error")
end
end
diff --git a/test/support/fixtures.ex b/test/support/fixtures.ex
index 13b3baa..6355a60 100644
--- a/test/support/fixtures.ex
+++ b/test/support/fixtures.ex
@@ -2,7 +2,6 @@ defmodule Memex.Fixtures do
@moduledoc """
This module defines test helpers for creating entities
"""
-
alias Memex.{Accounts, Accounts.User, Email, Repo}
def unique_user_email, do: "user#{System.unique_integer()}@example.com"
@@ -57,5 +56,14 @@ defmodule Memex.Fixtures do
})
end
+ def random_slug(length \\ 20) do
+ symbols = '0123456789abcdef-'
+ symbol_count = Enum.count(symbols)
+
+ for _ <- Range.new(1, length),
+ into: "",
+ do: <>
+ end
+
defp unwrap_ok_tuple({:ok, value}), do: value
end
diff --git a/test/support/fixtures/contexts_fixtures.ex b/test/support/fixtures/contexts_fixtures.ex
index b930f21..f034543 100644
--- a/test/support/fixtures/contexts_fixtures.ex
+++ b/test/support/fixtures/contexts_fixtures.ex
@@ -3,6 +3,7 @@ defmodule Memex.ContextsFixtures do
This module defines test helpers for creating
entities via the `Memex.Contexts` context.
"""
+ import Memex.Fixtures
alias Memex.{Accounts.User, Contexts, Contexts.Context}
@doc """
@@ -16,7 +17,7 @@ defmodule Memex.ContextsFixtures do
|> Enum.into(%{
content: "some content",
tag: [],
- title: "some title",
+ slug: random_slug(),
visibility: :private
})
|> Contexts.create_context(user)
diff --git a/test/support/fixtures/notes_fixtures.ex b/test/support/fixtures/notes_fixtures.ex
index ee3266b..2c593e6 100644
--- a/test/support/fixtures/notes_fixtures.ex
+++ b/test/support/fixtures/notes_fixtures.ex
@@ -3,6 +3,7 @@ defmodule Memex.NotesFixtures do
This module defines test helpers for creating
entities via the `Memex.Notes` context.
"""
+ import Memex.Fixtures
alias Memex.{Accounts.User, Notes, Notes.Note}
@doc """
@@ -16,7 +17,7 @@ defmodule Memex.NotesFixtures do
|> Enum.into(%{
content: "some content",
tag: [],
- title: "some title",
+ slug: random_slug(),
visibility: :private
})
|> Notes.create_note(user)
diff --git a/test/support/fixtures/pipelines_fixtures.ex b/test/support/fixtures/pipelines_fixtures.ex
index 48168c1..2cd6069 100644
--- a/test/support/fixtures/pipelines_fixtures.ex
+++ b/test/support/fixtures/pipelines_fixtures.ex
@@ -3,6 +3,7 @@ defmodule Memex.PipelinesFixtures do
This module defines test helpers for creating
entities via the `Memex.Pipelines` context.
"""
+ import Memex.Fixtures
alias Memex.{Accounts.User, Pipelines, Pipelines.Pipeline}
@doc """
@@ -16,7 +17,7 @@ defmodule Memex.PipelinesFixtures do
|> Enum.into(%{
description: "some description",
tag: [],
- title: "some title",
+ slug: random_slug(),
visibility: :private
})
|> Pipelines.create_pipeline(user)