diff --git a/lib/cannery/accounts/email_worker.ex b/lib/cannery/accounts/email_worker.ex index bee0b4b5..d8e52a0c 100644 --- a/lib/cannery/accounts/email_worker.ex +++ b/lib/cannery/accounts/email_worker.ex @@ -4,7 +4,7 @@ defmodule Cannery.EmailWorker do """ use Oban.Worker, queue: :mailers - alias Cannery.{Accounts, Mailer, Email} + alias Cannery.{Accounts, Email, Mailer} @impl Oban.Worker def perform(%Oban.Job{args: %{"email" => email, "user_id" => user_id, "attrs" => attrs}}) do diff --git a/lib/cannery/containers.ex b/lib/cannery/containers.ex index ae22543d..08827e31 100644 --- a/lib/cannery/containers.ex +++ b/lib/cannery/containers.ex @@ -184,8 +184,7 @@ defmodule Cannery.Containers do Repo.delete_all( from ct in ContainerTag, where: ct.container_id == ^container_id, - where: ct.tag_id == ^tag_id, - where: ct.user_id == ^user_id + where: ct.tag_id == ^tag_id ) if count == 0, do: raise("could not delete container tag"), else: count diff --git a/lib/cannery/containers/container.ex b/lib/cannery/containers/container.ex index 8b3f0c51..5d4fe3a7 100644 --- a/lib/cannery/containers/container.ex +++ b/lib/cannery/containers/container.ex @@ -6,7 +6,8 @@ defmodule Cannery.Containers.Container do use Ecto.Schema import Ecto.Changeset alias Ecto.{Changeset, UUID} - alias Cannery.{Accounts.User, Ammo.AmmoGroup, Containers.Container} + alias Cannery.Containers.{Container, ContainerTag} + alias Cannery.{Accounts.User, Ammo.AmmoGroup, Tags.Tag} @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id @@ -19,6 +20,7 @@ defmodule Cannery.Containers.Container do belongs_to :user, User has_many :ammo_groups, AmmoGroup + many_to_many :tags, Tag, join_through: ContainerTag timestamps() end @@ -32,6 +34,7 @@ defmodule Cannery.Containers.Container do user: User.t(), user_id: User.id(), ammo_groups: [AmmoGroup.t()] | nil, + tags: [Tag.t()] | nil, inserted_at: NaiveDateTime.t(), updated_at: NaiveDateTime.t() } diff --git a/lib/cannery/tags.ex b/lib/cannery/tags.ex index a99ba800..4b6a9c0d 100644 --- a/lib/cannery/tags.ex +++ b/lib/cannery/tags.ex @@ -4,6 +4,7 @@ defmodule Cannery.Tags do """ import Ecto.Query, warn: false + import CanneryWeb.Gettext alias Cannery.{Accounts.User, Repo, Tags.Tag} alias Ecto.Changeset @@ -22,6 +23,27 @@ defmodule Cannery.Tags do @doc """ Gets a single tag. + ## Examples + + iex> get_tag(123, %User{id: 123}) + {:ok, %Tag{}} + + iex> get_tag(456, %User{id: 123}) + {:error, "tag not found"} + + """ + @spec get_tag(Tag.id(), User.t()) :: {:ok, Tag.t()} | {:error, String.t()} + def get_tag(id, %User{id: user_id}) do + Repo.one(from t in Tag, where: t.id == ^id and t.user_id == ^user_id) + |> case do + nil -> {:error, dgettext("errors", "Tag not found")} + tag -> {:ok, tag} + end + end + + @doc """ + Gets a single tag. + Raises `Ecto.NoResultsError` if the Tag does not exist. ## Examples diff --git a/lib/cannery_web/live/container_live/add_tag_component.ex b/lib/cannery_web/live/container_live/add_tag_component.ex new file mode 100644 index 00000000..6cd43cf6 --- /dev/null +++ b/lib/cannery_web/live/container_live/add_tag_component.ex @@ -0,0 +1,79 @@ +defmodule CanneryWeb.ContainerLive.AddTagComponent do + @moduledoc """ + Livecomponent that can add a tag to a Container + """ + + use CanneryWeb, :live_component + alias Cannery.{Accounts.User, Containers, Containers.Container, Tags, Tags.Tag} + alias Phoenix.LiveView.Socket + + @impl true + @spec update( + %{:container => Container.t(), :current_user => User.t(), optional(any) => any}, + Socket.t() + ) :: {:ok, Socket.t()} + def update(%{container: _container, current_user: current_user} = assigns, socket) do + {:ok, socket |> assign(assigns) |> assign(:tags, Tags.list_tags(current_user))} + end + + @impl true + def handle_event( + "save", + %{"tag" => %{"tag_id" => tag_id}}, + %{ + assigns: %{ + tags: tags, + container: container, + current_user: current_user, + return_to: return_to + } + } = socket + ) do + socket = + case tags |> Enum.find(fn %{id: id} -> tag_id == id end) do + nil -> + prompt = dgettext("errors", "Tag could not be added") + socket |> put_flash(:error, prompt) + + %{name: tag_name} = tag -> + _container_tag = Containers.add_tag!(container, tag, current_user) + prompt = dgettext("prompts", "%{name} added successfully", name: tag_name) + socket |> put_flash(:info, prompt) |> push_redirect(to: return_to) + end + + {:noreply, socket} + end + + @impl true + def render(assigns) do + ~H""" +
<%= if @container.ammo_groups |> Enum.empty?() do %> @@ -50,14 +89,26 @@ <% end %> <% end %>
- - <%= if @live_action in [:edit] do %> - <%= live_modal(CanneryWeb.ContainerLive.FormComponent, - id: @container.id, - title: @page_title, - action: @live_action, - container: @container, - return_to: Routes.container_show_path(@socket, :show, @container) - ) %> - <% end %> + +<%= if @live_action in [:edit] do %> + <%= live_modal(CanneryWeb.ContainerLive.FormComponent, + id: @container.id, + title: @page_title, + action: @live_action, + container: @container, + return_to: Routes.container_show_path(Endpoint, :show, @container), + current_user: @current_user + ) %> +<% end %> + +<%= if @live_action == :add_tag do %> + <%= live_modal(CanneryWeb.ContainerLive.AddTagComponent, + id: @container.id, + title: @page_title, + action: @live_action, + container: @container, + return_to: Routes.container_show_path(Endpoint, :show, @container), + current_user: @current_user + ) %> +<% end %> diff --git a/lib/cannery_web/router.ex b/lib/cannery_web/router.ex index f56014e3..f1f4dc7f 100644 --- a/lib/cannery_web/router.ex +++ b/lib/cannery_web/router.ex @@ -67,6 +67,7 @@ defmodule CanneryWeb.Router do live "/containers/:id", ContainerLive.Show, :show live "/containers/:id/show/edit", ContainerLive.Show, :edit + live "/containers/:id/show/add_tag", ContainerLive.Show, :add_tag live "/ammo_groups", AmmoGroupLive.Index, :index live "/ammo_groups/new", AmmoGroupLive.Index, :new diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot index 0283e4d5..a476a759 100644 --- a/priv/gettext/actions.pot +++ b/priv/gettext/actions.pot @@ -143,3 +143,13 @@ msgstr "" #: lib/cannery_web/live/ammo_group_live/index.html.heex:56 msgid "View" msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/show.html.heex:50 +msgid "Why not add one?" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/add_tag_component.ex:66 +msgid "Add" +msgstr "" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index ab8916ba..4c94dc2b 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -160,7 +160,7 @@ msgstr "" #, elixir-format, ex-autogen #: lib/cannery_web/live/container_live/index.ex:23 -#: lib/cannery_web/live/container_live/show.ex:67 +#: lib/cannery_web/live/container_live/show.ex:89 msgid "Edit Container" msgstr "" @@ -347,7 +347,7 @@ msgid "No ammo for this type" msgstr "" #, elixir-format, ex-autogen -#: lib/cannery_web/live/container_live/show.html.heex:46 +#: lib/cannery_web/live/container_live/show.html.heex:85 msgid "No ammo groups in this container" msgstr "" @@ -456,7 +456,7 @@ msgid "Show Ammo type" msgstr "" #, elixir-format, ex-autogen -#: lib/cannery_web/live/container_live/show.ex:66 +#: lib/cannery_web/live/container_live/show.ex:88 msgid "Show Container" msgstr "" @@ -482,6 +482,7 @@ msgstr "" #, elixir-format, ex-autogen #: lib/cannery_web/components/topbar.ex:35 +#: lib/cannery_web/live/container_live/show.html.heex:57 msgid "Tags" msgstr "" @@ -546,3 +547,13 @@ msgstr "" #: lib/cannery_web/live/home_live.ex:67 msgid "Your data stays with you, period" msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/show.ex:90 +msgid "Add Tag to Container" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/show.html.heex:47 +msgid "No tags for this container" +msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 37bba7b2..53548367 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -17,7 +17,7 @@ msgstr "" #, elixir-format, ex-autogen #: lib/cannery_web/live/container_live/index.ex:54 -#: lib/cannery_web/live/container_live/show.ex:52 +#: lib/cannery_web/live/container_live/show.ex:74 msgid "Could not delete %{name}: %{error}" msgstr "" @@ -130,3 +130,13 @@ msgstr "" #: lib/cannery/accounts/user.ex:82 msgid "must have the @ sign and no spaces" msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery/tags.ex:39 +msgid "Tag not found" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/add_tag_component.ex:35 +msgid "Tag could not be added" +msgstr "" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index ace431f1..7bc6dc35 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -39,7 +39,7 @@ msgstr "" #, elixir-format, ex-autogen #: lib/cannery_web/live/container_live/index.ex:47 -#: lib/cannery_web/live/container_live/show.ex:42 +#: lib/cannery_web/live/container_live/show.ex:64 msgid "%{name} has been deleted" msgstr "" @@ -177,3 +177,23 @@ msgstr "" #: lib/cannery_web/controllers/user_settings_controller.ex:78 msgid "Your account has been deleted" msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/show.html.heex:68 +msgid "Are you sure you want to remove the %{tag_name} tag from %{container_name}?" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/add_tag_component.ex:40 +msgid "%{name} added successfully" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/show.ex:40 +msgid "%{tag_name} has been removed from %{container_name}" +msgstr "" + +#, elixir-format, ex-autogen +#: lib/cannery_web/live/container_live/add_tag_component.ex:68 +msgid "Adding..." +msgstr ""