From 1a508a42ef2ff736c5689539ead67510a2d599a0 Mon Sep 17 00:00:00 2001 From: shibao Date: Thu, 17 Nov 2022 22:38:52 -0500 Subject: [PATCH] implement notes --- assets/js/maintain_attrs.js | 20 +- lib/memex/notes.ex | 115 ++++- lib/memex/notes/note.ex | 46 +- lib/memex_web/components/note_card.ex | 29 ++ .../components/notes_table_component.ex | 136 +++++ .../live/note_live/form_component.ex | 42 +- .../live/note_live/form_component.html.heex | 49 +- lib/memex_web/live/note_live/index.ex | 39 +- lib/memex_web/live/note_live/index.html.heex | 98 ++-- lib/memex_web/live/note_live/show.ex | 10 +- lib/memex_web/live/note_live/show.html.heex | 67 ++- priv/gettext/actions.pot | 162 +++--- priv/gettext/default.pot | 476 +++++++++++------- priv/gettext/emails.pot | 28 +- priv/gettext/errors.pot | 48 +- priv/gettext/prompts.pot | 113 +++-- .../20220726000552_create_notes.exs | 4 +- test/memex/notes_test.exs | 120 +++-- test/memex_web/live/context_live_test.exs | 24 +- test/memex_web/live/note_live_test.exs | 35 +- test/support/fixtures/notes_fixtures.ex | 9 +- 21 files changed, 1096 insertions(+), 574 deletions(-) create mode 100644 lib/memex_web/components/note_card.ex create mode 100644 lib/memex_web/components/notes_table_component.ex diff --git a/assets/js/maintain_attrs.js b/assets/js/maintain_attrs.js index f4ff238..ae1a194 100644 --- a/assets/js/maintain_attrs.js +++ b/assets/js/maintain_attrs.js @@ -2,7 +2,21 @@ // update. https://github.com/phoenixframework/phoenix_live_view/issues/1011 export default { - attrs () { return this.el.getAttribute('data-attrs').split(', ') }, - beforeUpdate () { this.prevAttrs = this.attrs().map(name => [name, this.el.getAttribute(name)]) }, - updated () { this.prevAttrs.forEach(([name, val]) => this.el.setAttribute(name, val)) } + attrs () { + if (this.el && this.el.getAttribute('data-attrs')) { + return this.el.getAttribute('data-attrs').split(', ') + } else { + return [] + } + }, + beforeUpdate () { + if (this.el) { + this.prevAttrs = this.attrs().map(name => [name, this.el.getAttribute(name)]) + } + }, + updated () { + if (this.el) { + this.prevAttrs.forEach(([name, val]) => this.el.setAttribute(name, val)) + } + } } diff --git a/lib/memex/notes.ex b/lib/memex/notes.ex index 6670bb1..ecd0b21 100644 --- a/lib/memex/notes.ex +++ b/lib/memex/notes.ex @@ -4,21 +4,40 @@ defmodule Memex.Notes do """ import Ecto.Query, warn: false - alias Memex.Repo - - alias Memex.Notes.Note + alias Ecto.Changeset + alias Memex.{Accounts.User, Notes.Note, Repo} @doc """ Returns the list of notes. ## Examples - iex> list_notes() + iex> list_notes(%User{id: 123}) [%Note{}, ...] + iex> list_notes("my note", %User{id: 123}) + [%Note{title: "my note"}, ...] + """ - def list_notes do - Repo.all(Note) + @spec list_notes(User.t()) :: [Note.t()] + def list_notes(%{id: user_id}) do + Repo.all(from n in Note, where: n.user_id == ^user_id, order_by: n.title) + end + + @doc """ + Returns the list of public notes for viewing + + ## Examples + + iex> list_public_notes() + [%Note{}, ...] + + iex> list_public_notes("my note") + [%Note{title: "my note"}, ...] + """ + @spec list_public_notes() :: [Note.t()] + def list_public_notes do + Repo.all(from n in Note, where: n.visibility == :public, order_by: n.title) end @doc """ @@ -28,31 +47,46 @@ defmodule Memex.Notes do ## Examples - iex> get_note!(123) + iex> get_note!(123, %User{id: 123}) %Note{} - iex> get_note!(456) + iex> get_note!(456, %User{id: 123}) ** (Ecto.NoResultsError) """ - def get_note!(id), do: Repo.get!(Note, id) + @spec get_note!(Note.id(), User.t()) :: Note.t() + def get_note!(id, %{id: user_id}) do + Repo.one!( + from n in Note, + where: n.id == ^id, + where: n.user_id == ^user_id or n.visibility in [:public, :unlisted] + ) + end + + def get_note!(id, _invalid_user) do + Repo.one!( + from n in Note, + where: n.id == ^id, + where: n.visibility in [:public, :unlisted] + ) + end @doc """ Creates a note. ## Examples - iex> create_note(%{field: value}) + iex> create_note(%{field: value}, %User{id: 123}) {:ok, %Note{}} - iex> create_note(%{field: bad_value}) + iex> create_note(%{field: bad_value}, %User{id: 123}) {:error, %Ecto.Changeset{}} """ - def create_note(attrs \\ %{}) do - %Note{} - |> Note.changeset(attrs) - |> Repo.insert() + @spec create_note(User.t()) :: {:ok, Note.t()} | {:error, Note.changeset()} + @spec create_note(attrs :: map(), User.t()) :: {:ok, Note.t()} | {:error, Note.changeset()} + def create_note(attrs \\ %{}, user) do + Note.create_changeset(attrs, user) |> Repo.insert() end @doc """ @@ -60,16 +94,18 @@ defmodule Memex.Notes do ## Examples - iex> update_note(note, %{field: new_value}) + iex> update_note(note, %{field: new_value}, %User{id: 123}) {:ok, %Note{}} - iex> update_note(note, %{field: bad_value}) + iex> update_note(note, %{field: bad_value}, %User{id: 123}) {:error, %Ecto.Changeset{}} """ - def update_note(%Note{} = note, attrs) do + @spec update_note(Note.t(), attrs :: map(), User.t()) :: + {:ok, Note.t()} | {:error, Note.changeset()} + def update_note(%Note{} = note, attrs, user) do note - |> Note.changeset(attrs) + |> Note.update_changeset(attrs, user) |> Repo.update() end @@ -78,15 +114,23 @@ defmodule Memex.Notes do ## Examples - iex> delete_note(note) + iex> delete_note(%Note{user_id: 123}, %User{id: 123}) {:ok, %Note{}} - iex> delete_note(note) + iex> delete_note(%Note{}, %User{role: :admin}) + {:ok, %Note{}} + + iex> delete_note(%Note{}, %User{id: 123}) {:error, %Ecto.Changeset{}} """ - def delete_note(%Note{} = note) do - Repo.delete(note) + @spec delete_note(Note.t(), User.t()) :: {:ok, Note.t()} | {:error, Note.changeset()} + def delete_note(%Note{user_id: user_id} = note, %{id: user_id}) do + note |> Repo.delete() + end + + def delete_note(%Note{} = note, %{role: :admin}) do + note |> Repo.delete() end @doc """ @@ -94,11 +138,30 @@ defmodule Memex.Notes do ## Examples - iex> change_note(note) + iex> change_note(note, %User{id: 123}) + %Ecto.Changeset{data: %Note{}} + + iex> change_note(note, %{title: "new title"}, %User{id: 123}) %Ecto.Changeset{data: %Note{}} """ - def change_note(%Note{} = note, attrs \\ %{}) do - Note.changeset(note, attrs) + @spec change_note(Note.t(), User.t()) :: Note.changeset() + @spec change_note(Note.t(), attrs :: map(), User.t()) :: Note.changeset() + def change_note(%Note{} = note, attrs \\ %{}, user) do + note |> Note.update_changeset(attrs, user) + end + + @doc """ + Gets a canonical string representation of the `:tags` field for a Note + """ + @spec get_tags_string(Note.t() | Note.changeset() | [String.t()] | nil) :: String.t() + def get_tags_string(nil), do: "" + def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",") + def get_tags_string(%Note{tags: tags}), do: tags |> get_tags_string() + + def get_tags_string(%Changeset{} = changeset) do + changeset + |> Changeset.get_field(:tags) + |> get_tags_string() end end diff --git a/lib/memex/notes/note.ex b/lib/memex/notes/note.ex index 1175d5a..84bc68e 100644 --- a/lib/memex/notes/note.ex +++ b/lib/memex/notes/note.ex @@ -1,22 +1,58 @@ defmodule Memex.Notes.Note do + @moduledoc """ + Schema for a user-written note + """ use Ecto.Schema import Ecto.Changeset + alias Ecto.{Changeset, UUID} + alias Memex.{Accounts.User, Notes.Note} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "notes" do field :content, :string - field :tag, {:array, :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 + timestamps() end + @type t :: %Note{} + @type id :: UUID.t() + @type changeset :: Changeset.t(t()) + @doc false - def changeset(note, attrs) do - note - |> cast(attrs, [:title, :content, :tag, :visibility]) - |> validate_required([:title, :content, :tag, :visibility]) + @spec create_changeset(attrs :: map(), User.t()) :: changeset() + def create_changeset(attrs, %User{id: user_id}) do + %Note{} + |> cast(attrs, [:title, :content, :tags, :visibility]) + |> change(user_id: user_id) + |> cast_tags_string(attrs) + |> validate_required([:title, :content, :user_id, :visibility]) end + + @spec update_changeset(Note.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_tags_string(attrs) + |> validate_required([:title, :content, :visibility]) + end + + defp cast_tags_string(changeset, %{"tags_string" => tags_string}) + when tags_string |> is_binary() do + tags = + tags_string + |> String.split(",", trim: true) + |> Enum.map(fn str -> str |> String.trim() end) + |> Enum.sort() + + changeset |> change(tags: tags) + end + + defp cast_tags_string(changeset, _attrs), do: changeset end diff --git a/lib/memex_web/components/note_card.ex b/lib/memex_web/components/note_card.ex new file mode 100644 index 0000000..3f306e0 --- /dev/null +++ b/lib/memex_web/components/note_card.ex @@ -0,0 +1,29 @@ +defmodule MemexWeb.Components.NoteCard do + @moduledoc """ + Display card for an note + """ + + use MemexWeb, :component + + def note_card(assigns) do + ~H""" +
+

+ <%= @note.name %> +

+ +

+ <%= gettext("visibility: %{visibility}", visibility: @note.visibility) %> +

+ + <%= if @inner_block do %> +
+ <%= render_slot(@inner_block) %> +
+ <% end %> +
+ """ + end +end diff --git a/lib/memex_web/components/notes_table_component.ex b/lib/memex_web/components/notes_table_component.ex new file mode 100644 index 0000000..731f588 --- /dev/null +++ b/lib/memex_web/components/notes_table_component.ex @@ -0,0 +1,136 @@ +defmodule MemexWeb.Components.NotesTableComponent do + @moduledoc """ + A component that displays a list of notes + """ + use MemexWeb, :live_component + alias Ecto.UUID + alias Memex.{Accounts.User, Notes, Notes.Note} + alias MemexWeb.Endpoint + alias Phoenix.LiveView.{Rendered, Socket} + + @impl true + @spec update( + %{ + required(:id) => UUID.t(), + required(:current_user) => User.t(), + required(:notes) => [Note.t()], + optional(any()) => any() + }, + Socket.t() + ) :: {:ok, Socket.t()} + def update(%{id: _id, notes: _notes, current_user: _current_user} = assigns, socket) do + socket = + socket + |> assign(assigns) + |> assign_new(:actions, fn -> [] end) + |> display_notes() + + {:ok, socket} + end + + defp display_notes( + %{ + assigns: %{ + notes: notes, + current_user: current_user, + actions: actions + } + } = socket + ) do + columns = + if actions == [] or current_user |> is_nil() do + [] + else + [%{label: nil, key: :actions, sortable: false}] + end + + columns = [ + %{label: gettext("title"), key: :title}, + %{label: gettext("content"), key: :content}, + %{label: gettext("tags"), key: :tags}, + %{label: gettext("visibility"), key: :visibility} + | columns + ] + + rows = + notes + |> Enum.map(fn note -> + note + |> get_row_data_for_note(%{ + columns: columns, + current_user: current_user, + actions: actions + }) + end) + + socket |> assign(columns: columns, rows: rows) + end + + @impl true + def render(assigns) do + ~H""" +
+ <.live_component + module={MemexWeb.Components.TableComponent} + id={@id} + columns={@columns} + rows={@rows} + /> +
+ """ + end + + @spec get_row_data_for_note(Note.t(), additional_data :: map()) :: map() + defp get_row_data_for_note(note, %{columns: columns} = additional_data) do + columns + |> Map.new(fn %{key: key} -> + {key, get_value_for_key(key, note, additional_data)} + end) + end + + @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} + + title_block = ~H""" + <.link + navigate={Routes.note_show_path(Endpoint, :show, @id)} + class="link" + data-qa={"note-show-#{@id}"} + > + <%= @title %> + + """ + + {title, title_block} + end + + defp get_value_for_key(:content, %{content: content}, _additional_data) do + assigns = %{content: content} + + content_block = ~H""" +
+ <%= @content %> +
+ """ + + {content, content_block} + end + + defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do + tags |> Notes.get_tags_string() + end + + defp get_value_for_key(:actions, note, %{actions: actions}) do + assigns = %{actions: actions, note: note} + + ~H""" +
+ <%= render_slot(@actions, @note) %> +
+ """ + end + + defp get_value_for_key(key, note, _additional_data), do: note |> Map.get(key) +end diff --git a/lib/memex_web/live/note_live/form_component.ex b/lib/memex_web/live/note_live/form_component.ex index 8a0f640..01833f5 100644 --- a/lib/memex_web/live/note_live/form_component.ex +++ b/lib/memex_web/live/note_live/form_component.ex @@ -4,8 +4,8 @@ defmodule MemexWeb.NoteLive.FormComponent do alias Memex.Notes @impl true - def update(%{note: note} = assigns, socket) do - changeset = Notes.change_note(note) + def update(%{note: note, current_user: current_user} = assigns, socket) do + changeset = Notes.change_note(note, current_user) {:ok, socket @@ -14,39 +14,51 @@ defmodule MemexWeb.NoteLive.FormComponent do end @impl true - def handle_event("validate", %{"note" => note_params}, socket) do + def handle_event( + "validate", + %{"note" => note_params}, + %{assigns: %{note: note, current_user: current_user}} = socket + ) do changeset = - socket.assigns.note - |> Notes.change_note(note_params) + note + |> Notes.change_note(note_params, current_user) |> Map.put(:action, :validate) {:noreply, assign(socket, :changeset, changeset)} end - def handle_event("save", %{"note" => note_params}, socket) do - save_note(socket, socket.assigns.action, note_params) + def handle_event("save", %{"note" => note_params}, %{assigns: %{action: action}} = socket) do + save_note(socket, action, note_params) end - defp save_note(socket, :edit, note_params) do - case Notes.update_note(socket.assigns.note, note_params) do - {:ok, _note} -> + defp save_note( + %{assigns: %{note: note, return_to: return_to, current_user: current_user}} = socket, + :edit, + note_params + ) do + case Notes.update_note(note, note_params, current_user) do + {:ok, %{title: title}} -> {:noreply, socket |> put_flash(:info, gettext("%{title} saved", title: title)) - |> push_navigate(to: socket.assigns.return_to)} + |> push_navigate(to: return_to)} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :changeset, changeset)} end end - defp save_note(socket, :new, note_params) do - case Notes.create_note(note_params) do - {:ok, _note} -> + defp save_note( + %{assigns: %{return_to: return_to, current_user: current_user}} = socket, + :new, + note_params + ) do + case Notes.create_note(note_params, current_user) do + {:ok, %{title: title}} -> {:noreply, socket |> put_flash(:info, gettext("%{title} created", title: title)) - |> push_navigate(to: socket.assigns.return_to)} + |> push_navigate(to: return_to)} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, 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 f3d3cb0..75b588d 100644 --- a/lib/memex_web/live/note_live/form_component.html.heex +++ b/lib/memex_web/live/note_live/form_component.html.heex @@ -1,6 +1,4 @@ -
-

<%= @title %>

- +
<.form :let={f} for={@changeset} @@ -8,27 +6,44 @@ phx-target={@myself} phx-change="validate" phx-submit="save" + phx-debounce="300" + class="flex flex-col justify-start items-stretch space-y-4" > - <%= label(f, :title) %> - <%= text_input(f, :title) %> + <%= text_input(f, :title, + class: "input input-primary", + placeholder: gettext("title") + ) %> <%= error_tag(f, :title) %> - <%= label(f, :content) %> - <%= textarea(f, :content) %> + <%= textarea(f, :content, + id: "note-form-content", + class: "input input-primary h-64 min-h-64", + phx_hook: "MaintainAttrs", + phx_update: "ignore", + placeholder: gettext("content") + ) %> <%= error_tag(f, :content) %> - <%= label(f, :tag) %> - <%= multiple_select(f, :tag, "Option 1": "option1", "Option 2": "option2") %> - <%= error_tag(f, :tag) %> - - <%= label(f, :visibility) %> - <%= select(f, :visibility, Ecto.Enum.values(Memex.Notes.Note, :visibility), - prompt: "Choose a value" + <%= text_input(f, :tags_string, + id: "tags-input", + class: "input input-primary", + placeholder: gettext("tag1,tag2"), + phx_update: "ignore", + value: Notes.get_tags_string(@changeset) ) %> - <%= error_tag(f, :visibility) %> + <%= error_tag(f, :tags_string) %> -
- <%= submit("Save", phx_disable_with: "Saving...") %> +
+ <%= select(f, :visibility, Ecto.Enum.values(Memex.Notes.Note, :visibility), + class: "grow input input-primary", + prompt: gettext("select privacy") + ) %> + + <%= submit(dgettext("actions", "save"), + phx_disable_with: gettext("saving..."), + class: "mx-auto btn btn-primary" + ) %>
+ <%= error_tag(f, :visibility) %>
diff --git a/lib/memex_web/live/note_live/index.ex b/lib/memex_web/live/note_live/index.ex index 548905e..706f804 100644 --- a/lib/memex_web/live/note_live/index.ex +++ b/lib/memex_web/live/note_live/index.ex @@ -1,45 +1,52 @@ defmodule MemexWeb.NoteLive.Index do use MemexWeb, :live_view - - alias Memex.Notes - alias Memex.Notes.Note + alias Memex.{Notes, Notes.Note} @impl true + def mount(_params, _session, %{assigns: %{current_user: current_user}} = socket) + when not (current_user |> is_nil()) do + {:ok, socket |> assign(notes: Notes.list_notes(current_user))} + end + def mount(_params, _session, socket) do - {:ok, assign(socket, :notes, list_notes())} + {:ok, socket |> assign(notes: Notes.list_public_notes())} end @impl true - def handle_params(params, _url, socket) do - {:noreply, apply_action(socket, socket.assigns.live_action, params)} + def handle_params(params, _url, %{assigns: %{live_action: live_action}} = socket) do + {:noreply, apply_action(socket, live_action, params)} end - defp apply_action(socket, :edit, %{"id" => id}) do + defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do + %{title: title} = note = Notes.get_note!(id, current_user) + socket |> assign(page_title: gettext("edit %{title}", title: title)) - |> assign(:note, Notes.get_note!(id)) + |> assign(note: note) end - defp apply_action(socket, :new, _params) do + defp apply_action(%{assigns: %{current_user: %{id: current_user_id}}} = socket, :new, _params) do socket |> assign(page_title: "new note") - |> assign(:note, %Note{}) + |> assign(note: %Note{user_id: current_user_id}) end defp apply_action(socket, :index, _params) do socket |> assign(page_title: "notes") - |> assign(:note, nil) + |> assign(note: nil) end @impl true - def handle_event("delete", %{"id" => id}, socket) do - note = Notes.get_note!(id) - {:ok, _} = Notes.delete_note(note) + def handle_event("delete", %{"id" => id}, %{assigns: %{current_user: current_user}} = socket) do + %{title: title} = note = Notes.get_note!(id, current_user) + {:ok, _} = Notes.delete_note(note, current_user) + socket = + socket + |> assign(notes: Notes.list_notes(current_user)) |> put_flash(:info, gettext("%{title} deleted", title: title)) - defp list_notes do - Notes.list_notes() + {:noreply, socket} end end diff --git a/lib/memex_web/live/note_live/index.html.heex b/lib/memex_web/live/note_live/index.html.heex index 19a6eab..ceb95e2 100644 --- a/lib/memex_web/live/note_live/index.html.heex +++ b/lib/memex_web/live/note_live/index.html.heex @@ -1,10 +1,54 @@ -

Listing Notes

+
+

+ <%= gettext("notes") %> +

+ + <%= if @notes |> Enum.empty?() do %> +

+ <%= gettext("no notes found") %> +

+ <% else %> + <.live_component + module={MemexWeb.Components.NotesTableComponent} + id="notes-index-table" + current_user={@current_user} + notes={@notes} + > + <:actions :let={note}> + <%= if @current_user do %> + <.link + patch={Routes.note_index_path(@socket, :edit, note)} + data-qa={"note-edit-#{note.id}"} + > + <%= dgettext("actions", "edit") %> + + <.link + href="#" + phx-click="delete" + phx-value-id={note.id} + data-confirm={dgettext("prompts", "are you sure?")} + data-qa={"delete-note-#{note.id}"} + > + <%= dgettext("actions", "delete") %> + + <% end %> + + + <% end %> + + <%= if @current_user do %> + <.link patch={Routes.note_index_path(@socket, :new)} class="self-end btn btn-primary"> + <%= dgettext("actions", "new note") %> + + <% end %> +
<%= if @live_action in [:new, :edit] do %> <.modal return_to={Routes.note_index_path(@socket, :index)}> <.live_component module={MemexWeb.NoteLive.FormComponent} id={@note.id || :new} + current_user={@current_user} title={@page_title} action={@live_action} note={@note} @@ -12,55 +56,3 @@ /> <% end %> - - - - - - - - - - - - - - <%= for note <- @notes do %> - - - - - - - - - <% end %> - -
TitleContentTagVisibility
<%= note.title %><%= note.content %><%= note.tag %><%= note.visibility %> - - <.link navigate={Routes.note_show_path(@socket, :show, note)}> - <%= dgettext("actions", "Show") %> - - - - <.link patch={Routes.note_index_path(@socket, :edit, note)}> - <%= dgettext("actions", "Edit") %> - - - - <.link - href="#" - phx-click="delete" - phx-value-id={note.id} - data-confirm={dgettext("prompts", "Are you sure?")} - > - <%= dgettext("actions", "Delete") %> - - -
- - - <.link patch={Routes.note_index_path(@socket, :new)}> - <%= dgettext("actions", "New Note") %> - - diff --git a/lib/memex_web/live/note_live/show.ex b/lib/memex_web/live/note_live/show.ex index 0854b1a..44d6f4b 100644 --- a/lib/memex_web/live/note_live/show.ex +++ b/lib/memex_web/live/note_live/show.ex @@ -9,11 +9,15 @@ defmodule MemexWeb.NoteLive.Show do end @impl true - def handle_params(%{"id" => id}, _, socket) do + def handle_params( + %{"id" => id}, + _, + %{assigns: %{live_action: live_action, current_user: current_user}} = socket + ) do {:noreply, socket - |> assign(:page_title, page_title(socket.assigns.live_action)) - |> assign(:note, Notes.get_note!(id))} + |> assign(:page_title, page_title(live_action)) + |> assign(:note, Notes.get_note!(id, current_user))} end defp page_title(:show), do: "show note" diff --git a/lib/memex_web/live/note_live/show.html.heex b/lib/memex_web/live/note_live/show.html.heex index fc5239b..8de70cf 100644 --- a/lib/memex_web/live/note_live/show.html.heex +++ b/lib/memex_web/live/note_live/show.html.heex @@ -1,10 +1,41 @@ -

Show Note

+
+

+ <%= @note.title %> +

+ +

<%= if @note.tags, do: @note.tags |> Enum.join(", ") %>

+ + + +

+ <%= gettext("Visibility: %{visibility}", visibility: @note.visibility) %> +

+ +
+ <.link class="btn btn-primary" patch={Routes.note_index_path(@socket, :index)}> + <%= dgettext("actions", "Back") %> + + <%= if @current_user do %> + <.link class="btn btn-primary" patch={Routes.note_show_path(@socket, :edit, @note)}> + <%= dgettext("actions", "edit") %> + + <% end %> +
+
<%= if @live_action in [:edit] do %> <.modal return_to={Routes.note_show_path(@socket, :show, @note)}> <.live_component module={MemexWeb.NoteLive.FormComponent} id={@note.id} + current_user={@current_user} title={@page_title} action={@live_action} note={@note} @@ -12,37 +43,3 @@ /> <% end %> - -
    -
  • - Title: - <%= @note.title %> -
  • - -
  • - Content: - <%= @note.content %> -
  • - -
  • - Tag: - <%= @note.tag %> -
  • - -
  • - Visibility: - <%= @note.visibility %> -
  • -
- - - <.link patch={Routes.note_show_path(@socket, :edit, @note)} class="button"> - <%= dgettext("actions", "Edit") %> - - -| - - <.link patch={Routes.note_index_path(@socket, :index)}> - <%= dgettext("actions", "Back") %> - - diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot index af28542..8ffe295 100644 --- a/priv/gettext/actions.pot +++ b/priv/gettext/actions.pot @@ -10,95 +10,141 @@ msgid "" msgstr "" +#: lib/memex_web/live/context_live/show.html.heex:46 +#: lib/memex_web/live/note_live/show.html.heex:23 +#: lib/memex_web/live/pipeline_live/show.html.heex:41 #, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:113 -msgid "Change Language" +msgid "Back" msgstr "" +#: lib/memex_web/live/invite_live/index.html.heex:30 #, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:15 -#: lib/memex_web/templates/user_settings/edit.html.heex:44 -msgid "Change email" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:131 -msgid "Change language" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:58 -#: lib/memex_web/templates/user_settings/edit.html.heex:99 -msgid "Change password" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:32 msgid "Copy to clipboard" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:16 -msgid "Create Invite" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:139 -msgid "Delete User" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/templates/user_registration/new.html.heex:51 #: lib/memex_web/templates/user_reset_password/new.html.heex:3 #: lib/memex_web/templates/user_session/new.html.heex:44 +#, elixir-autogen, elixir-format msgid "Forgot your password?" msgstr "" +#: lib/memex_web/templates/user_confirmation/new.html.heex:3 +#: lib/memex_web/templates/user_confirmation/new.html.heex:15 #, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:11 -msgid "Invite someone new!" +msgid "Resend confirmation instructions" msgstr "" +#: lib/memex_web/templates/user_reset_password/edit.html.heex:3 +#: lib/memex_web/templates/user_reset_password/edit.html.heex:33 #, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:119 +msgid "Reset password" +msgstr "" + +#: lib/memex_web/live/invite_live/form_component.html.heex:28 +#, elixir-autogen, elixir-format +msgid "Save" +msgstr "" + +#: lib/memex_web/templates/user_reset_password/new.html.heex:15 +#, elixir-autogen, elixir-format +msgid "Send instructions to reset password" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:15 +#: lib/memex_web/templates/user_settings/edit.html.heex:44 +#, elixir-autogen, elixir-format +msgid "change email" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:113 +#: lib/memex_web/templates/user_settings/edit.html.heex:131 +#, elixir-autogen, elixir-format +msgid "change language" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:58 +#: lib/memex_web/templates/user_settings/edit.html.heex:99 +#, elixir-autogen, elixir-format +msgid "change password" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:16 +#, elixir-autogen, elixir-format +msgid "create invite" +msgstr "" + +#: lib/memex_web/live/context_live/index.html.heex:53 +#: lib/memex_web/live/note_live/index.html.heex:32 +#: lib/memex_web/live/pipeline_live/index.html.heex:51 +#, elixir-autogen, elixir-format +msgid "delete" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:145 +#, elixir-autogen, elixir-format +msgid "delete user" +msgstr "" + +#: lib/memex_web/live/context_live/index.html.heex:43 +#: lib/memex_web/live/context_live/show.html.heex:40 +#: lib/memex_web/live/note_live/index.html.heex:23 +#: lib/memex_web/live/note_live/show.html.heex:27 +#: lib/memex_web/live/pipeline_live/index.html.heex:41 +#: lib/memex_web/live/pipeline_live/show.html.heex:35 +#, elixir-autogen, elixir-format +msgid "edit" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:12 +#, elixir-autogen, elixir-format +msgid "invite someone new!" +msgstr "" + +#: lib/memex_web/components/topbar.ex:125 #: lib/memex_web/templates/user_confirmation/new.html.heex:29 -#: lib/memex_web/templates/user_registration/new.html.heex:47 +#: lib/memex_web/templates/user_registration/new.html.heex:48 #: lib/memex_web/templates/user_reset_password/edit.html.heex:47 #: lib/memex_web/templates/user_reset_password/new.html.heex:29 #: lib/memex_web/templates/user_session/new.html.heex:3 #: lib/memex_web/templates/user_session/new.html.heex:32 -msgid "Log in" +#, elixir-autogen, elixir-format +msgid "log in" msgstr "" +#: lib/memex_web/live/context_live/index.html.heex:64 #, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:111 -#: lib/memex_web/templates/user_confirmation/new.html.heex:24 +msgid "new context" +msgstr "" + +#: lib/memex_web/live/note_live/index.html.heex:41 +#, elixir-autogen, elixir-format +msgid "new note" +msgstr "" + +#: lib/memex_web/live/pipeline_live/index.html.heex:62 +#, elixir-autogen, elixir-format +msgid "new pipeline" +msgstr "" + +#: lib/memex_web/components/topbar.ex:115 +#: lib/memex_web/templates/user_confirmation/new.html.heex:25 #: lib/memex_web/templates/user_registration/new.html.heex:3 #: lib/memex_web/templates/user_registration/new.html.heex:41 -#: lib/memex_web/templates/user_reset_password/edit.html.heex:42 -#: lib/memex_web/templates/user_reset_password/new.html.heex:24 -#: lib/memex_web/templates/user_session/new.html.heex:39 -msgid "Register" +#: lib/memex_web/templates/user_reset_password/edit.html.heex:43 +#: lib/memex_web/templates/user_reset_password/new.html.heex:25 +#: lib/memex_web/templates/user_session/new.html.heex:40 +#, elixir-autogen, elixir-format +msgid "register" msgstr "" +#: lib/memex_web/live/note_live/form_component.html.heex:42 #, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_confirmation/new.html.heex:3 -#: lib/memex_web/templates/user_confirmation/new.html.heex:15 -msgid "Resend confirmation instructions" +msgid "save" msgstr "" +#: lib/memex_web/live/context_live/index.html.heex:38 +#: lib/memex_web/live/pipeline_live/index.html.heex:36 #, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_reset_password/edit.html.heex:3 -#: lib/memex_web/templates/user_reset_password/edit.html.heex:33 -msgid "Reset password" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/form_component.html.heex:28 -msgid "Save" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_reset_password/new.html.heex:15 -msgid "Send instructions to reset password" +msgid "show" msgstr "" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index e30f34e..1f5cffe 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -10,297 +10,391 @@ msgid "" msgstr "" +#: lib/memex_web/live/note_live/form_component.ex:60 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:73 -msgid "Accessible from any internet-capable device" +msgid "%{title} created" msgstr "" +#: lib/memex_web/live/note_live/index.ex:48 +#, elixir-autogen, elixir-format +msgid "%{title} deleted" +msgstr "" + +#: lib/memex_web/live/note_live/form_component.ex:43 +#, elixir-autogen, elixir-format +msgid "%{title} saved" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:90 #, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:89 msgid "Admins" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:53 -msgid "Built with sharing and collaboration in mind" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:78 -msgid "Confirm new password" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_confirmation_controller.ex:8 +#, elixir-autogen, elixir-format msgid "Confirm your account" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:63 -msgid "Contexts" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:22 -msgid "Contexts:" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:70 -msgid "Convenient:" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:32 -#: lib/memex_web/templates/user_settings/edit.html.heex:87 -msgid "Current password" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:58 -msgid "Disable" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:15 -msgid "Document notes about individual items or concepts" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:35 -msgid "Document your processes, attaching contexts to each step" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.ex:33 -msgid "Edit Invite" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:62 -msgid "Enable" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/templates/user_registration/new.html.heex:36 -#: lib/memex_web/templates/user_settings/edit.html.heex:126 +#, elixir-autogen, elixir-format msgid "English" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:44 -msgid "Features" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_reset_password_controller.ex:9 +#, elixir-autogen, elixir-format msgid "Forgot your password?" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/home_live.ex:12 +#, elixir-autogen, elixir-format msgid "Home" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/components/invite_card.ex:25 -msgid "Invite Disabled" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:78 -#: lib/memex_web/live/invite_live/index.ex:41 -#: lib/memex_web/live/invite_live/index.html.heex:3 -msgid "Invites" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/templates/user_session/new.html.heex:27 +#, elixir-autogen, elixir-format msgid "Keep me logged in for 60 days" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/user_registration/new.html.heex:32 +#, elixir-autogen, elixir-format msgid "Language" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/layout/live.html.heex:37 +#, elixir-autogen, elixir-format msgid "Loading..." msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/controllers/user_session_controller.ex:8 -msgid "Log in" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:50 -msgid "Multi-user:" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/form_component.html.heex:20 +#, elixir-autogen, elixir-format msgid "Name" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.ex:37 -msgid "New Invite" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:71 -msgid "New password" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:8 -msgid "No invites 😔" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:70 -msgid "Notes" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:12 -msgid "Notes:" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:56 -msgid "Pipelines" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:32 -msgid "Pipelines:" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:63 -msgid "Privacy controls on a per-note, context or pipeline basis" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:60 -msgid "Privacy:" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:25 -msgid "Provide context around a single topic and hotlink to your notes" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/templates/layout/live.html.heex:50 +#, elixir-autogen, elixir-format msgid "Reconnecting..." msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/controllers/user_registration_controller.ex:35 -msgid "Register" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_reset_password_controller.ex:36 +#, elixir-autogen, elixir-format msgid "Reset your password" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:78 -msgid "Set Unlimited" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:10 -#: lib/memex_web/templates/user_settings/edit.html.heex:3 +#, elixir-autogen, elixir-format msgid "Settings" msgstr "" +#: lib/memex_web/components/user_card.ex:33 #, elixir-autogen, elixir-format -#: lib/memex_web/components/user_card.ex:30 msgid "User registered on" msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:118 -msgid "Users" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/components/invite_card.ex:20 +#, elixir-autogen, elixir-format msgid "Uses Left:" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/form_component.html.heex:24 +#, elixir-autogen, elixir-format msgid "Uses left" msgstr "" +#: lib/memex_web/live/note_live/show.html.heex:18 #, elixir-autogen, elixir-format +msgid "Visibility: %{visibility}" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:73 +#, elixir-autogen, elixir-format +msgid "accessible from any internet-capable device" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:87 +#, elixir-autogen, elixir-format +msgid "admins:" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:53 +#, elixir-autogen, elixir-format +msgid "built with sharing and collaboration in mind" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:78 +#, elixir-autogen, elixir-format +msgid "confirm new password" +msgstr "" + +#: lib/memex_web/components/notes_table_component.ex:49 +#: lib/memex_web/live/note_live/form_component.html.heex:23 +#, elixir-autogen, elixir-format +msgid "content" +msgstr "" + +#: lib/memex_web/components/topbar.ex:53 +#, elixir-autogen, elixir-format +msgid "contexts" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:22 +#, elixir-autogen, elixir-format +msgid "contexts:" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:70 +#, elixir-autogen, elixir-format +msgid "convenient:" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:32 +#: lib/memex_web/templates/user_settings/edit.html.heex:87 +#, elixir-autogen, elixir-format +msgid "current password" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:59 +#, elixir-autogen, elixir-format +msgid "disable" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:15 +#, elixir-autogen, elixir-format +msgid "document notes about individual items or concepts" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:35 +#, elixir-autogen, elixir-format +msgid "document your processes, attaching contexts to each step" +msgstr "" + +#: lib/memex_web/live/note_live/index.ex:24 +#, elixir-autogen, elixir-format +msgid "edit %{title}" +msgstr "" + +#: lib/memex_web/live/invite_live/index.ex:33 +#, elixir-autogen, elixir-format +msgid "edit invite" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:28 +#, elixir-autogen, elixir-format +msgid "email" +msgstr "" + +#: lib/memex_web/components/user_card.ex:23 +#, elixir-autogen, elixir-format +msgid "email unconfirmed" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:63 +#, elixir-autogen, elixir-format +msgid "enable" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:126 +#, elixir-autogen, elixir-format +msgid "english" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:44 +#, elixir-autogen, elixir-format +msgid "features" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:138 +#, elixir-autogen, elixir-format +msgid "get involved!" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:159 +#, elixir-autogen, elixir-format +msgid "help translate" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:82 +#, elixir-autogen, elixir-format +msgid "instance information" +msgstr "" + +#: lib/memex_web/components/invite_card.ex:25 +#, elixir-autogen, elixir-format +msgid "invite disabled" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:115 +#, elixir-autogen, elixir-format +msgid "invite only" +msgstr "" + +#: lib/memex_web/components/topbar.ex:74 +#: lib/memex_web/live/invite_live/index.ex:41 +#: lib/memex_web/live/invite_live/index.html.heex:3 +#, elixir-autogen, elixir-format +msgid "invites" +msgstr "" + +#: lib/memex_web/controllers/user_session_controller.ex:8 +#, elixir-autogen, elixir-format +msgid "log in" +msgstr "" + +#: lib/memex_web/components/topbar.ex:23 #: lib/memex_web/live/home_live.html.heex:3 +#: lib/memex_web/templates/layout/root.html.heex:8 +#: lib/memex_web/templates/layout/root.html.heex:9 +#, elixir-autogen, elixir-format msgid "memex" msgstr "" +#: lib/memex_web/live/home_live.html.heex:50 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:87 -msgid "Admins:" +msgid "multi-user:" msgstr "" +#: lib/memex_web/live/invite_live/index.ex:37 #, elixir-autogen, elixir-format -#: lib/memex_web/live/note_live/form_component.html.heex:20 -msgid "Content" +msgid "new invite" msgstr "" +#: lib/memex_web/templates/user_settings/edit.html.heex:71 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:134 -msgid "Get involved!" +msgid "new password" msgstr "" +#: lib/memex_web/live/invite_live/index.html.heex:8 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:151 -msgid "Help translate" +msgid "no invites 😔" msgstr "" +#: lib/memex_web/live/note_live/index.html.heex:8 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:82 -msgid "Instance Information" +msgid "no notes found" msgstr "" +#: lib/memex_web/components/topbar.ex:44 +#: lib/memex_web/live/note_live/index.html.heex:3 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:113 -msgid "Invite Only" +msgid "notes" msgstr "" +#: lib/memex_web/live/home_live.html.heex:12 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:112 -msgid "Public Signups" +msgid "notes:" msgstr "" +#: lib/memex_web/components/topbar.ex:62 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:160 -msgid "Report bugs or request features" +msgid "pipelines" msgstr "" +#: lib/memex_web/live/home_live.html.heex:32 #, elixir-autogen, elixir-format -#: lib/memex_web/live/note_live/form_component.html.heex:35 -msgid "Save" +msgid "pipelines:" msgstr "" +#: lib/memex_web/live/home_live.html.heex:63 #, elixir-autogen, elixir-format -#: lib/memex_web/live/note_live/form_component.html.heex:36 -msgid "Saving..." +msgid "privacy controls on a per-note, context or pipeline basis" msgstr "" +#: lib/memex_web/live/home_live.html.heex:60 #, elixir-autogen, elixir-format -#: lib/memex_web/live/note_live/form_component.html.heex:13 -msgid "Title" +msgid "privacy:" msgstr "" +#: lib/memex_web/live/home_live.html.heex:25 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:142 -msgid "View the source code" +msgid "provide context around a single topic and hotlink to your notes" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:114 +#, elixir-autogen, elixir-format +msgid "public signups" +msgstr "" + +#: lib/memex_web/controllers/user_registration_controller.ex:35 +#, elixir-autogen, elixir-format +msgid "register" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:110 +#, elixir-autogen, elixir-format +msgid "registration:" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:170 +#, elixir-autogen, elixir-format +msgid "report bugs or request features" +msgstr "" + +#: lib/memex_web/live/note_live/form_component.html.heex:43 +#, elixir-autogen, elixir-format +msgid "saving..." +msgstr "" + +#: lib/memex_web/live/note_live/form_component.html.heex:39 +#, elixir-autogen, elixir-format +msgid "select privacy" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:79 +#, elixir-autogen, elixir-format +msgid "set unlimited" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:3 +#, elixir-autogen, elixir-format +msgid "settings" +msgstr "" + +#: lib/memex_web/live/note_live/form_component.html.heex:30 +#, elixir-autogen, elixir-format +msgid "tag1,tag2" +msgstr "" + +#: lib/memex_web/components/notes_table_component.ex:50 +#, elixir-autogen, elixir-format +msgid "tags" +msgstr "" + +#: lib/memex_web/components/notes_table_component.ex:48 +#: lib/memex_web/live/note_live/form_component.html.heex:14 +#, elixir-autogen, elixir-format +msgid "title" +msgstr "" + +#: lib/memex_web/components/invite_card.ex:21 +#, elixir-autogen, elixir-format +msgid "unlimited" +msgstr "" + +#: lib/memex_web/components/user_card.ex:25 +#, elixir-autogen, elixir-format +msgid "user was confirmed at %{relative_datetime}" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:120 +#, elixir-autogen, elixir-format +msgid "users" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:121 +#, elixir-autogen, elixir-format +msgid "version:" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:148 +#, elixir-autogen, elixir-format +msgid "view the source code" +msgstr "" + +#: lib/memex_web/components/notes_table_component.ex:51 +#, elixir-autogen, elixir-format +msgid "visibility" +msgstr "" + +#: lib/memex_web/components/note_card.ex:18 +#, elixir-autogen, elixir-format +msgid "visibility: %{visibility}" msgstr "" diff --git a/priv/gettext/emails.pot b/priv/gettext/emails.pot index e9c08c0..5eae8ec 100644 --- a/priv/gettext/emails.pot +++ b/priv/gettext/emails.pot @@ -10,83 +10,83 @@ msgid "" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/email.ex:30 +#, elixir-autogen, elixir-format msgid "Confirm your Memex account" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/confirm_email.html.heex:3 #: lib/memex_web/templates/email/confirm_email.txt.eex:2 #: lib/memex_web/templates/email/reset_password.html.heex:3 #: lib/memex_web/templates/email/reset_password.txt.eex:2 #: lib/memex_web/templates/email/update_email.html.heex:3 #: lib/memex_web/templates/email/update_email.txt.eex:2 +#, elixir-autogen, elixir-format msgid "Hi %{email}," msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/confirm_email.txt.eex:10 +#, elixir-autogen, elixir-format msgid "If you didn't create an account at %{url}, please ignore this." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/confirm_email.html.heex:22 +#, elixir-autogen, elixir-format msgid "If you didn't create an account at Memex, please ignore this." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/reset_password.txt.eex:8 #: lib/memex_web/templates/email/update_email.txt.eex:8 +#, elixir-autogen, elixir-format msgid "If you didn't request this change from %{url}, please ignore this." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/reset_password.html.heex:16 #: lib/memex_web/templates/email/update_email.html.heex:16 +#, elixir-autogen, elixir-format msgid "If you didn't request this change from Memex, please ignore this." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/email.ex:37 +#, elixir-autogen, elixir-format msgid "Reset your Memex password" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/layout/email.txt.eex:9 +#, elixir-autogen, elixir-format msgid "This email was sent from Memex at %{url}, the self-hosted firearm tracker website." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/layout/email.html.heex:13 +#, elixir-autogen, elixir-format msgid "This email was sent from Memex, the self-hosted firearm tracker website." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/email.ex:44 +#, elixir-autogen, elixir-format msgid "Update your Memex email" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/confirm_email.html.heex:9 #: lib/memex_web/templates/email/confirm_email.txt.eex:4 +#, elixir-autogen, elixir-format msgid "Welcome to Memex" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/update_email.html.heex:8 #: lib/memex_web/templates/email/update_email.txt.eex:4 +#, elixir-autogen, elixir-format msgid "You can change your email by visiting the URL below:" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/confirm_email.html.heex:14 #: lib/memex_web/templates/email/confirm_email.txt.eex:6 +#, elixir-autogen, elixir-format msgid "You can confirm your account by visiting the URL below:" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/email/reset_password.html.heex:8 #: lib/memex_web/templates/email/reset_password.txt.eex:4 +#, elixir-autogen, elixir-format msgid "You can reset your password by visiting the URL below:" msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 060610a..d31e70d 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -10,109 +10,113 @@ msgid "" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:84 +#, elixir-autogen, elixir-format msgid "Email change link is invalid or it has expired." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/error/error.html.heex:8 +#, elixir-autogen, elixir-format msgid "Error" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/templates/error/error.html.heex:28 +#, elixir-autogen, elixir-format msgid "Go back home" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/views/error_view.ex:11 +#, elixir-autogen, elixir-format msgid "Internal Server Error" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_session_controller.ex:17 +#, elixir-autogen, elixir-format msgid "Invalid email or password" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/views/error_view.ex:9 +#, elixir-autogen, elixir-format msgid "Not found" msgstr "" -#, elixir-autogen, elixir-format #: 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:21 #: lib/memex_web/templates/user_settings/edit.html.heex:64 -#: lib/memex_web/templates/user_settings/edit.html.heex:119 +#, elixir-autogen, elixir-format msgid "Oops, something went wrong! Please check the errors below." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_reset_password_controller.ex:63 +#, elixir-autogen, elixir-format msgid "Reset password link is invalid or it has expired." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_registration_controller.ex:25 #: lib/memex_web/controllers/user_registration_controller.ex:56 +#, elixir-autogen, elixir-format msgid "Sorry, public registration is disabled" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_registration_controller.ex:15 #: lib/memex_web/controllers/user_registration_controller.ex:46 +#, elixir-autogen, elixir-format msgid "Sorry, this invite was not found or expired" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:99 +#, elixir-autogen, elixir-format msgid "Unable to delete user" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/views/error_view.ex:10 +#, elixir-autogen, elixir-format msgid "Unauthorized" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_confirmation_controller.ex:54 +#, elixir-autogen, elixir-format msgid "User confirmation link is invalid or it has expired." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:18 +#, elixir-autogen, elixir-format msgid "You are not authorized to view this page" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_auth.ex:177 +#, elixir-autogen, elixir-format msgid "You are not authorized to view this page." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_auth.ex:39 #: lib/memex_web/controllers/user_auth.ex:161 +#, elixir-autogen, elixir-format msgid "You must confirm your account and log in to access this page." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/user.ex:130 +#, elixir-autogen, elixir-format msgid "did not change" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/user.ex:151 +#, elixir-autogen, elixir-format msgid "does not match password" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/user.ex:188 +#, elixir-autogen, elixir-format msgid "is not valid" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex/accounts/user.ex:84 +#, elixir-autogen, elixir-format msgid "must have the @ sign and no spaces" msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:21 +#: lib/memex_web/templates/user_settings/edit.html.heex:119 +#, elixir-autogen, elixir-format +msgid "oops, something went wrong! Please check the errors below" +msgstr "" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index 3df080b..f3b1669 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -10,138 +10,145 @@ msgid "" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_confirmation_controller.ex:38 +#, elixir-autogen, elixir-format msgid "%{email} confirmed successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/form_component.ex:62 +#, elixir-autogen, elixir-format msgid "%{invite_name} created successfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:53 +#, elixir-autogen, elixir-format msgid "%{invite_name} deleted succesfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:114 +#, elixir-autogen, elixir-format msgid "%{invite_name} disabled succesfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:90 +#, elixir-autogen, elixir-format msgid "%{invite_name} enabled succesfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:68 +#, elixir-autogen, elixir-format msgid "%{invite_name} updated succesfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/form_component.ex:42 +#, elixir-autogen, elixir-format msgid "%{invite_name} updated successfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:139 +#, elixir-autogen, elixir-format msgid "%{user_email} deleted succesfully" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:29 +#, elixir-autogen, elixir-format msgid "A link to confirm your email change has been sent to the new address." msgstr "" -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:133 -msgid "Are you sure you want to change your language?" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:101 -#: lib/memex_web/live/invite_live/index.html.heex:130 -msgid "Are you sure you want to delete %{email}? This action is permanent!" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:48 -msgid "Are you sure you want to delete the invite for %{invite_name}?" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/templates/user_settings/edit.html.heex:143 -msgid "Are you sure you want to delete your account?" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/components/topbar.ex:95 -msgid "Are you sure you want to log out?" -msgstr "" - -#, elixir-autogen, elixir-format -#: lib/memex_web/live/invite_live/index.html.heex:73 -msgid "Are you sure you want to make %{invite_name} unlimited?" -msgstr "" - -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/index.ex:127 +#, elixir-autogen, elixir-format msgid "Copied to clipboard" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:77 +#, elixir-autogen, elixir-format msgid "Email changed successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_confirmation_controller.ex:23 +#, elixir-autogen, elixir-format msgid "If your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_reset_password_controller.ex:24 +#, elixir-autogen, elixir-format msgid "If your email is in our system, you will receive instructions to reset your password shortly." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:65 +#, elixir-autogen, elixir-format msgid "Language updated successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_session_controller.ex:23 +#, elixir-autogen, elixir-format msgid "Logged out successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_reset_password_controller.ex:46 +#, elixir-autogen, elixir-format msgid "Password reset successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:49 +#, elixir-autogen, elixir-format msgid "Password updated successfully." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_registration_controller.ex:74 +#, elixir-autogen, elixir-format msgid "Please check your email to verify your account" msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/live/invite_live/form_component.html.heex:30 +#, elixir-autogen, elixir-format msgid "Saving..." msgstr "" -#, elixir-autogen, elixir-format #: lib/memex_web/controllers/user_settings_controller.ex:95 +#, elixir-autogen, elixir-format msgid "Your account has been deleted" msgstr "" +#: lib/memex_web/templates/user_settings/edit.html.heex:133 #, elixir-autogen, elixir-format -#: lib/memex_web/live/home_live.html.heex:91 -msgid "Register to setup %{name}" +msgid "are you sure you want to change your language?" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:102 +#: lib/memex_web/live/invite_live/index.html.heex:132 +#, elixir-autogen, elixir-format +msgid "are you sure you want to delete %{email}? This action is permanent!" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:48 +#, elixir-autogen, elixir-format +msgid "are you sure you want to delete the invite for %{invite_name}?" +msgstr "" + +#: lib/memex_web/templates/user_settings/edit.html.heex:143 +#, elixir-autogen, elixir-format +msgid "are you sure you want to delete your account?" +msgstr "" + +#: lib/memex_web/components/topbar.ex:92 +#, elixir-autogen, elixir-format +msgid "are you sure you want to log out?" +msgstr "" + +#: lib/memex_web/live/invite_live/index.html.heex:74 +#, elixir-autogen, elixir-format +msgid "are you sure you want to make %{invite_name} unlimited?" +msgstr "" + +#: lib/memex_web/live/context_live/index.html.heex:51 +#: lib/memex_web/live/note_live/index.html.heex:29 +#: lib/memex_web/live/pipeline_live/index.html.heex:49 +#, elixir-autogen, elixir-format +msgid "are you sure?" +msgstr "" + +#: lib/memex_web/live/home_live.html.heex:95 +#, elixir-autogen, elixir-format +msgid "register to setup %{name}" msgstr "" diff --git a/priv/repo/migrations/20220726000552_create_notes.exs b/priv/repo/migrations/20220726000552_create_notes.exs index 8c6495a..1e4e0c6 100644 --- a/priv/repo/migrations/20220726000552_create_notes.exs +++ b/priv/repo/migrations/20220726000552_create_notes.exs @@ -6,9 +6,11 @@ defmodule Memex.Repo.Migrations.CreateNotes do add :id, :binary_id, primary_key: true add :title, :string add :content, :text - add :tag, {:array, :string} + add :tags, {:array, :string} add :visibility, :string + add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) + timestamps() end end diff --git a/test/memex/notes_test.exs b/test/memex/notes_test.exs index 4b9ea29..bbb2663 100644 --- a/test/memex/notes_test.exs +++ b/test/memex/notes_test.exs @@ -1,71 +1,113 @@ defmodule Memex.NotesTest do use Memex.DataCase - - alias Memex.Notes + import Memex.NotesFixtures + alias Memex.{Notes, Notes.Note} + @moduletag :notes_test + @invalid_attrs %{content: nil, tag: nil, title: nil, visibility: nil} describe "notes" do - alias Memex.Notes.Note - - import Memex.NotesFixtures - - @invalid_attrs %{content: nil, tag: nil, title: nil, visibility: nil} - - test "list_notes/0 returns all notes" do - note = note_fixture() - assert Notes.list_notes() == [note] + setup do + [user: user_fixture()] end - test "get_note!/1 returns the note with given id" do - note = note_fixture() - assert Notes.get_note!(note.id) == note + 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) + assert Notes.list_notes(user) == [note_a, note_b, note_c] end - test "create_note/1 with valid data creates a note" do - valid_attrs = %{content: "some content", tag: [], title: "some title", visibility: :public} + test "list_public_notes/0 returns public notes", %{user: user} do + public_note = note_fixture(%{visibility: :public}, user) + note_fixture(%{visibility: :unlisted}, user) + note_fixture(%{visibility: :private}, user) + assert Notes.list_public_notes() == [public_note] + end - assert {:ok, %Note{} = note} = Notes.create_note(valid_attrs) + test "get_note!/1 returns the note with given id", %{user: user} do + note = note_fixture(%{visibility: :public}, user) + assert Notes.get_note!(note.id, user) == note + + note = note_fixture(%{visibility: :unlisted}, user) + assert Notes.get_note!(note.id, user) == note + + note = note_fixture(%{visibility: :private}, user) + assert Notes.get_note!(note.id, user) == note + end + + test "get_note!/1 only returns unlisted or public notes for other users", %{user: user} do + another_user = user_fixture() + note = note_fixture(%{visibility: :public}, another_user) + assert Notes.get_note!(note.id, user) == note + + note = note_fixture(%{visibility: :unlisted}, another_user) + assert Notes.get_note!(note.id, user) == note + + note = note_fixture(%{visibility: :private}, another_user) + + assert_raise Ecto.NoResultsError, fn -> + Notes.get_note!(note.id, user) + end + 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", + "visibility" => :public + } + + assert {:ok, %Note{} = note} = Notes.create_note(valid_attrs, user) assert note.content == "some content" - assert note.tag == [] + assert note.tags == ["tag1", "tag2"] assert note.title == "some title" assert note.visibility == :public end - test "create_note/1 with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = Notes.create_note(@invalid_attrs) + test "create_note/1 with invalid data returns error changeset", %{user: user} do + assert {:error, %Ecto.Changeset{}} = Notes.create_note(@invalid_attrs, user) end - test "update_note/2 with valid data updates the note" do - note = note_fixture() + test "update_note/2 with valid data updates the note", %{user: user} do + note = note_fixture(user) update_attrs = %{ - content: "some updated content", - tag: [], - title: "some updated title", - visibility: :private + "content" => "some updated content", + "tags_string" => "tag1,tag2", + "title" => "some updated title", + "visibility" => :private } - assert {:ok, %Note{} = note} = Notes.update_note(note, update_attrs) + assert {:ok, %Note{} = note} = Notes.update_note(note, update_attrs, user) assert note.content == "some updated content" - assert note.tag == [] + assert note.tags == ["tag1", "tag2"] assert note.title == "some updated title" assert note.visibility == :private end - test "update_note/2 with invalid data returns error changeset" do - note = note_fixture() - assert {:error, %Ecto.Changeset{}} = Notes.update_note(note, @invalid_attrs) - assert note == Notes.get_note!(note.id) + test "update_note/2 with invalid data returns error changeset", %{user: user} do + note = note_fixture(user) + assert {:error, %Ecto.Changeset{}} = Notes.update_note(note, @invalid_attrs, user) + assert note == Notes.get_note!(note.id, user) end - test "delete_note/1 deletes the note" do - note = note_fixture() - assert {:ok, %Note{}} = Notes.delete_note(note) - assert_raise Ecto.NoResultsError, fn -> Notes.get_note!(note.id) end + test "delete_note/1 deletes the note", %{user: user} do + note = note_fixture(user) + assert {:ok, %Note{}} = Notes.delete_note(note, user) + assert_raise Ecto.NoResultsError, fn -> Notes.get_note!(note.id, user) end end - test "change_note/1 returns a note changeset" do - note = note_fixture() - assert %Ecto.Changeset{} = Notes.change_note(note) + test "delete_note/1 deletes the note for an admin user", %{user: user} do + admin_user = admin_fixture() + note = note_fixture(user) + assert {:ok, %Note{}} = Notes.delete_note(note, admin_user) + assert_raise Ecto.NoResultsError, fn -> Notes.get_note!(note.id, user) end + end + + test "change_note/1 returns a note changeset", %{user: user} do + note = note_fixture(user) + assert %Ecto.Changeset{} = Notes.change_note(note, user) end end end diff --git a/test/memex_web/live/context_live_test.exs b/test/memex_web/live/context_live_test.exs index 3529d75..2522147 100644 --- a/test/memex_web/live/context_live_test.exs +++ b/test/memex_web/live/context_live_test.exs @@ -4,14 +4,24 @@ defmodule MemexWeb.ContextLiveTest do import Phoenix.LiveViewTest import Memex.ContextsFixtures - @create_attrs %{content: "some content", tag: [], title: "some title", visibility: :public} - @update_attrs %{ - content: "some updated content", - tag: [], - title: "some updated title", - visibility: :private + @create_attrs %{ + "content" => "some content", + "tags_string" => "tag1", + "title" => "some title", + "visibility" => :public + } + @update_attrs %{ + "content" => "some updated content", + "tags_string" => "tag1,tag2", + "title" => "some updated title", + "visibility" => :private + } + @invalid_attrs %{ + "content" => nil, + "tags_string" => "", + "title" => nil, + "visibility" => nil } - @invalid_attrs %{content: nil, tag: [], title: nil, visibility: nil} defp create_context(_) do context = context_fixture() diff --git a/test/memex_web/live/note_live_test.exs b/test/memex_web/live/note_live_test.exs index 63bf0ee..7b70a57 100644 --- a/test/memex_web/live/note_live_test.exs +++ b/test/memex_web/live/note_live_test.exs @@ -4,22 +4,31 @@ defmodule MemexWeb.NoteLiveTest do import Phoenix.LiveViewTest import Memex.NotesFixtures - @create_attrs %{content: "some content", tag: [], title: "some title", visibility: :public} - @update_attrs %{ - content: "some updated content", - tag: [], - title: "some updated title", - visibility: :private + @create_attrs %{ + "content" => "some content", + "tags_string" => "tag1", + "title" => "some title", + "visibility" => :public + } + @update_attrs %{ + "content" => "some updated content", + "tags_string" => "tag1,tag2", + "title" => "some updated title", + "visibility" => :private + } + @invalid_attrs %{ + "content" => nil, + "tags_string" => "", + "title" => nil, + "visibility" => nil } - @invalid_attrs %{content: nil, tag: [], title: nil, visibility: nil} - defp create_note(_) do - note = note_fixture() - %{note: note} + defp create_note(%{user: user}) do + [note: note_fixture(user)] end describe "Index" do - setup [:create_note] + setup [:register_and_log_in_user, :create_note] test "lists all notes", %{conn: conn, note: note} do {:ok, _index_live, html} = live(conn, Routes.note_index_path(conn, :index)) @@ -53,7 +62,7 @@ defmodule MemexWeb.NoteLiveTest do test "updates note in listing", %{conn: conn, note: note} do {:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index)) - assert index_live |> element("#note-#{note.id} a", "Edit") |> render_click() =~ + assert index_live |> element("[data-qa=\"note-edit-#{note.id}\"]") |> render_click() =~ "edit" assert_patch(index_live, Routes.note_index_path(conn, :edit, note)) @@ -75,7 +84,7 @@ defmodule MemexWeb.NoteLiveTest do test "deletes note in listing", %{conn: conn, note: note} do {:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index)) - assert index_live |> element("#note-#{note.id} a", "Delete") |> render_click() + assert index_live |> element("[data-qa=\"delete-note-#{note.id}\"]") |> render_click() refute has_element?(index_live, "#note-#{note.id}") end end diff --git a/test/support/fixtures/notes_fixtures.ex b/test/support/fixtures/notes_fixtures.ex index 6548cc3..ee3266b 100644 --- a/test/support/fixtures/notes_fixtures.ex +++ b/test/support/fixtures/notes_fixtures.ex @@ -3,20 +3,23 @@ defmodule Memex.NotesFixtures do This module defines test helpers for creating entities via the `Memex.Notes` context. """ + alias Memex.{Accounts.User, Notes, Notes.Note} @doc """ Generate a note. """ - def note_fixture(attrs \\ %{}) do + @spec note_fixture(User.t()) :: Note.t() + @spec note_fixture(attrs :: map(), User.t()) :: Note.t() + def note_fixture(attrs \\ %{}, user) do {:ok, note} = attrs |> Enum.into(%{ content: "some content", tag: [], title: "some title", - visibility: :public + visibility: :private }) - |> Memex.Notes.create_note() + |> Notes.create_note(user) note end