From 2db9ab968f6e784e93d38de9d39086186db685a5 Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 00:20:50 -0400 Subject: [PATCH 01/32] rename ammo types page to catalog --- lib/cannery_web/components/topbar.ex | 4 ++-- lib/cannery_web/live/ammo_type_live/index.html.heex | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cannery_web/components/topbar.ex b/lib/cannery_web/components/topbar.ex index 0936510..130f454 100644 --- a/lib/cannery_web/components/topbar.ex +++ b/lib/cannery_web/components/topbar.ex @@ -47,13 +47,13 @@ defmodule CanneryWeb.Components.Topbar do ) %>
  • - <%= live_redirect(gettext("Ammo"), + <%= live_redirect(gettext("Catalog"), to: Routes.ammo_type_index_path(Endpoint, :index), class: "text-primary-600 text-white hover:underline" ) %>
  • - <%= live_redirect(gettext("Manage"), + <%= live_redirect(gettext("Ammo"), to: Routes.ammo_group_index_path(Endpoint, :index), class: "text-primary-600 text-white hover:underline" ) %> diff --git a/lib/cannery_web/live/ammo_type_live/index.html.heex b/lib/cannery_web/live/ammo_type_live/index.html.heex index 90243e9..92bca7b 100644 --- a/lib/cannery_web/live/ammo_type_live/index.html.heex +++ b/lib/cannery_web/live/ammo_type_live/index.html.heex @@ -1,6 +1,6 @@

    - <%= gettext("Ammo Types") %> + <%= gettext("Catalog") %>

    <%= if @rows |> Enum.empty?() do %> From a1efd7cc60e083edea8d3dc072b4a9e1792972c8 Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 00:23:04 -0400 Subject: [PATCH 02/32] improve ammo group wording --- .../live/ammo_group_live/form_component.ex | 6 +- .../live/ammo_group_live/index.html.heex | 2 +- lib/cannery_web/live/ammo_group_live/show.ex | 8 +-- .../live/ammo_group_live/show.html.heex | 2 +- .../live/container_live/show.html.heex | 2 +- lib/cannery_web/live/range_live/index.ex | 2 +- priv/gettext/actions.pot | 6 +- priv/gettext/de/LC_MESSAGES/actions.po | 6 +- priv/gettext/de/LC_MESSAGES/default.po | 60 ++++++++++--------- priv/gettext/de/LC_MESSAGES/prompts.po | 40 +++++++------ priv/gettext/default.pot | 60 ++++++++++--------- priv/gettext/en/LC_MESSAGES/actions.po | 6 +- priv/gettext/en/LC_MESSAGES/default.po | 60 ++++++++++--------- priv/gettext/en/LC_MESSAGES/prompts.po | 40 +++++++------ priv/gettext/es/LC_MESSAGES/actions.po | 6 +- priv/gettext/es/LC_MESSAGES/default.po | 60 ++++++++++--------- priv/gettext/es/LC_MESSAGES/prompts.po | 40 +++++++------ priv/gettext/fr/LC_MESSAGES/actions.po | 6 +- priv/gettext/fr/LC_MESSAGES/default.po | 60 ++++++++++--------- priv/gettext/fr/LC_MESSAGES/prompts.po | 40 +++++++------ priv/gettext/prompts.pot | 40 +++++++------ .../cannery_web/live/ammo_group_live_test.exs | 28 ++++----- 22 files changed, 300 insertions(+), 280 deletions(-) diff --git a/lib/cannery_web/live/ammo_group_live/form_component.ex b/lib/cannery_web/live/ammo_group_live/form_component.ex index 213cef2..2e79341 100644 --- a/lib/cannery_web/live/ammo_group_live/form_component.ex +++ b/lib/cannery_web/live/ammo_group_live/form_component.ex @@ -85,7 +85,7 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do socket = case Ammo.update_ammo_group(ammo_group, ammo_group_params, current_user) do {:ok, _ammo_group} -> - prompt = dgettext("prompts", "Ammo group updated successfully") + prompt = dgettext("prompts", "Ammo updated successfully") socket |> put_flash(:info, prompt) |> push_redirect(to: return_to) {:error, %Changeset{} = changeset} -> @@ -146,8 +146,8 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do prompt = dngettext( "prompts", - "Ammo group created successfully", - "Ammo groups created successfully", + "Ammo added successfully", + "Ammo added successfully", count ) diff --git a/lib/cannery_web/live/ammo_group_live/index.html.heex b/lib/cannery_web/live/ammo_group_live/index.html.heex index d10ced3..831684a 100644 --- a/lib/cannery_web/live/ammo_group_live/index.html.heex +++ b/lib/cannery_web/live/ammo_group_live/index.html.heex @@ -39,7 +39,7 @@ ) %>
    <% else %> - <%= live_patch(dgettext("actions", "New Ammo group"), + <%= live_patch(dgettext("actions", "Add Ammo"), to: Routes.ammo_group_index_path(Endpoint, :new), class: "btn btn-primary" ) %> diff --git a/lib/cannery_web/live/ammo_group_live/show.ex b/lib/cannery_web/live/ammo_group_live/show.ex index 58f2e1e..6c8a777 100644 --- a/lib/cannery_web/live/ammo_group_live/show.ex +++ b/lib/cannery_web/live/ammo_group_live/show.ex @@ -35,9 +35,9 @@ defmodule CanneryWeb.AmmoGroupLive.Show do defp page_title(:add_shot_group), do: gettext("Record Shots") defp page_title(:edit_shot_group), do: gettext("Edit Shot Records") - defp page_title(:move), do: gettext("Move Ammo group") - defp page_title(:show), do: gettext("Show Ammo group") - defp page_title(:edit), do: gettext("Edit Ammo group") + defp page_title(:move), do: gettext("Move Ammo") + defp page_title(:show), do: gettext("Show Ammo") + defp page_title(:edit), do: gettext("Edit Ammo") @impl true def handle_event( @@ -47,7 +47,7 @@ defmodule CanneryWeb.AmmoGroupLive.Show do ) do ammo_group |> Ammo.delete_ammo_group!(current_user) - prompt = dgettext("prompts", "Ammo group deleted succesfully") + prompt = dgettext("prompts", "Ammo deleted succesfully") redirect_to = Routes.ammo_group_index_path(socket, :index) {:noreply, socket |> put_flash(:info, prompt) |> push_redirect(to: redirect_to)} diff --git a/lib/cannery_web/live/ammo_group_live/show.html.heex b/lib/cannery_web/live/ammo_group_live/show.html.heex index de64360..23c917f 100644 --- a/lib/cannery_web/live/ammo_group_live/show.html.heex +++ b/lib/cannery_web/live/ammo_group_live/show.html.heex @@ -105,7 +105,7 @@ <.container_card container={@ammo_group.container} /> <% else %> - <%= gettext("This ammo group is not in a container") %> + <%= gettext("This ammo is not in a container") %> <% end %> diff --git a/lib/cannery_web/live/container_live/show.html.heex b/lib/cannery_web/live/container_live/show.html.heex index 55d6c5b..4393579 100644 --- a/lib/cannery_web/live/container_live/show.html.heex +++ b/lib/cannery_web/live/container_live/show.html.heex @@ -75,7 +75,7 @@
    <%= if @container.ammo_groups |> Enum.empty?() do %>

    - <%= gettext("No ammo groups in this container") %> + <%= gettext("No ammo in this container") %>

    <% else %>
    diff --git a/lib/cannery_web/live/range_live/index.ex b/lib/cannery_web/live/range_live/index.ex index ff711b7..f9cda6f 100644 --- a/lib/cannery_web/live/range_live/index.ex +++ b/lib/cannery_web/live/range_live/index.ex @@ -65,7 +65,7 @@ defmodule CanneryWeb.RangeLive.Index do {:ok, _ammo_group} = ammo_group |> Ammo.update_ammo_group(%{"staged" => !ammo_group.staged}, current_user) - prompt = dgettext("prompts", "Ammo group unstaged succesfully") + prompt = dgettext("prompts", "Ammo unstaged succesfully") {:noreply, socket |> put_flash(:info, prompt) |> display_shot_groups()} end diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot index 106e277..d004181 100644 --- a/priv/gettext/actions.pot +++ b/priv/gettext/actions.pot @@ -12,6 +12,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:44 +#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 msgid "Add Ammo" msgstr "" @@ -80,11 +81,6 @@ msgstr "" msgid "Make your first tag!" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 -msgid "New Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/index.html.heex:17 msgid "New Ammo type" diff --git a/priv/gettext/de/LC_MESSAGES/actions.po b/priv/gettext/de/LC_MESSAGES/actions.po index b3a5e01..34833a7 100644 --- a/priv/gettext/de/LC_MESSAGES/actions.po +++ b/priv/gettext/de/LC_MESSAGES/actions.po @@ -25,6 +25,7 @@ msgstr "" ## effect: edit them in PO (.po) files instead. #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:44 +#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 msgid "Add Ammo" msgstr "Munition hinzufügen" @@ -93,11 +94,6 @@ msgstr "Einloggen" msgid "Make your first tag!" msgstr "Erstellen Sie ihren ersten Tag!" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 -msgid "New Ammo group" -msgstr "Neue Munitionsgruppe" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/index.html.heex:17 msgid "New Ammo type" diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 4007771..6d814b9 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -46,7 +46,7 @@ msgid "Admins:" msgstr "Admins:" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/components/topbar.ex:56 #: lib/cannery_web/live/ammo_group_live/index.html.heex:3 #: lib/cannery_web/live/range_live/index.ex:80 msgid "Ammo" @@ -173,7 +173,6 @@ msgstr "Einfache Anwendung:" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:38 -#: lib/cannery_web/live/ammo_group_live/show.ex:40 msgid "Edit Ammo group" msgstr "Munitionsgruppe bearbeiten" @@ -266,11 +265,6 @@ msgstr "Standort:" msgid "Magazine, Clip, Ammo Box, etc" msgstr "Magazin, Ladestreifen, Munitionskiste usw." -#, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:56 -msgid "Manage" -msgstr "Verwalten" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:148 #: lib/cannery_web/live/ammo_type_live/index.ex:73 @@ -332,11 +326,6 @@ msgstr "Keine Munitionsarten" msgid "No ammo for this type" msgstr "Keine Munition dieser Art" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 -msgid "No ammo groups in this container" -msgstr "Keine Munitionsgruppe in diesem Behälter" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/container_live/index.html.heex:8 msgid "No containers" @@ -426,11 +415,6 @@ msgstr "Unbegrenzt setzen" msgid "Settings" msgstr "Einstellungen" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.ex:39 -msgid "Show Ammo group" -msgstr "Munitionsgruppen anzeigen" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.ex:44 msgid "Show Ammo type" @@ -473,11 +457,6 @@ msgstr "Textfarbe" msgid "The self-hosted firearm tracker website" msgstr "Die selbst-gehostete Website zur Verwaltung von Schusswaffen" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 -msgid "This ammo group is not in a container" -msgstr "Diese Munitionsgruppe ist nicht in einem Behälter" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:132 #: lib/cannery_web/live/ammo_type_live/index.ex:69 @@ -572,11 +551,6 @@ msgstr "Für Schießplatz deselektieren" msgid "Record shots" msgstr "Schüsse dokumentieren" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 -msgid "Ammo Types" -msgstr "Munitionsarten" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:49 msgid "Ammo groups" @@ -622,7 +596,6 @@ msgstr "Schießkladde" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:32 -#: lib/cannery_web/live/ammo_group_live/show.ex:38 msgid "Move Ammo group" msgstr "Munitionsgruppe verschieben" @@ -907,3 +880,34 @@ msgstr "Sende Bugs oder Erweiterungsvorschläge" #: lib/cannery_web/live/home_live.ex:147 msgid "View the source code" msgstr "Quellcode ansehen" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 +msgid "Catalog" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:40 +msgid "Edit Ammo" +msgstr "Munitionstyp bearbeiten" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:38 +msgid "Move Ammo" +msgstr "Munition verschieben" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/container_live/show.html.heex:78 +msgid "No ammo in this container" +msgstr "Keine Munitionsgruppe in diesem Behälter" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:39 +msgid "Show Ammo" +msgstr "Zeige Munitionsarten" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 +msgid "This ammo is not in a container" +msgstr "Diese Munitionsgruppe ist nicht in einem Behälter" diff --git a/priv/gettext/de/LC_MESSAGES/prompts.po b/priv/gettext/de/LC_MESSAGES/prompts.po index ace0fa8..26ccc8e 100644 --- a/priv/gettext/de/LC_MESSAGES/prompts.po +++ b/priv/gettext/de/LC_MESSAGES/prompts.po @@ -76,15 +76,9 @@ msgstr "Eine Mail zum Bestätigen ihre Mailadresse wurde Ihnen zugesandt." #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:56 -#: lib/cannery_web/live/ammo_group_live/show.ex:50 msgid "Ammo group deleted succesfully" msgstr "Munitionsgruppe erfolgreich gelöscht" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 -msgid "Ammo group updated successfully" -msgstr "Munitionsgruppe erfolgreich aktualisiert" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/invite_live/index.html.heex:102 #: lib/cannery_web/live/invite_live/index.html.heex:131 @@ -220,11 +214,6 @@ msgstr "Schüsse erfolgreich dokumentiert" msgid "Are you sure you want to unstage this ammo?" msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/range_live/index.ex:68 -msgid "Ammo group unstaged succesfully" -msgstr "Munition erfolgreich demarkiert" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/show.ex:130 #: lib/cannery_web/live/range_live/index.ex:128 @@ -273,13 +262,6 @@ msgstr "Sie müssen" msgid "Creating..." msgstr "Erstellen..." -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 -msgid "Ammo group created successfully" -msgid_plural "Ammo groups created successfully" -msgstr[0] "Munitionsgruppe erfolgreich erstellt" -msgstr[1] "Munitionsgruppen erfolgreich erstellt" - #, elixir-autogen, elixir-format #: lib/cannery_web/templates/user_settings/edit.html.heex:136 msgid "Are you sure you want to change your language?" @@ -289,3 +271,25 @@ msgstr "Möchten Sie die Sprache wechseln?" #: lib/cannery_web/controllers/user_settings_controller.ex:65 msgid "Language updated successfully." msgstr "Spracheinstellung gespeichert." + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:50 +msgid "Ammo deleted succesfully" +msgstr "Munitionsgruppe erfolgreich gelöscht" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/range_live/index.ex:68 +msgid "Ammo unstaged succesfully" +msgstr "Munition erfolgreich demarkiert" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +msgid "Ammo updated successfully" +msgstr "Munitionsgruppe erfolgreich aktualisiert" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +msgid "Ammo added successfully" +msgid_plural "Ammo added successfully" +msgstr[0] "Munitionsgruppe erfolgreich aktualisiert" +msgstr[1] "Munitionsgruppe erfolgreich aktualisiert" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 9b77b06..c44a98a 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -31,7 +31,7 @@ msgid "Admins:" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/components/topbar.ex:56 #: lib/cannery_web/live/ammo_group_live/index.html.heex:3 #: lib/cannery_web/live/range_live/index.ex:80 msgid "Ammo" @@ -158,7 +158,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:38 -#: lib/cannery_web/live/ammo_group_live/show.ex:40 msgid "Edit Ammo group" msgstr "" @@ -251,11 +250,6 @@ msgstr "" msgid "Magazine, Clip, Ammo Box, etc" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:56 -msgid "Manage" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:148 #: lib/cannery_web/live/ammo_type_live/index.ex:73 @@ -317,11 +311,6 @@ msgstr "" msgid "No ammo for this type" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 -msgid "No ammo groups in this container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/container_live/index.html.heex:8 msgid "No containers" @@ -409,11 +398,6 @@ msgstr "" msgid "Settings" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.ex:39 -msgid "Show Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.ex:44 msgid "Show Ammo type" @@ -456,11 +440,6 @@ msgstr "" msgid "The self-hosted firearm tracker website" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 -msgid "This ammo group is not in a container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:132 #: lib/cannery_web/live/ammo_type_live/index.ex:69 @@ -555,11 +534,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 -msgid "Ammo Types" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:49 msgid "Ammo groups" @@ -605,7 +579,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:32 -#: lib/cannery_web/live/ammo_group_live/show.ex:38 msgid "Move Ammo group" msgstr "" @@ -890,3 +863,34 @@ msgstr "" #: lib/cannery_web/live/home_live.ex:147 msgid "View the source code" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 +msgid "Catalog" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.ex:40 +msgid "Edit Ammo" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.ex:38 +msgid "Move Ammo" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/container_live/show.html.heex:78 +msgid "No ammo in this container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.ex:39 +msgid "Show Ammo" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 +msgid "This ammo is not in a container" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/actions.po b/priv/gettext/en/LC_MESSAGES/actions.po index 745fc22..625025f 100644 --- a/priv/gettext/en/LC_MESSAGES/actions.po +++ b/priv/gettext/en/LC_MESSAGES/actions.po @@ -13,6 +13,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:44 +#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 msgid "Add Ammo" msgstr "" @@ -81,11 +82,6 @@ msgstr "" msgid "Make your first tag!" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 -msgid "New Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/index.html.heex:17 msgid "New Ammo type" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index dd06454..29c7759 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -32,7 +32,7 @@ msgid "Admins:" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/components/topbar.ex:56 #: lib/cannery_web/live/ammo_group_live/index.html.heex:3 #: lib/cannery_web/live/range_live/index.ex:80 msgid "Ammo" @@ -159,7 +159,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:38 -#: lib/cannery_web/live/ammo_group_live/show.ex:40 msgid "Edit Ammo group" msgstr "" @@ -252,11 +251,6 @@ msgstr "" msgid "Magazine, Clip, Ammo Box, etc" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:56 -msgid "Manage" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:148 #: lib/cannery_web/live/ammo_type_live/index.ex:73 @@ -318,11 +312,6 @@ msgstr "" msgid "No ammo for this type" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 -msgid "No ammo groups in this container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/container_live/index.html.heex:8 msgid "No containers" @@ -410,11 +399,6 @@ msgstr "" msgid "Settings" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.ex:39 -msgid "Show Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.ex:44 msgid "Show Ammo type" @@ -457,11 +441,6 @@ msgstr "" msgid "The self-hosted firearm tracker website" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 -msgid "This ammo group is not in a container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:132 #: lib/cannery_web/live/ammo_type_live/index.ex:69 @@ -556,11 +535,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 -msgid "Ammo Types" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:49 msgid "Ammo groups" @@ -606,7 +580,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:32 -#: lib/cannery_web/live/ammo_group_live/show.ex:38 msgid "Move Ammo group" msgstr "" @@ -891,3 +864,34 @@ msgstr "" #: lib/cannery_web/live/home_live.ex:147 msgid "View the source code" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 +msgid "Catalog" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:40 +msgid "Edit Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:38 +msgid "Move Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/container_live/show.html.heex:78 +msgid "No ammo in this container" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:39 +msgid "Show Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 +msgid "This ammo is not in a container" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/prompts.po b/priv/gettext/en/LC_MESSAGES/prompts.po index 59926be..ba314a0 100644 --- a/priv/gettext/en/LC_MESSAGES/prompts.po +++ b/priv/gettext/en/LC_MESSAGES/prompts.po @@ -64,15 +64,9 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:56 -#: lib/cannery_web/live/ammo_group_live/show.ex:50 msgid "Ammo group deleted succesfully" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 -msgid "Ammo group updated successfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/invite_live/index.html.heex:102 #: lib/cannery_web/live/invite_live/index.html.heex:131 @@ -200,11 +194,6 @@ msgstr "" msgid "Are you sure you want to unstage this ammo?" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/range_live/index.ex:68 -msgid "Ammo group unstaged succesfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/show.ex:130 #: lib/cannery_web/live/range_live/index.ex:128 @@ -253,13 +242,6 @@ msgstr "" msgid "Creating..." msgstr "" -#, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 -msgid "Ammo group created successfully" -msgid_plural "Ammo groups created successfully" -msgstr[0] "" -msgstr[1] "" - #, elixir-autogen, elixir-format #: lib/cannery_web/templates/user_settings/edit.html.heex:136 msgid "Are you sure you want to change your language?" @@ -269,3 +251,25 @@ msgstr "" #: lib/cannery_web/controllers/user_settings_controller.ex:65 msgid "Language updated successfully." msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:50 +msgid "Ammo deleted succesfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/range_live/index.ex:68 +msgid "Ammo unstaged succesfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +msgid "Ammo updated successfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +msgid "Ammo added successfully" +msgid_plural "Ammo added successfully" +msgstr[0] "" +msgstr[1] "" diff --git a/priv/gettext/es/LC_MESSAGES/actions.po b/priv/gettext/es/LC_MESSAGES/actions.po index 105d044..e700ac5 100644 --- a/priv/gettext/es/LC_MESSAGES/actions.po +++ b/priv/gettext/es/LC_MESSAGES/actions.po @@ -23,6 +23,7 @@ msgstr "" ## effect: edit them in PO (.po) files instead. #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:44 +#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 msgid "Add Ammo" msgstr "" @@ -91,11 +92,6 @@ msgstr "" msgid "Make your first tag!" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 -msgid "New Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/index.html.heex:17 msgid "New Ammo type" diff --git a/priv/gettext/es/LC_MESSAGES/default.po b/priv/gettext/es/LC_MESSAGES/default.po index 138220d..d034d6a 100644 --- a/priv/gettext/es/LC_MESSAGES/default.po +++ b/priv/gettext/es/LC_MESSAGES/default.po @@ -42,7 +42,7 @@ msgid "Admins:" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/components/topbar.ex:56 #: lib/cannery_web/live/ammo_group_live/index.html.heex:3 #: lib/cannery_web/live/range_live/index.ex:80 msgid "Ammo" @@ -169,7 +169,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:38 -#: lib/cannery_web/live/ammo_group_live/show.ex:40 msgid "Edit Ammo group" msgstr "" @@ -262,11 +261,6 @@ msgstr "" msgid "Magazine, Clip, Ammo Box, etc" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:56 -msgid "Manage" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:148 #: lib/cannery_web/live/ammo_type_live/index.ex:73 @@ -328,11 +322,6 @@ msgstr "" msgid "No ammo for this type" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 -msgid "No ammo groups in this container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/container_live/index.html.heex:8 msgid "No containers" @@ -420,11 +409,6 @@ msgstr "" msgid "Settings" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.ex:39 -msgid "Show Ammo group" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.ex:44 msgid "Show Ammo type" @@ -467,11 +451,6 @@ msgstr "" msgid "The self-hosted firearm tracker website" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 -msgid "This ammo group is not in a container" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:132 #: lib/cannery_web/live/ammo_type_live/index.ex:69 @@ -566,11 +545,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 -msgid "Ammo Types" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:49 msgid "Ammo groups" @@ -616,7 +590,6 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:32 -#: lib/cannery_web/live/ammo_group_live/show.ex:38 msgid "Move Ammo group" msgstr "" @@ -901,3 +874,34 @@ msgstr "" #: lib/cannery_web/live/home_live.ex:147 msgid "View the source code" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 +msgid "Catalog" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:40 +msgid "Edit Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:38 +msgid "Move Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/container_live/show.html.heex:78 +msgid "No ammo in this container" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:39 +msgid "Show Ammo" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 +msgid "This ammo is not in a container" +msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/prompts.po b/priv/gettext/es/LC_MESSAGES/prompts.po index ca90f0b..5ffea52 100644 --- a/priv/gettext/es/LC_MESSAGES/prompts.po +++ b/priv/gettext/es/LC_MESSAGES/prompts.po @@ -74,15 +74,9 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:56 -#: lib/cannery_web/live/ammo_group_live/show.ex:50 msgid "Ammo group deleted succesfully" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 -msgid "Ammo group updated successfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/invite_live/index.html.heex:102 #: lib/cannery_web/live/invite_live/index.html.heex:131 @@ -210,11 +204,6 @@ msgstr "" msgid "Are you sure you want to unstage this ammo?" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/range_live/index.ex:68 -msgid "Ammo group unstaged succesfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/show.ex:130 #: lib/cannery_web/live/range_live/index.ex:128 @@ -263,13 +252,6 @@ msgstr "" msgid "Creating..." msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 -msgid "Ammo group created successfully" -msgid_plural "Ammo groups created successfully" -msgstr[0] "" -msgstr[1] "" - #, elixir-autogen, elixir-format #: lib/cannery_web/templates/user_settings/edit.html.heex:136 msgid "Are you sure you want to change your language?" @@ -279,3 +261,25 @@ msgstr "" #: lib/cannery_web/controllers/user_settings_controller.ex:65 msgid "Language updated successfully." msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:50 +msgid "Ammo deleted succesfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/range_live/index.ex:68 +msgid "Ammo unstaged succesfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +msgid "Ammo updated successfully" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +msgid "Ammo added successfully" +msgid_plural "Ammo added successfully" +msgstr[0] "" +msgstr[1] "" diff --git a/priv/gettext/fr/LC_MESSAGES/actions.po b/priv/gettext/fr/LC_MESSAGES/actions.po index 8a92f3f..4914def 100644 --- a/priv/gettext/fr/LC_MESSAGES/actions.po +++ b/priv/gettext/fr/LC_MESSAGES/actions.po @@ -25,6 +25,7 @@ msgstr "" ## effect: edit them in PO (.po) files instead. #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:44 +#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 msgid "Add Ammo" msgstr "ajouter munition" @@ -93,11 +94,6 @@ msgstr "Se connecter" msgid "Make your first tag!" msgstr "Faîtes votre premier tag !" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/index.html.heex:42 -msgid "New Ammo group" -msgstr "Nouveau groupe de munition" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/index.html.heex:17 msgid "New Ammo type" diff --git a/priv/gettext/fr/LC_MESSAGES/default.po b/priv/gettext/fr/LC_MESSAGES/default.po index 411cee5..086c328 100644 --- a/priv/gettext/fr/LC_MESSAGES/default.po +++ b/priv/gettext/fr/LC_MESSAGES/default.po @@ -46,7 +46,7 @@ msgid "Admins:" msgstr "Administrateur·ices :" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/components/topbar.ex:56 #: lib/cannery_web/live/ammo_group_live/index.html.heex:3 #: lib/cannery_web/live/range_live/index.ex:80 msgid "Ammo" @@ -173,7 +173,6 @@ msgstr "Simple à utiliser :" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:38 -#: lib/cannery_web/live/ammo_group_live/show.ex:40 msgid "Edit Ammo group" msgstr "Éditer le groupe de munition" @@ -266,11 +265,6 @@ msgstr "Localisation :" msgid "Magazine, Clip, Ammo Box, etc" msgstr "Chargeur, lame-chargeur, boite de munition, etc." -#, elixir-autogen, elixir-format -#: lib/cannery_web/components/topbar.ex:56 -msgid "Manage" -msgstr "Gérer" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:148 #: lib/cannery_web/live/ammo_type_live/index.ex:73 @@ -332,11 +326,6 @@ msgstr "Aucun type de munition" msgid "No ammo for this type" msgstr "Aucune munition pour ce type" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 -msgid "No ammo groups in this container" -msgstr "Aucun groupe de munition pour ce conteneur" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/container_live/index.html.heex:8 msgid "No containers" @@ -426,11 +415,6 @@ msgstr "Mettre illimité" msgid "Settings" msgstr "Paramètres" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.ex:39 -msgid "Show Ammo group" -msgstr "Montrer le groupe de munition" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.ex:44 msgid "Show Ammo type" @@ -475,11 +459,6 @@ msgstr "Couleur du texte" msgid "The self-hosted firearm tracker website" msgstr "Le site web de suivi d’arme à feux auto-hébergé" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 -msgid "This ammo group is not in a container" -msgstr "Ce groupe de munition n’est pas dans un conteneur" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:132 #: lib/cannery_web/live/ammo_type_live/index.ex:69 @@ -574,11 +553,6 @@ msgstr "Désélectionner pour le stand" msgid "Record shots" msgstr "Tirs enregistrés" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 -msgid "Ammo Types" -msgstr "Types de munition" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:49 msgid "Ammo groups" @@ -624,7 +598,6 @@ msgstr "Enregistrements de tir" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:32 -#: lib/cannery_web/live/ammo_group_live/show.ex:38 msgid "Move Ammo group" msgstr "Déplacer le groupe de munition" @@ -909,3 +882,34 @@ msgstr "Remonter des bugs ou une demande de fonctionnalité" #: lib/cannery_web/live/home_live.ex:147 msgid "View the source code" msgstr "Voir le code source" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/topbar.ex:50 +#: lib/cannery_web/live/ammo_type_live/index.html.heex:3 +msgid "Catalog" +msgstr "" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:40 +msgid "Edit Ammo" +msgstr "Éditer le type de munition" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:38 +msgid "Move Ammo" +msgstr "Déplacer munition" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/container_live/show.html.heex:78 +msgid "No ammo in this container" +msgstr "Aucun groupe de munition pour ce conteneur" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:39 +msgid "Show Ammo" +msgstr "Montrer le type de munition" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.html.heex:108 +msgid "This ammo is not in a container" +msgstr "Ce groupe de munition n’est pas dans un conteneur" diff --git a/priv/gettext/fr/LC_MESSAGES/prompts.po b/priv/gettext/fr/LC_MESSAGES/prompts.po index 892dabf..522848f 100644 --- a/priv/gettext/fr/LC_MESSAGES/prompts.po +++ b/priv/gettext/fr/LC_MESSAGES/prompts.po @@ -78,15 +78,9 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:56 -#: lib/cannery_web/live/ammo_group_live/show.ex:50 msgid "Ammo group deleted succesfully" msgstr "Groupe de munition supprimé avec succès" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 -msgid "Ammo group updated successfully" -msgstr "Groupe de munition mis à jour avec succès" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/invite_live/index.html.heex:102 #: lib/cannery_web/live/invite_live/index.html.heex:131 @@ -221,11 +215,6 @@ msgstr "Tirs enregistré avec succès" msgid "Are you sure you want to unstage this ammo?" msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/range_live/index.ex:68 -msgid "Ammo group unstaged succesfully" -msgstr "Groupe de munition désélectionner avec succès" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/show.ex:130 #: lib/cannery_web/live/range_live/index.ex:128 @@ -274,13 +263,6 @@ msgstr "Vous aurez besoin de" msgid "Creating..." msgstr "Création en cours…" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 -msgid "Ammo group created successfully" -msgid_plural "Ammo groups created successfully" -msgstr[0] "Groupe de munition créé avec succès" -msgstr[1] "Groupes de munitions créé avec succès" - #, elixir-autogen, elixir-format #: lib/cannery_web/templates/user_settings/edit.html.heex:136 msgid "Are you sure you want to change your language?" @@ -290,3 +272,25 @@ msgstr "Êtes-vous certain·e de vouloir changer votre langue ?" #: lib/cannery_web/controllers/user_settings_controller.ex:65 msgid "Language updated successfully." msgstr "Langue mise à jour avec succès." + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/show.ex:50 +msgid "Ammo deleted succesfully" +msgstr "Groupe de munition supprimé avec succès" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/range_live/index.ex:68 +msgid "Ammo unstaged succesfully" +msgstr "Groupe de munition désélectionner avec succès" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +msgid "Ammo updated successfully" +msgstr "Groupe de munition mis à jour avec succès" + +#, elixir-autogen, elixir-format, fuzzy +#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +msgid "Ammo added successfully" +msgid_plural "Ammo added successfully" +msgstr[0] "Groupe de munition mis à jour avec succès" +msgstr[1] "Groupe de munition mis à jour avec succès" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index 5e69e09..ae45494 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -63,15 +63,9 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/index.ex:56 -#: lib/cannery_web/live/ammo_group_live/show.ex:50 msgid "Ammo group deleted succesfully" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 -msgid "Ammo group updated successfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/invite_live/index.html.heex:102 #: lib/cannery_web/live/invite_live/index.html.heex:131 @@ -199,11 +193,6 @@ msgstr "" msgid "Are you sure you want to unstage this ammo?" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/range_live/index.ex:68 -msgid "Ammo group unstaged succesfully" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_group_live/show.ex:130 #: lib/cannery_web/live/range_live/index.ex:128 @@ -252,13 +241,6 @@ msgstr "" msgid "Creating..." msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 -msgid "Ammo group created successfully" -msgid_plural "Ammo groups created successfully" -msgstr[0] "" -msgstr[1] "" - #, elixir-autogen, elixir-format #: lib/cannery_web/templates/user_settings/edit.html.heex:136 msgid "Are you sure you want to change your language?" @@ -268,3 +250,25 @@ msgstr "" #: lib/cannery_web/controllers/user_settings_controller.ex:65 msgid "Language updated successfully." msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.ex:50 +msgid "Ammo deleted succesfully" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/range_live/index.ex:68 +msgid "Ammo unstaged succesfully" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +msgid "Ammo updated successfully" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +msgid "Ammo added successfully" +msgid_plural "Ammo added successfully" +msgstr[0] "" +msgstr[1] "" diff --git a/test/cannery_web/live/ammo_group_live_test.exs b/test/cannery_web/live/ammo_group_live_test.exs index b3de49a..2a53b2f 100644 --- a/test/cannery_web/live/ammo_group_live_test.exs +++ b/test/cannery_web/live/ammo_group_live_test.exs @@ -35,15 +35,15 @@ defmodule CanneryWeb.AmmoGroupLiveTest do {:ok, _index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) ammo_group = ammo_group |> Repo.preload(:ammo_type) - assert html =~ gettext("Ammo groups") + assert html =~ gettext("Ammo") assert html =~ ammo_group.ammo_type.name end test "saves a single new ammo_group", %{conn: conn} do {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) - assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~ - gettext("New Ammo group") + assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ + gettext("Add Ammo") assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) @@ -57,7 +57,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do |> render_submit() |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) - assert html =~ dgettext("prompts", "Ammo group created successfully") + assert html =~ dgettext("prompts", "Ammo added successfully") assert html =~ "42" end @@ -66,8 +66,8 @@ defmodule CanneryWeb.AmmoGroupLiveTest do {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) - assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~ - gettext("New Ammo group") + assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ + gettext("Add Ammo") assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) @@ -83,15 +83,15 @@ defmodule CanneryWeb.AmmoGroupLiveTest do |> render_submit() |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) - assert html =~ dgettext("prompts", "Ammo groups created successfully") + assert html =~ dgettext("prompts", "Ammo added successfully") assert Ammo.list_ammo_groups(current_user) |> Enum.count() == multiplier + 1 end test "does not save invalid number of new ammo_groups", %{conn: conn} do {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) - assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~ - gettext("New Ammo group") + assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ + gettext("Add Ammo") assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) @@ -150,7 +150,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do assert index_live |> element("[data-qa=\"edit-#{ammo_group.id}\"]") |> render_click() =~ - gettext("Edit Ammo group") + gettext("Edit Ammo") assert_patch(index_live, Routes.ammo_group_index_path(conn, :edit, ammo_group)) @@ -164,7 +164,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do |> render_submit() |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) - assert html =~ dgettext("prompts", "Ammo group updated successfully") + assert html =~ dgettext("prompts", "Ammo updated successfully") assert html =~ "43" end @@ -186,7 +186,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do {:ok, _show_live, html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) ammo_group = ammo_group |> Repo.preload(:ammo_type) - assert html =~ gettext("Show Ammo group") + assert html =~ gettext("Show Ammo") assert html =~ ammo_group.ammo_type.name end @@ -196,7 +196,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do assert show_live |> element("[data-qa=\"edit\"]") |> render_click() =~ - gettext("Edit Ammo group") + gettext("Edit Ammo") assert_patch(show_live, Routes.ammo_group_show_path(conn, :edit, ammo_group)) @@ -210,7 +210,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do |> render_submit() |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) - assert html =~ dgettext("prompts", "Ammo group updated successfully") + assert html =~ dgettext("prompts", "Ammo updated successfully") assert html =~ "some updated notes" end From 268085e761b760a673ae4fa857856e859ecabc1f Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 00:25:38 -0400 Subject: [PATCH 03/32] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811898b..284c910 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.5.4 +- Rename "Ammo" tab to "Catalog", and "Manage" tab is now "Ammo" +- Ammo groups are now just referred to as Ammo + # v0.5.3 - Update French translation: Thank you [duponin](https://udongein.xyz/users/duponin)! - Update German translation: Thank you [Kaia](https://shitposter.club/users/kaia)! From 948fa929ec91e0135109a721e436dc07afd5351f Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 00:27:51 -0400 Subject: [PATCH 04/32] rename "Ammo Details" to "View in Catalog" --- lib/cannery_web/live/ammo_group_live/show.html.heex | 2 +- priv/gettext/actions.pot | 10 +++++----- priv/gettext/de/LC_MESSAGES/actions.po | 10 +++++----- priv/gettext/en/LC_MESSAGES/actions.po | 10 +++++----- priv/gettext/es/LC_MESSAGES/actions.po | 10 +++++----- priv/gettext/fr/LC_MESSAGES/actions.po | 10 +++++----- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/cannery_web/live/ammo_group_live/show.html.heex b/lib/cannery_web/live/ammo_group_live/show.html.heex index 23c917f..b6c537b 100644 --- a/lib/cannery_web/live/ammo_group_live/show.html.heex +++ b/lib/cannery_web/live/ammo_group_live/show.html.heex @@ -52,7 +52,7 @@
    - <%= live_patch(dgettext("actions", "Ammo Details"), + <%= live_patch(dgettext("actions", "View in Catalog"), to: Routes.ammo_type_show_path(Endpoint, :show, @ammo_group.ammo_type), class: "mx-4 my-2 btn btn-primary", data: [qa: "details"] diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot index d004181..c71e963 100644 --- a/priv/gettext/actions.pot +++ b/priv/gettext/actions.pot @@ -162,11 +162,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 -msgid "Ammo Details" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/components/move_ammo_group_component.ex:89 msgid "Add another container!" @@ -207,3 +202,8 @@ msgstr "" #: lib/cannery_web/templates/user_settings/edit.html.heex:134 msgid "Change language" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 +msgid "View in Catalog" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/actions.po b/priv/gettext/de/LC_MESSAGES/actions.po index 34833a7..8e00b0b 100644 --- a/priv/gettext/de/LC_MESSAGES/actions.po +++ b/priv/gettext/de/LC_MESSAGES/actions.po @@ -175,11 +175,6 @@ msgstr "Warum nicht einige für den Schießstand auswählen?" msgid "Record shots" msgstr "Schüsse dokumentieren" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 -msgid "Ammo Details" -msgstr "Munitionsdetails" - #, elixir-autogen, elixir-format #: lib/cannery_web/components/move_ammo_group_component.ex:89 msgid "Add another container!" @@ -220,3 +215,8 @@ msgstr "Sprache wechseln" #: lib/cannery_web/templates/user_settings/edit.html.heex:134 msgid "Change language" msgstr "Sprache wechseln" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 +msgid "View in Catalog" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/actions.po b/priv/gettext/en/LC_MESSAGES/actions.po index 625025f..c4ae050 100644 --- a/priv/gettext/en/LC_MESSAGES/actions.po +++ b/priv/gettext/en/LC_MESSAGES/actions.po @@ -163,11 +163,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 -msgid "Ammo Details" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/components/move_ammo_group_component.ex:89 msgid "Add another container!" @@ -208,3 +203,8 @@ msgstr "" #: lib/cannery_web/templates/user_settings/edit.html.heex:134 msgid "Change language" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 +msgid "View in Catalog" +msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/actions.po b/priv/gettext/es/LC_MESSAGES/actions.po index e700ac5..5ef26c1 100644 --- a/priv/gettext/es/LC_MESSAGES/actions.po +++ b/priv/gettext/es/LC_MESSAGES/actions.po @@ -173,11 +173,6 @@ msgstr "" msgid "Record shots" msgstr "" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 -msgid "Ammo Details" -msgstr "" - #, elixir-autogen, elixir-format #: lib/cannery_web/components/move_ammo_group_component.ex:89 msgid "Add another container!" @@ -218,3 +213,8 @@ msgstr "" #: lib/cannery_web/templates/user_settings/edit.html.heex:134 msgid "Change language" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 +msgid "View in Catalog" +msgstr "" diff --git a/priv/gettext/fr/LC_MESSAGES/actions.po b/priv/gettext/fr/LC_MESSAGES/actions.po index 4914def..0b01f97 100644 --- a/priv/gettext/fr/LC_MESSAGES/actions.po +++ b/priv/gettext/fr/LC_MESSAGES/actions.po @@ -175,11 +175,6 @@ msgstr "Pourquoi pas en préparer pour tirer ?" msgid "Record shots" msgstr "Enregistrer des tirs" -#, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 -msgid "Ammo Details" -msgstr "Détails de la munition" - #, elixir-autogen, elixir-format #: lib/cannery_web/components/move_ammo_group_component.ex:89 msgid "Add another container!" @@ -220,3 +215,8 @@ msgstr "Changer la langue" #: lib/cannery_web/templates/user_settings/edit.html.heex:134 msgid "Change language" msgstr "Changer la langue" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/live/ammo_group_live/show.html.heex:55 +msgid "View in Catalog" +msgstr "" From 11b1ae9980358d9e8d8d2a9cdd1c4bea2a973c5d Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 00:29:33 -0400 Subject: [PATCH 05/32] update paths --- CHANGELOG.md | 1 + lib/cannery_web/router.ex | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 284c910..ee5b619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v0.5.4 - Rename "Ammo" tab to "Catalog", and "Manage" tab is now "Ammo" - Ammo groups are now just referred to as Ammo +- URL paths now reflect new names # v0.5.3 - Update French translation: Thank you [duponin](https://udongein.xyz/users/duponin)! diff --git a/lib/cannery_web/router.ex b/lib/cannery_web/router.ex index f7f77c7..e38b297 100644 --- a/lib/cannery_web/router.ex +++ b/lib/cannery_web/router.ex @@ -65,12 +65,12 @@ defmodule CanneryWeb.Router do live "/tags/new", TagLive.Index, :new live "/tags/:id/edit", TagLive.Index, :edit - live "/ammo_types", AmmoTypeLive.Index, :index - live "/ammo_types/new", AmmoTypeLive.Index, :new - live "/ammo_types/:id/edit", AmmoTypeLive.Index, :edit + live "/catalog", AmmoTypeLive.Index, :index + live "/catalog/new", AmmoTypeLive.Index, :new + live "/catalog/:id/edit", AmmoTypeLive.Index, :edit - live "/ammo_types/:id", AmmoTypeLive.Show, :show - live "/ammo_types/:id/show/edit", AmmoTypeLive.Show, :edit + live "/catalog/:id", AmmoTypeLive.Show, :show + live "/catalog/:id/show/edit", AmmoTypeLive.Show, :edit live "/containers", ContainerLive.Index, :index live "/containers/new", ContainerLive.Index, :new @@ -81,17 +81,17 @@ defmodule CanneryWeb.Router do live "/containers/:id/show/edit", ContainerLive.Show, :edit live "/containers/:id/show/edit_tags", ContainerLive.Show, :edit_tags - live "/ammo_groups", AmmoGroupLive.Index, :index - live "/ammo_groups/new", AmmoGroupLive.Index, :new - live "/ammo_groups/:id/edit", AmmoGroupLive.Index, :edit - live "/ammo_groups/:id/add_shot_group", AmmoGroupLive.Index, :add_shot_group - live "/ammo_groups/:id/move", AmmoGroupLive.Index, :move + live "/ammo", AmmoGroupLive.Index, :index + live "/ammo/new", AmmoGroupLive.Index, :new + live "/ammo/:id/edit", AmmoGroupLive.Index, :edit + live "/ammo/:id/add_shot_group", AmmoGroupLive.Index, :add_shot_group + live "/ammo/:id/move", AmmoGroupLive.Index, :move - live "/ammo_groups/:id", AmmoGroupLive.Show, :show - live "/ammo_groups/:id/show/edit", AmmoGroupLive.Show, :edit - live "/ammo_groups/:id/show/add_shot_group", AmmoGroupLive.Show, :add_shot_group - live "/ammo_groups/:id/show/move", AmmoGroupLive.Show, :move - live "/ammo_groups/:id/show/:shot_group_id/edit", AmmoGroupLive.Show, :edit_shot_group + live "/ammo/:id", AmmoGroupLive.Show, :show + live "/ammo/:id/show/edit", AmmoGroupLive.Show, :edit + live "/ammo/:id/show/add_shot_group", AmmoGroupLive.Show, :add_shot_group + live "/ammo/:id/show/move", AmmoGroupLive.Show, :move + live "/ammo/:id/show/:shot_group_id/edit", AmmoGroupLive.Show, :edit_shot_group live "/range", RangeLive.Index, :index live "/range/:id/edit", RangeLive.Index, :edit From 9a1a104c6d0b3daccf77665c6f35c406f5d7cb69 Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 19:13:54 -0400 Subject: [PATCH 06/32] add pack and round count to containers --- CHANGELOG.md | 3 ++- lib/cannery/containers.ex | 12 ++++++++++++ lib/cannery_web/components/container_card.ex | 7 ++++++- lib/cannery_web/live/container_live/show.html.heex | 12 ++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee5b619..d4b5844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # v0.5.4 - Rename "Ammo" tab to "Catalog", and "Manage" tab is now "Ammo" -- Ammo groups are now just referred to as Ammo +- Ammo groups are now just referred to as Ammo or "Packs" - URL paths now reflect new names +- Add pack and round count to container information # v0.5.3 - Update French translation: Thank you [duponin](https://udongein.xyz/users/duponin)! diff --git a/lib/cannery/containers.ex b/lib/cannery/containers.ex index 55e0b90..58b139e 100644 --- a/lib/cannery/containers.ex +++ b/lib/cannery/containers.ex @@ -207,6 +207,18 @@ defmodule Cannery.Containers do if count == 0, do: raise("could not delete container tag"), else: count end + @doc """ + Returns number of rounds in container. If data is already preloaded, then + there will be no db hit. + """ + @spec get_container_ammo_group_count!(Container.t()) :: non_neg_integer() + def get_container_ammo_group_count!(%Container{} = container) do + container + |> Repo.preload(:ammo_groups) + |> Map.fetch!(:ammo_groups) + |> Enum.count() + end + @doc """ Returns number of rounds in container. If data is already preloaded, then there will be no db hit. diff --git a/lib/cannery_web/components/container_card.ex b/lib/cannery_web/components/container_card.ex index fc298e9..db3af29 100644 --- a/lib/cannery_web/components/container_card.ex +++ b/lib/cannery_web/components/container_card.ex @@ -45,7 +45,12 @@ defmodule CanneryWeb.Components.ContainerCard do <% end %> - <%= if @container.ammo_groups do %> + <%= unless @container.ammo_groups |> Enum.empty?() do %> + + <%= gettext("Packs:") %> + <%= @container |> Containers.get_container_ammo_group_count!() %> + + <%= gettext("Rounds:") %> <%= @container |> Containers.get_container_rounds!() %> diff --git a/lib/cannery_web/live/container_live/show.html.heex b/lib/cannery_web/live/container_live/show.html.heex index 4393579..2fc68c6 100644 --- a/lib/cannery_web/live/container_live/show.html.heex +++ b/lib/cannery_web/live/container_live/show.html.heex @@ -22,6 +22,18 @@ <% end %> + <%= unless @container.ammo_groups |> Enum.empty?() do %> + + <%= gettext("Packs:") %> + <%= @container |> Containers.get_container_ammo_group_count!() %> + + + + <%= gettext("Rounds:") %> + <%= @container |> Containers.get_container_rounds!() %> + + <% end %> +
    <%= live_patch to: Routes.container_show_path(Endpoint, :edit, @container), class: "text-primary-600 link", From 8c62a39c97fd6bdfa8adbf9cd7e664c44f8638c3 Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 19:16:31 -0400 Subject: [PATCH 07/32] bump to 0.5.4 --- lib/cannery_web/live/home_live.ex | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cannery_web/live/home_live.ex b/lib/cannery_web/live/home_live.ex index 4fdc9ad..ab869fe 100644 --- a/lib/cannery_web/live/home_live.ex +++ b/lib/cannery_web/live/home_live.ex @@ -126,7 +126,7 @@ defmodule CanneryWeb.HomeLive do to: "https://gitea.bubbletea.dev/shibao/cannery/src/branch/stable/CHANGELOG.md", target: "_blank", rel: "noopener noreferrer" do %> -

    0.5.3

    +

    0.5.4

    <% end %>
  • diff --git a/mix.exs b/mix.exs index b0aae78..54e36d5 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule Cannery.MixProject do def project do [ app: :cannery, - version: "0.5.3", + version: "0.5.4", elixir: "1.13.4", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:gettext] ++ Mix.compilers(), From 5fd46c326f1297b74485177deefe4da981353e8d Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 19:16:59 -0400 Subject: [PATCH 08/32] update gettext --- priv/gettext/actions.pot | 2 +- priv/gettext/de/LC_MESSAGES/actions.po | 2 +- priv/gettext/de/LC_MESSAGES/default.po | 13 ++++++++++--- priv/gettext/de/LC_MESSAGES/prompts.po | 2 +- priv/gettext/default.pot | 13 ++++++++++--- priv/gettext/en/LC_MESSAGES/actions.po | 2 +- priv/gettext/en/LC_MESSAGES/default.po | 13 ++++++++++--- priv/gettext/en/LC_MESSAGES/prompts.po | 2 +- priv/gettext/es/LC_MESSAGES/actions.po | 2 +- priv/gettext/es/LC_MESSAGES/default.po | 13 ++++++++++--- priv/gettext/es/LC_MESSAGES/prompts.po | 2 +- priv/gettext/fr/LC_MESSAGES/actions.po | 2 +- priv/gettext/fr/LC_MESSAGES/default.po | 13 ++++++++++--- priv/gettext/fr/LC_MESSAGES/prompts.po | 2 +- priv/gettext/prompts.pot | 2 +- 15 files changed, 60 insertions(+), 25 deletions(-) diff --git a/priv/gettext/actions.pot b/priv/gettext/actions.pot index c71e963..81f86a9 100644 --- a/priv/gettext/actions.pot +++ b/priv/gettext/actions.pot @@ -136,7 +136,7 @@ msgid "Send instructions to reset password" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:53 +#: lib/cannery_web/live/container_live/show.html.heex:65 msgid "Why not add one?" msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/actions.po b/priv/gettext/de/LC_MESSAGES/actions.po index 8e00b0b..0a5dd51 100644 --- a/priv/gettext/de/LC_MESSAGES/actions.po +++ b/priv/gettext/de/LC_MESSAGES/actions.po @@ -149,7 +149,7 @@ msgid "Send instructions to reset password" msgstr "Anleitung zum Passwort zurücksetzen zusenden" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:53 +#: lib/cannery_web/live/container_live/show.html.heex:65 msgid "Why not add one?" msgstr "Warum fügen Sie keine hinzu?" diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 6d814b9..b8c92eb 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -502,7 +502,7 @@ msgid "Your data stays with you, period" msgstr "Ihre Daten bleiben bei Ihnen, Punkt" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:49 +#: lib/cannery_web/live/container_live/show.html.heex:61 msgid "No tags for this container" msgstr "Keine Tags für diesen Behälter" @@ -720,7 +720,8 @@ msgid "Edit %{name} tags" msgstr "Editiere %{name} Tags" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/components/container_card.ex:55 +#: lib/cannery_web/live/container_live/show.html.heex:32 msgid "Rounds:" msgstr "Patronen:" @@ -898,7 +899,7 @@ msgid "Move Ammo" msgstr "Munition verschieben" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/container_live/show.html.heex:78 +#: lib/cannery_web/live/container_live/show.html.heex:90 msgid "No ammo in this container" msgstr "Keine Munitionsgruppe in diesem Behälter" @@ -911,3 +912,9 @@ msgstr "Zeige Munitionsarten" #: lib/cannery_web/live/ammo_group_live/show.html.heex:108 msgid "This ammo is not in a container" msgstr "Diese Munitionsgruppe ist nicht in einem Behälter" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/live/container_live/show.html.heex:27 +msgid "Packs:" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/prompts.po b/priv/gettext/de/LC_MESSAGES/prompts.po index 26ccc8e..5e63332 100644 --- a/priv/gettext/de/LC_MESSAGES/prompts.po +++ b/priv/gettext/de/LC_MESSAGES/prompts.po @@ -90,7 +90,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.html.heex:27 #: lib/cannery_web/live/container_live/index.html.heex:46 -#: lib/cannery_web/live/container_live/show.html.heex:37 +#: lib/cannery_web/live/container_live/show.html.heex:49 #: lib/cannery_web/live/tag_live/index.html.heex:38 msgid "Are you sure you want to delete %{name}?" msgstr "Sind Sie sicher, dass sie %{name} löschen möchten?" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index c44a98a..623790c 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -485,7 +485,7 @@ msgid "Your data stays with you, period" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:49 +#: lib/cannery_web/live/container_live/show.html.heex:61 msgid "No tags for this container" msgstr "" @@ -703,7 +703,8 @@ msgid "Edit %{name} tags" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/components/container_card.ex:55 +#: lib/cannery_web/live/container_live/show.html.heex:32 msgid "Rounds:" msgstr "" @@ -881,7 +882,7 @@ msgid "Move Ammo" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:78 +#: lib/cannery_web/live/container_live/show.html.heex:90 msgid "No ammo in this container" msgstr "" @@ -894,3 +895,9 @@ msgstr "" #: lib/cannery_web/live/ammo_group_live/show.html.heex:108 msgid "This ammo is not in a container" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/live/container_live/show.html.heex:27 +msgid "Packs:" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/actions.po b/priv/gettext/en/LC_MESSAGES/actions.po index c4ae050..f8f1e6c 100644 --- a/priv/gettext/en/LC_MESSAGES/actions.po +++ b/priv/gettext/en/LC_MESSAGES/actions.po @@ -137,7 +137,7 @@ msgid "Send instructions to reset password" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:53 +#: lib/cannery_web/live/container_live/show.html.heex:65 msgid "Why not add one?" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 29c7759..b5fb79b 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -486,7 +486,7 @@ msgid "Your data stays with you, period" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:49 +#: lib/cannery_web/live/container_live/show.html.heex:61 msgid "No tags for this container" msgstr "" @@ -704,7 +704,8 @@ msgid "Edit %{name} tags" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/components/container_card.ex:55 +#: lib/cannery_web/live/container_live/show.html.heex:32 msgid "Rounds:" msgstr "" @@ -882,7 +883,7 @@ msgid "Move Ammo" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/container_live/show.html.heex:78 +#: lib/cannery_web/live/container_live/show.html.heex:90 msgid "No ammo in this container" msgstr "" @@ -895,3 +896,9 @@ msgstr "" #: lib/cannery_web/live/ammo_group_live/show.html.heex:108 msgid "This ammo is not in a container" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/live/container_live/show.html.heex:27 +msgid "Packs:" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/prompts.po b/priv/gettext/en/LC_MESSAGES/prompts.po index ba314a0..0c80fb4 100644 --- a/priv/gettext/en/LC_MESSAGES/prompts.po +++ b/priv/gettext/en/LC_MESSAGES/prompts.po @@ -76,7 +76,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.html.heex:27 #: lib/cannery_web/live/container_live/index.html.heex:46 -#: lib/cannery_web/live/container_live/show.html.heex:37 +#: lib/cannery_web/live/container_live/show.html.heex:49 #: lib/cannery_web/live/tag_live/index.html.heex:38 msgid "Are you sure you want to delete %{name}?" msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/actions.po b/priv/gettext/es/LC_MESSAGES/actions.po index 5ef26c1..185cc87 100644 --- a/priv/gettext/es/LC_MESSAGES/actions.po +++ b/priv/gettext/es/LC_MESSAGES/actions.po @@ -147,7 +147,7 @@ msgid "Send instructions to reset password" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:53 +#: lib/cannery_web/live/container_live/show.html.heex:65 msgid "Why not add one?" msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/default.po b/priv/gettext/es/LC_MESSAGES/default.po index d034d6a..244908f 100644 --- a/priv/gettext/es/LC_MESSAGES/default.po +++ b/priv/gettext/es/LC_MESSAGES/default.po @@ -496,7 +496,7 @@ msgid "Your data stays with you, period" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:49 +#: lib/cannery_web/live/container_live/show.html.heex:61 msgid "No tags for this container" msgstr "" @@ -714,7 +714,8 @@ msgid "Edit %{name} tags" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/components/container_card.ex:55 +#: lib/cannery_web/live/container_live/show.html.heex:32 msgid "Rounds:" msgstr "" @@ -892,7 +893,7 @@ msgid "Move Ammo" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/container_live/show.html.heex:78 +#: lib/cannery_web/live/container_live/show.html.heex:90 msgid "No ammo in this container" msgstr "" @@ -905,3 +906,9 @@ msgstr "" #: lib/cannery_web/live/ammo_group_live/show.html.heex:108 msgid "This ammo is not in a container" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/live/container_live/show.html.heex:27 +msgid "Packs:" +msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/prompts.po b/priv/gettext/es/LC_MESSAGES/prompts.po index 5ffea52..3850bfe 100644 --- a/priv/gettext/es/LC_MESSAGES/prompts.po +++ b/priv/gettext/es/LC_MESSAGES/prompts.po @@ -86,7 +86,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.html.heex:27 #: lib/cannery_web/live/container_live/index.html.heex:46 -#: lib/cannery_web/live/container_live/show.html.heex:37 +#: lib/cannery_web/live/container_live/show.html.heex:49 #: lib/cannery_web/live/tag_live/index.html.heex:38 msgid "Are you sure you want to delete %{name}?" msgstr "" diff --git a/priv/gettext/fr/LC_MESSAGES/actions.po b/priv/gettext/fr/LC_MESSAGES/actions.po index 0b01f97..a8b08ca 100644 --- a/priv/gettext/fr/LC_MESSAGES/actions.po +++ b/priv/gettext/fr/LC_MESSAGES/actions.po @@ -149,7 +149,7 @@ msgid "Send instructions to reset password" msgstr "Envoyer les instructions pour réinitialiser le mot de passe" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:53 +#: lib/cannery_web/live/container_live/show.html.heex:65 msgid "Why not add one?" msgstr "Pourquoi pas en ajouter un ?" diff --git a/priv/gettext/fr/LC_MESSAGES/default.po b/priv/gettext/fr/LC_MESSAGES/default.po index 086c328..608cdf8 100644 --- a/priv/gettext/fr/LC_MESSAGES/default.po +++ b/priv/gettext/fr/LC_MESSAGES/default.po @@ -504,7 +504,7 @@ msgid "Your data stays with you, period" msgstr "Vos données restent avec vous, point final" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/container_live/show.html.heex:49 +#: lib/cannery_web/live/container_live/show.html.heex:61 msgid "No tags for this container" msgstr "Aucun tag pour ce conteneur" @@ -722,7 +722,8 @@ msgid "Edit %{name} tags" msgstr "Éditer les tags de %{name}" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/components/container_card.ex:55 +#: lib/cannery_web/live/container_live/show.html.heex:32 msgid "Rounds:" msgstr "Cartouches :" @@ -900,7 +901,7 @@ msgid "Move Ammo" msgstr "Déplacer munition" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/container_live/show.html.heex:78 +#: lib/cannery_web/live/container_live/show.html.heex:90 msgid "No ammo in this container" msgstr "Aucun groupe de munition pour ce conteneur" @@ -913,3 +914,9 @@ msgstr "Montrer le type de munition" #: lib/cannery_web/live/ammo_group_live/show.html.heex:108 msgid "This ammo is not in a container" msgstr "Ce groupe de munition n’est pas dans un conteneur" + +#, elixir-autogen, elixir-format +#: lib/cannery_web/components/container_card.ex:50 +#: lib/cannery_web/live/container_live/show.html.heex:27 +msgid "Packs:" +msgstr "" diff --git a/priv/gettext/fr/LC_MESSAGES/prompts.po b/priv/gettext/fr/LC_MESSAGES/prompts.po index 522848f..6f86ce6 100644 --- a/priv/gettext/fr/LC_MESSAGES/prompts.po +++ b/priv/gettext/fr/LC_MESSAGES/prompts.po @@ -91,7 +91,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.html.heex:27 #: lib/cannery_web/live/container_live/index.html.heex:46 -#: lib/cannery_web/live/container_live/show.html.heex:37 +#: lib/cannery_web/live/container_live/show.html.heex:49 #: lib/cannery_web/live/tag_live/index.html.heex:38 msgid "Are you sure you want to delete %{name}?" msgstr "Êtes-vous certain·e de supprimer %{name} ?" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index ae45494..391f35f 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -75,7 +75,7 @@ msgstr "" #, elixir-autogen, elixir-format #: lib/cannery_web/live/ammo_type_live/show.html.heex:27 #: lib/cannery_web/live/container_live/index.html.heex:46 -#: lib/cannery_web/live/container_live/show.html.heex:37 +#: lib/cannery_web/live/container_live/show.html.heex:49 #: lib/cannery_web/live/tag_live/index.html.heex:38 msgid "Are you sure you want to delete %{name}?" msgstr "" From 67010640f099502bf1f572a22f36547b8352cac0 Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 19:53:44 -0400 Subject: [PATCH 09/32] remove unchangeable requirements --- lib/cannery/ammo/ammo_group.ex | 4 ++-- lib/cannery/ammo/ammo_type.ex | 2 +- lib/cannery/containers/container.ex | 2 +- lib/cannery/invites/invite.ex | 2 +- lib/cannery/tags/tag.ex | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/cannery/ammo/ammo_group.ex b/lib/cannery/ammo/ammo_group.ex index 9e9954b..1dfe618 100644 --- a/lib/cannery/ammo/ammo_group.ex +++ b/lib/cannery/ammo/ammo_group.ex @@ -63,7 +63,7 @@ defmodule Cannery.Ammo.AmmoGroup do ammo_group |> cast(attrs, [:count, :price_paid, :notes, :staged, :ammo_type_id, :container_id]) |> validate_number(:count, greater_than_or_equal_to: 0) - |> validate_required([:count, :staged, :ammo_type_id, :container_id, :user_id]) + |> validate_required([:count, :staged, :ammo_type_id, :container_id]) end @doc """ @@ -75,6 +75,6 @@ defmodule Cannery.Ammo.AmmoGroup do def range_changeset(ammo_group, attrs) do ammo_group |> cast(attrs, [:count, :staged]) - |> validate_required([:count, :staged, :ammo_type_id, :container_id, :user_id]) + |> validate_required([:count, :staged]) end end diff --git a/lib/cannery/ammo/ammo_type.ex b/lib/cannery/ammo/ammo_type.ex index d986dcc..d7593f7 100644 --- a/lib/cannery/ammo/ammo_type.ex +++ b/lib/cannery/ammo/ammo_type.ex @@ -118,6 +118,6 @@ defmodule Cannery.Ammo.AmmoType do def update_changeset(ammo_type, attrs) do ammo_type |> cast(attrs, changeset_fields()) - |> validate_required([:name, :user_id]) + |> validate_required(:name) end end diff --git a/lib/cannery/containers/container.ex b/lib/cannery/containers/container.ex index c3ded85..59cc2f0 100644 --- a/lib/cannery/containers/container.ex +++ b/lib/cannery/containers/container.ex @@ -55,6 +55,6 @@ defmodule Cannery.Containers.Container do def update_changeset(container, attrs) do container |> cast(attrs, [:name, :desc, :type, :location]) - |> validate_required([:name, :type, :user_id]) + |> validate_required([:name, :type]) end end diff --git a/lib/cannery/invites/invite.ex b/lib/cannery/invites/invite.ex index 7b606f1..a0ea2c9 100644 --- a/lib/cannery/invites/invite.ex +++ b/lib/cannery/invites/invite.ex @@ -51,7 +51,7 @@ defmodule Cannery.Invites.Invite do def update_changeset(invite, attrs) do invite |> cast(attrs, [:name, :uses_left, :disabled_at]) - |> validate_required([:name, :token, :user_id]) + |> validate_required([:name]) |> validate_number(:uses_left, greater_than_or_equal_to: 0) end end diff --git a/lib/cannery/tags/tag.ex b/lib/cannery/tags/tag.ex index 6056077..addeb06 100644 --- a/lib/cannery/tags/tag.ex +++ b/lib/cannery/tags/tag.ex @@ -47,6 +47,6 @@ defmodule Cannery.Tags.Tag do def update_changeset(tag, attrs) do tag |> cast(attrs, [:name, :bg_color, :text_color]) - |> validate_required([:name, :bg_color, :text_color, :user_id]) + |> validate_required([:name, :bg_color, :text_color]) end end From 3cbd62e84c30ec87d681d44bebb16622ff759e6e Mon Sep 17 00:00:00 2001 From: shibao Date: Fri, 1 Jul 2022 21:39:08 -0400 Subject: [PATCH 10/32] fix shotgroup changesets --- lib/cannery/activity_log.ex | 153 ++++++++---------- lib/cannery/activity_log/shot_group.ex | 63 +++++++- .../components/add_shot_group_component.ex | 26 +-- .../live/range_live/form_component.ex | 8 +- priv/gettext/de/LC_MESSAGES/errors.po | 6 +- priv/gettext/de/LC_MESSAGES/prompts.po | 2 +- priv/gettext/en/LC_MESSAGES/errors.po | 6 +- priv/gettext/en/LC_MESSAGES/prompts.po | 2 +- priv/gettext/errors.pot | 6 +- priv/gettext/es/LC_MESSAGES/errors.po | 6 +- priv/gettext/es/LC_MESSAGES/prompts.po | 2 +- priv/gettext/fr/LC_MESSAGES/errors.po | 6 +- priv/gettext/fr/LC_MESSAGES/prompts.po | 2 +- priv/gettext/prompts.pot | 2 +- test/cannery/activity_log_test.exs | 5 - 15 files changed, 157 insertions(+), 138 deletions(-) diff --git a/lib/cannery/activity_log.ex b/lib/cannery/activity_log.ex index 354872d..911ee67 100644 --- a/lib/cannery/activity_log.ex +++ b/lib/cannery/activity_log.ex @@ -4,8 +4,7 @@ defmodule Cannery.ActivityLog do """ import Ecto.Query, warn: false - import CanneryWeb.Gettext - alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Ammo, Ammo.AmmoGroup, Repo} + alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Ammo.AmmoGroup, Repo} alias Ecto.{Changeset, Multi} @doc """ @@ -60,32 +59,30 @@ defmodule Cannery.ActivityLog do """ @spec create_shot_group(attrs :: map(), User.t(), AmmoGroup.t()) :: {:ok, ShotGroup.t()} | {:error, Changeset.t(ShotGroup.t()) | nil} - def create_shot_group( - attrs, - %User{id: user_id}, - %AmmoGroup{id: ammo_group_id, count: ammo_group_count, user_id: user_id} = ammo_group - ) do - attrs = attrs |> Map.merge(%{"user_id" => user_id, "ammo_group_id" => ammo_group_id}) - changeset = %ShotGroup{} |> ShotGroup.create_changeset(attrs) - shot_group_count = changeset |> Changeset.get_field(:count) - - if shot_group_count > ammo_group_count do - error = dgettext("errors", "Count must be less than %{count}", count: ammo_group_count) - changeset = changeset |> Changeset.add_error(:count, error) - {:error, changeset} - else - Multi.new() - |> Multi.insert(:create_shot_group, changeset) - |> Multi.update( - :update_ammo_group, - ammo_group |> AmmoGroup.range_changeset(%{"count" => ammo_group_count - shot_group_count}) - ) - |> Repo.transaction() - |> case do - {:ok, %{create_shot_group: shot_group}} -> {:ok, shot_group} - {:error, :create_shot_group, changeset, _changes_so_far} -> {:error, changeset} - {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil} + def create_shot_group(attrs, user, ammo_group) do + Multi.new() + |> Multi.insert( + :create_shot_group, + %ShotGroup{} |> ShotGroup.create_changeset(user, ammo_group, attrs) + ) + |> Multi.run( + :ammo_group, + fn repo, %{create_shot_group: %{ammo_group_id: ammo_group_id, user_id: user_id}} -> + {:ok, + repo.one(from ag in AmmoGroup, where: ag.id == ^ammo_group_id and ag.user_id == ^user_id)} end + ) + |> Multi.update( + :update_ammo_group, + fn %{create_shot_group: %{count: shot_group_count}, ammo_group: %{count: ammo_group_count}} -> + ammo_group |> AmmoGroup.range_changeset(%{"count" => ammo_group_count - shot_group_count}) + end + ) + |> Repo.transaction() + |> case do + {:ok, %{create_shot_group: shot_group}} -> {:ok, shot_group} + {:error, :create_shot_group, changeset, _changes_so_far} -> {:error, changeset} + {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil} end end @@ -104,42 +101,38 @@ defmodule Cannery.ActivityLog do @spec update_shot_group(ShotGroup.t(), attrs :: map(), User.t()) :: {:ok, ShotGroup.t()} | {:error, Changeset.t(ShotGroup.t()) | nil} def update_shot_group( - %ShotGroup{count: count, user_id: user_id, ammo_group_id: ammo_group_id} = shot_group, + %ShotGroup{count: count, user_id: user_id} = shot_group, attrs, %User{id: user_id} = user ) do - %{count: ammo_group_count, user_id: ^user_id} = - ammo_group = ammo_group_id |> Ammo.get_ammo_group!(user) - - changeset = shot_group |> ShotGroup.update_changeset(attrs) - new_shot_group_count = changeset |> Changeset.get_field(:count) - shot_diff_to_add = new_shot_group_count - count - - cond do - shot_diff_to_add > ammo_group_count -> - error = dgettext("errors", "Count must be less than %{count}", count: ammo_group_count) - changeset = changeset |> Changeset.add_error(:count, error) - {:error, changeset} - - new_shot_group_count <= 0 -> - error = dgettext("errors", "Count must be at least 1") - changeset = changeset |> Changeset.add_error(:count, error) - {:error, changeset} - - true -> - Multi.new() - |> Multi.update(:update_shot_group, changeset) - |> Multi.update( - :update_ammo_group, - ammo_group - |> AmmoGroup.range_changeset(%{"count" => ammo_group_count - shot_diff_to_add}) - ) - |> Repo.transaction() - |> case do - {:ok, %{update_shot_group: shot_group}} -> {:ok, shot_group} - {:error, :update_shot_group, changeset, _changes_so_far} -> {:error, changeset} - {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil} - end + Multi.new() + |> Multi.update( + :update_shot_group, + shot_group |> ShotGroup.update_changeset(user, attrs) + ) + |> Multi.run( + :ammo_group, + fn repo, %{update_shot_group: %{ammo_group_id: ammo_group_id, user_id: user_id}} -> + {:ok, + repo.one(from ag in AmmoGroup, where: ag.id == ^ammo_group_id and ag.user_id == ^user_id)} + end + ) + |> Multi.update( + :update_ammo_group, + fn %{ + update_shot_group: %{count: new_count}, + ammo_group: %{count: ammo_group_count} = ammo_group + } -> + shot_diff_to_add = new_count - count + new_ammo_group_count = ammo_group_count - shot_diff_to_add + ammo_group |> AmmoGroup.range_changeset(%{"count" => new_ammo_group_count}) + end + ) + |> Repo.transaction() + |> case do + {:ok, %{update_shot_group: shot_group}} -> {:ok, shot_group} + {:error, :update_shot_group, changeset, _changes_so_far} -> {:error, changeset} + {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil} end end @@ -158,18 +151,27 @@ defmodule Cannery.ActivityLog do @spec delete_shot_group(ShotGroup.t(), User.t()) :: {:ok, ShotGroup.t()} | {:error, Changeset.t(ShotGroup.t())} def delete_shot_group( - %ShotGroup{count: count, user_id: user_id, ammo_group_id: ammo_group_id} = shot_group, - %User{id: user_id} = user + %ShotGroup{user_id: user_id} = shot_group, + %User{id: user_id} ) do - %{count: ammo_group_count, user_id: ^user_id} = - ammo_group = ammo_group_id |> Ammo.get_ammo_group!(user) - Multi.new() |> Multi.delete(:delete_shot_group, shot_group) + |> Multi.run( + :ammo_group, + fn repo, %{delete_shot_group: %{ammo_group_id: ammo_group_id, user_id: user_id}} -> + {:ok, + repo.one(from ag in AmmoGroup, where: ag.id == ^ammo_group_id and ag.user_id == ^user_id)} + end + ) |> Multi.update( :update_ammo_group, - ammo_group - |> AmmoGroup.range_changeset(%{"count" => ammo_group_count + count}) + fn %{ + delete_shot_group: %{count: count}, + ammo_group: %{count: ammo_group_count} = ammo_group + } -> + new_ammo_group_count = ammo_group_count + count + ammo_group |> AmmoGroup.range_changeset(%{"count" => new_ammo_group_count}) + end ) |> Repo.transaction() |> case do @@ -178,21 +180,4 @@ defmodule Cannery.ActivityLog do {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil} end end - - @doc """ - Returns an `%Ecto.Changeset{}` for tracking shot_group changes. - - ## Examples - - iex> change_shot_group(shot_group) - %Ecto.Changeset{data: %ShotGroup{}} - - """ - @spec change_shot_group(ShotGroup.t() | ShotGroup.new_shot_group()) :: - Changeset.t(ShotGroup.t() | ShotGroup.new_shot_group()) - @spec change_shot_group(ShotGroup.t() | ShotGroup.new_shot_group(), attrs :: map()) :: - Changeset.t(ShotGroup.t() | ShotGroup.new_shot_group()) - def change_shot_group(%ShotGroup{} = shot_group, attrs \\ %{}) do - shot_group |> ShotGroup.update_changeset(attrs) - end end diff --git a/lib/cannery/activity_log/shot_group.ex b/lib/cannery/activity_log/shot_group.ex index 7b25433..4355a7e 100644 --- a/lib/cannery/activity_log/shot_group.ex +++ b/lib/cannery/activity_log/shot_group.ex @@ -4,8 +4,9 @@ defmodule Cannery.ActivityLog.ShotGroup do """ use Ecto.Schema + import CanneryWeb.Gettext import Ecto.Changeset - alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Ammo.AmmoGroup} + alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Ammo.AmmoGroup, Repo} alias Ecto.{Changeset, UUID} @primary_key {:id, :binary_id, autogenerate: true} @@ -37,21 +38,71 @@ defmodule Cannery.ActivityLog.ShotGroup do @type id :: UUID.t() @doc false - @spec create_changeset(new_shot_group(), attrs :: map()) :: Changeset.t(new_shot_group()) - def create_changeset(shot_group, attrs) do + @spec create_changeset(new_shot_group(), User.t(), AmmoGroup.t(), attrs :: map()) :: + Changeset.t(new_shot_group()) + def create_changeset( + shot_group, + %User{id: user_id}, + %AmmoGroup{id: ammo_group_id, user_id: user_id} = ammo_group, + attrs + ) + when not (user_id |> is_nil()) and not (ammo_group_id |> is_nil()) do shot_group - |> cast(attrs, [:count, :notes, :date, :ammo_group_id, :user_id]) + |> change(user_id: user_id) + |> change(ammo_group_id: ammo_group_id) + |> cast(attrs, [:count, :notes, :date]) |> validate_number(:count, greater_than: 0) + |> validate_create_shot_group_count(ammo_group) |> validate_required([:count, :ammo_group_id, :user_id]) end + defp validate_create_shot_group_count(changeset, %AmmoGroup{count: ammo_group_count}) do + if changeset |> Changeset.get_field(:count) > ammo_group_count do + error = dgettext("errors", "Count must be less than %{count}", count: ammo_group_count) + changeset |> Changeset.add_error(:count, error) + else + changeset + end + end + @doc false - @spec update_changeset(t() | new_shot_group(), attrs :: map()) :: + @spec update_changeset(t() | new_shot_group(), User.t(), attrs :: map()) :: Changeset.t(t() | new_shot_group()) - def update_changeset(shot_group, attrs) do + def update_changeset( + %ShotGroup{user_id: user_id} = shot_group, + %User{id: user_id} = user, + attrs + ) + when not (user_id |> is_nil()) do shot_group |> cast(attrs, [:count, :notes, :date]) |> validate_number(:count, greater_than: 0) |> validate_required([:count]) + |> validate_update_shot_group_count(shot_group, user) + end + + defp validate_update_shot_group_count( + changeset, + %ShotGroup{count: count} = shot_group, + %User{id: user_id} + ) + when not (user_id |> is_nil()) do + %{ammo_group: %AmmoGroup{count: ammo_group_count, user_id: ^user_id}} = + shot_group |> Repo.preload(:ammo_group) + + new_shot_group_count = changeset |> Changeset.get_field(:count) + shot_diff_to_add = new_shot_group_count - count + + cond do + shot_diff_to_add > ammo_group_count -> + error = dgettext("errors", "Count must be less than %{count}", count: ammo_group_count) + changeset |> Changeset.add_error(:count, error) + + new_shot_group_count <= 0 -> + changeset |> Changeset.add_error(:count, dgettext("errors", "Count must be at least 1")) + + true -> + changeset + end end end diff --git a/lib/cannery_web/components/add_shot_group_component.ex b/lib/cannery_web/components/add_shot_group_component.ex index 679e5f2..1500aaf 100644 --- a/lib/cannery_web/components/add_shot_group_component.ex +++ b/lib/cannery_web/components/add_shot_group_component.ex @@ -16,9 +16,10 @@ defmodule CanneryWeb.Components.AddShotGroupComponent do }, Socket.t() ) :: {:ok, Socket.t()} - def update(%{ammo_group: _ammo_group, current_user: _current_user} = assigns, socket) do + def update(%{ammo_group: ammo_group, current_user: current_user} = assigns, socket) do changeset = - %ShotGroup{date: NaiveDateTime.utc_now(), count: 1} |> ActivityLog.change_shot_group() + %ShotGroup{date: NaiveDateTime.utc_now(), count: 1} + |> ShotGroup.create_changeset(current_user, ammo_group, %{}) {:ok, socket |> assign(assigns) |> assign(:changeset, changeset)} end @@ -27,21 +28,13 @@ defmodule CanneryWeb.Components.AddShotGroupComponent do def handle_event( "validate", %{"shot_group" => shot_group_params}, - %{ - assigns: %{ - ammo_group: %AmmoGroup{id: ammo_group_id} = ammo_group, - current_user: %User{id: user_id} - } - } = socket + %{assigns: %{ammo_group: ammo_group, current_user: current_user}} = socket ) do - shot_group_params = - shot_group_params - |> process_params(ammo_group) - |> Map.merge(%{"ammo_group_id" => ammo_group_id, "user_id" => user_id}) + params = shot_group_params |> process_params(ammo_group) changeset = %ShotGroup{} - |> ActivityLog.change_shot_group(shot_group_params) + |> ShotGroup.create_changeset(current_user, ammo_group, params) |> Map.put(:action, :validate) {:noreply, socket |> assign(:changeset, changeset)} @@ -51,17 +44,12 @@ defmodule CanneryWeb.Components.AddShotGroupComponent do "save", %{"shot_group" => shot_group_params}, %{ - assigns: %{ - ammo_group: %{id: ammo_group_id} = ammo_group, - current_user: %{id: user_id} = current_user, - return_to: return_to - } + assigns: %{ammo_group: ammo_group, current_user: current_user, return_to: return_to} } = socket ) do socket = shot_group_params |> process_params(ammo_group) - |> Map.merge(%{"ammo_group_id" => ammo_group_id, "user_id" => user_id}) |> ActivityLog.create_shot_group(current_user, ammo_group) |> case do {:ok, _shot_group} -> diff --git a/lib/cannery_web/live/range_live/form_component.ex b/lib/cannery_web/live/range_live/form_component.ex index 770fe85..8eb8711 100644 --- a/lib/cannery_web/live/range_live/form_component.ex +++ b/lib/cannery_web/live/range_live/form_component.ex @@ -1,6 +1,6 @@ defmodule CanneryWeb.RangeLive.FormComponent do @moduledoc """ - Livecomponent that can update or create a ShotGroup + Livecomponent that can update a ShotGroup """ use CanneryWeb, :live_component @@ -24,7 +24,7 @@ defmodule CanneryWeb.RangeLive.FormComponent do } = assigns, socket ) do - changeset = shot_group |> ActivityLog.change_shot_group() + changeset = shot_group |> ShotGroup.update_changeset(current_user, %{}) ammo_group = Ammo.get_ammo_group!(ammo_group_id, current_user) {:ok, socket |> assign(assigns) |> assign(ammo_group: ammo_group, changeset: changeset)} end @@ -33,11 +33,11 @@ defmodule CanneryWeb.RangeLive.FormComponent do def handle_event( "validate", %{"shot_group" => shot_group_params}, - %{assigns: %{shot_group: shot_group}} = socket + %{assigns: %{current_user: current_user, shot_group: shot_group}} = socket ) do changeset = shot_group - |> ActivityLog.change_shot_group(shot_group_params) + |> ShotGroup.update_changeset(current_user, shot_group_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :changeset, changeset)} diff --git a/priv/gettext/de/LC_MESSAGES/errors.po b/priv/gettext/de/LC_MESSAGES/errors.po index b6c601b..7a3b94d 100644 --- a/priv/gettext/de/LC_MESSAGES/errors.po +++ b/priv/gettext/de/LC_MESSAGES/errors.po @@ -152,13 +152,13 @@ msgid "Tag could not be added" msgstr "Tag konnte nicht hinzugefügt werden" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:125 +#: lib/cannery/activity_log/shot_group.ex:102 msgid "Count must be at least 1" msgstr "Anzahl muss mindestens 1 sein" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:73 -#: lib/cannery/activity_log.ex:120 +#: lib/cannery/activity_log/shot_group.ex:61 +#: lib/cannery/activity_log/shot_group.ex:98 msgid "Count must be less than %{count}" msgstr "Anzahl muss weniger als %{count} betragen" diff --git a/priv/gettext/de/LC_MESSAGES/prompts.po b/priv/gettext/de/LC_MESSAGES/prompts.po index 5e63332..e4ca75a 100644 --- a/priv/gettext/de/LC_MESSAGES/prompts.po +++ b/priv/gettext/de/LC_MESSAGES/prompts.po @@ -205,7 +205,7 @@ msgid "Adding..." msgstr "Füge hinzu..." #, elixir-autogen, elixir-format -#: lib/cannery_web/components/add_shot_group_component.ex:68 +#: lib/cannery_web/components/add_shot_group_component.ex:56 msgid "Shots recorded successfully" msgstr "Schüsse erfolgreich dokumentiert" diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po index fe8d977..d303a0f 100644 --- a/priv/gettext/en/LC_MESSAGES/errors.po +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -139,13 +139,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:125 +#: lib/cannery/activity_log/shot_group.ex:102 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:73 -#: lib/cannery/activity_log.ex:120 +#: lib/cannery/activity_log/shot_group.ex:61 +#: lib/cannery/activity_log/shot_group.ex:98 msgid "Count must be less than %{count}" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/prompts.po b/priv/gettext/en/LC_MESSAGES/prompts.po index 0c80fb4..ce081ea 100644 --- a/priv/gettext/en/LC_MESSAGES/prompts.po +++ b/priv/gettext/en/LC_MESSAGES/prompts.po @@ -185,7 +185,7 @@ msgid "Adding..." msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/add_shot_group_component.ex:68 +#: lib/cannery_web/components/add_shot_group_component.ex:56 msgid "Shots recorded successfully" msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 80bb167..6b3a922 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -138,13 +138,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:125 +#: lib/cannery/activity_log/shot_group.ex:102 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:73 -#: lib/cannery/activity_log.ex:120 +#: lib/cannery/activity_log/shot_group.ex:61 +#: lib/cannery/activity_log/shot_group.ex:98 msgid "Count must be less than %{count}" msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/errors.po b/priv/gettext/es/LC_MESSAGES/errors.po index b59e657..aac6461 100644 --- a/priv/gettext/es/LC_MESSAGES/errors.po +++ b/priv/gettext/es/LC_MESSAGES/errors.po @@ -149,13 +149,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:125 +#: lib/cannery/activity_log/shot_group.ex:102 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:73 -#: lib/cannery/activity_log.ex:120 +#: lib/cannery/activity_log/shot_group.ex:61 +#: lib/cannery/activity_log/shot_group.ex:98 msgid "Count must be less than %{count}" msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/prompts.po b/priv/gettext/es/LC_MESSAGES/prompts.po index 3850bfe..095eda8 100644 --- a/priv/gettext/es/LC_MESSAGES/prompts.po +++ b/priv/gettext/es/LC_MESSAGES/prompts.po @@ -195,7 +195,7 @@ msgid "Adding..." msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/add_shot_group_component.ex:68 +#: lib/cannery_web/components/add_shot_group_component.ex:56 msgid "Shots recorded successfully" msgstr "" diff --git a/priv/gettext/fr/LC_MESSAGES/errors.po b/priv/gettext/fr/LC_MESSAGES/errors.po index ef5ae36..013a47f 100644 --- a/priv/gettext/fr/LC_MESSAGES/errors.po +++ b/priv/gettext/fr/LC_MESSAGES/errors.po @@ -153,13 +153,13 @@ msgid "Tag could not be added" msgstr "Le tag n’a pas pu être ajouté" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:125 +#: lib/cannery/activity_log/shot_group.ex:102 msgid "Count must be at least 1" msgstr "Le nombre doit être au moins égal à 1" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log.ex:73 -#: lib/cannery/activity_log.ex:120 +#: lib/cannery/activity_log/shot_group.ex:61 +#: lib/cannery/activity_log/shot_group.ex:98 msgid "Count must be less than %{count}" msgstr "La quantité doit être inférieur à %{count}" diff --git a/priv/gettext/fr/LC_MESSAGES/prompts.po b/priv/gettext/fr/LC_MESSAGES/prompts.po index 6f86ce6..0328cab 100644 --- a/priv/gettext/fr/LC_MESSAGES/prompts.po +++ b/priv/gettext/fr/LC_MESSAGES/prompts.po @@ -206,7 +206,7 @@ msgid "Adding..." msgstr "Ajout en cours…" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/add_shot_group_component.ex:68 +#: lib/cannery_web/components/add_shot_group_component.ex:56 msgid "Shots recorded successfully" msgstr "Tirs enregistré avec succès" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index 391f35f..364f8e4 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -184,7 +184,7 @@ msgid "Adding..." msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/components/add_shot_group_component.ex:68 +#: lib/cannery_web/components/add_shot_group_component.ex:56 msgid "Shots recorded successfully" msgstr "" diff --git a/test/cannery/activity_log_test.exs b/test/cannery/activity_log_test.exs index d96c105..418c8f5 100644 --- a/test/cannery/activity_log_test.exs +++ b/test/cannery/activity_log_test.exs @@ -178,10 +178,5 @@ defmodule Cannery.ActivityLogTest do ActivityLog.get_shot_group!(shot_group.id, current_user) end end - - test "change_shot_group/1 returns a shot_group changeset", - %{shot_group: shot_group} do - assert %Ecto.Changeset{} = ActivityLog.change_shot_group(shot_group) - end end end From 9ebca20dc6747f81c3fcde5d23424001e1906809 Mon Sep 17 00:00:00 2001 From: shibao Date: Mon, 4 Jul 2022 20:06:31 -0400 Subject: [PATCH 11/32] add error case for create_changeset --- lib/cannery/activity_log/shot_group.ex | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/cannery/activity_log/shot_group.ex b/lib/cannery/activity_log/shot_group.ex index 4355a7e..f81c1fb 100644 --- a/lib/cannery/activity_log/shot_group.ex +++ b/lib/cannery/activity_log/shot_group.ex @@ -38,7 +38,12 @@ defmodule Cannery.ActivityLog.ShotGroup do @type id :: UUID.t() @doc false - @spec create_changeset(new_shot_group(), User.t(), AmmoGroup.t(), attrs :: map()) :: + @spec create_changeset( + new_shot_group(), + User.t() | any(), + AmmoGroup.t() | any(), + attrs :: map() + ) :: Changeset.t(new_shot_group()) def create_changeset( shot_group, @@ -56,6 +61,14 @@ defmodule Cannery.ActivityLog.ShotGroup do |> validate_required([:count, :ammo_group_id, :user_id]) end + def create_changeset(shot_group, _invalid_user, _invalid_ammo_group, attrs) do + shot_group + |> cast(attrs, [:count, :notes, :date]) + |> validate_number(:count, greater_than: 0) + |> validate_required([:count, :ammo_group_id, :user_id]) + |> add_error(:invalid, dgettext("errors", "Please select a valid user and ammo group")) + end + defp validate_create_shot_group_count(changeset, %AmmoGroup{count: ammo_group_count}) do if changeset |> Changeset.get_field(:count) > ammo_group_count do error = dgettext("errors", "Count must be less than %{count}", count: ammo_group_count) From 947659b207123152692f39c17b2fb7b00ee3c9f2 Mon Sep 17 00:00:00 2001 From: shibao Date: Mon, 4 Jul 2022 20:06:41 -0400 Subject: [PATCH 12/32] fix ammo_group changesets --- lib/cannery/ammo.ex | 55 +++++++++++-------- lib/cannery/ammo/ammo_group.ex | 38 +++++++++++-- .../components/move_ammo_group_component.ex | 2 +- .../live/ammo_group_live/form_component.ex | 23 +++++++- priv/gettext/de/LC_MESSAGES/errors.po | 25 +++++++-- priv/gettext/de/LC_MESSAGES/prompts.po | 4 +- priv/gettext/en/LC_MESSAGES/errors.po | 25 +++++++-- priv/gettext/en/LC_MESSAGES/prompts.po | 4 +- priv/gettext/errors.pot | 25 +++++++-- priv/gettext/es/LC_MESSAGES/errors.po | 25 +++++++-- priv/gettext/es/LC_MESSAGES/prompts.po | 4 +- priv/gettext/fr/LC_MESSAGES/errors.po | 25 +++++++-- priv/gettext/fr/LC_MESSAGES/prompts.po | 4 +- priv/gettext/prompts.pot | 4 +- test/cannery/ammo_test.exs | 4 -- 15 files changed, 196 insertions(+), 71 deletions(-) diff --git a/lib/cannery/ammo.ex b/lib/cannery/ammo.ex index ea9c853..3c62ab6 100644 --- a/lib/cannery/ammo.ex +++ b/lib/cannery/ammo.ex @@ -3,6 +3,7 @@ defmodule Cannery.Ammo do The Ammo context. """ + import CanneryWeb.Gettext import Ecto.Query, warn: false alias Cannery.{Accounts.User, Containers, Repo} alias Cannery.ActivityLog.ShotGroup @@ -350,18 +351,21 @@ defmodule Cannery.Ammo do def create_ammo_groups( %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, multiplier, - %User{id: user_id} = user + %User{} = user ) - when multiplier >= 1 and multiplier <= @ammo_group_create_limit do - # validate ammo type and container ids belong to user - _valid_ammo_type = get_ammo_type!(ammo_type_id, user) - _valid_container = Containers.get_container!(container_id, user) - + when multiplier >= 1 and multiplier <= @ammo_group_create_limit and + not (ammo_type_id |> is_nil()) and not (container_id |> is_nil()) do now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) changesets = Enum.map(1..multiplier, fn _count -> - %AmmoGroup{} |> AmmoGroup.create_changeset(attrs |> Map.put("user_id", user_id)) + %AmmoGroup{} + |> AmmoGroup.create_changeset( + get_ammo_type!(ammo_type_id, user), + Containers.get_container!(container_id, user), + user, + attrs + ) end) if changesets |> Enum.all?(fn %{valid?: valid} -> valid end) do @@ -386,8 +390,27 @@ defmodule Cannery.Ammo do end end - def create_ammo_groups(invalid_attrs, _multiplier, _user) do - {:error, %AmmoGroup{} |> AmmoGroup.create_changeset(invalid_attrs)} + def create_ammo_groups( + %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, + _multiplier, + user + ) + when not (ammo_type_id |> is_nil()) and not (container_id |> is_nil()) do + changeset = + %AmmoGroup{} + |> AmmoGroup.create_changeset( + get_ammo_type!(ammo_type_id, user), + Containers.get_container!(container_id, user), + user, + attrs + ) + |> Changeset.add_error(:multiplier, dgettext("errors", "Invalid multiplier")) + + {:error, changeset} + end + + def create_ammo_groups(invalid_attrs, _multiplier, user) do + {:error, %AmmoGroup{} |> AmmoGroup.create_changeset(nil, nil, user, invalid_attrs)} end @doc """ @@ -436,18 +459,4 @@ defmodule Cannery.Ammo do @spec delete_ammo_group!(AmmoGroup.t(), User.t()) :: AmmoGroup.t() def delete_ammo_group!(%AmmoGroup{user_id: user_id} = ammo_group, %User{id: user_id}), do: ammo_group |> Repo.delete!() - - @doc """ - Returns an `%Changeset{}` for tracking ammo_group changes. - - ## Examples - - iex> change_ammo_group(ammo_group) - %Changeset{data: %AmmoGroup{}} - - """ - @spec change_ammo_group(AmmoGroup.t()) :: Changeset.t(AmmoGroup.t()) - @spec change_ammo_group(AmmoGroup.t(), attrs :: map()) :: Changeset.t(AmmoGroup.t()) - def change_ammo_group(%AmmoGroup{} = ammo_group, attrs \\ %{}), - do: AmmoGroup.update_changeset(ammo_group, attrs) end diff --git a/lib/cannery/ammo/ammo_group.ex b/lib/cannery/ammo/ammo_group.ex index 1dfe618..09426f0 100644 --- a/lib/cannery/ammo/ammo_group.ex +++ b/lib/cannery/ammo/ammo_group.ex @@ -7,6 +7,7 @@ defmodule Cannery.Ammo.AmmoGroup do """ use Ecto.Schema + import CanneryWeb.Gettext import Ecto.Changeset alias Cannery.Ammo.{AmmoGroup, AmmoType} alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Containers.Container} @@ -48,22 +49,49 @@ defmodule Cannery.Ammo.AmmoGroup do @type id :: UUID.t() @doc false - @spec create_changeset(new_ammo_group(), attrs :: map()) :: Changeset.t(new_ammo_group()) - def create_changeset(ammo_group, attrs) do + @spec create_changeset( + new_ammo_group(), + AmmoType.t() | nil, + Container.t() | nil, + User.t(), + attrs :: map() + ) :: Changeset.t(new_ammo_group()) + def create_changeset( + ammo_group, + %AmmoType{id: ammo_type_id}, + %Container{id: container_id, user_id: user_id}, + %User{id: user_id}, + attrs + ) + when not (ammo_type_id |> is_nil()) and not (container_id |> is_nil()) and + not (user_id |> is_nil()) do ammo_group - |> cast(attrs, [:count, :price_paid, :notes, :staged, :ammo_type_id, :container_id, :user_id]) + |> change(ammo_type_id: ammo_type_id) + |> change(user_id: user_id) + |> change(container_id: container_id) + |> cast(attrs, [:count, :price_paid, :notes, :staged]) |> validate_number(:count, greater_than: 0) |> validate_required([:count, :staged, :ammo_type_id, :container_id, :user_id]) end + @doc """ + Invalid changeset, used to prompt user to select ammo type and container + """ + def create_changeset(ammo_group, _invalid_ammo_type, _invalid_container, _invalid_user, attrs) do + ammo_group + |> cast(attrs, [:ammo_type_id, :container_id]) + |> validate_required([:ammo_type_id, :container_id]) + |> add_error(:invalid, dgettext("errors", "Please select an ammo type and container")) + end + @doc false @spec update_changeset(t() | new_ammo_group(), attrs :: map()) :: Changeset.t(t() | new_ammo_group()) def update_changeset(ammo_group, attrs) do ammo_group - |> cast(attrs, [:count, :price_paid, :notes, :staged, :ammo_type_id, :container_id]) + |> cast(attrs, [:count, :price_paid, :notes, :staged]) |> validate_number(:count, greater_than_or_equal_to: 0) - |> validate_required([:count, :staged, :ammo_type_id, :container_id]) + |> validate_required([:count, :staged]) end @doc """ diff --git a/lib/cannery_web/components/move_ammo_group_component.ex b/lib/cannery_web/components/move_ammo_group_component.ex index 8a8c3de..06f6b03 100644 --- a/lib/cannery_web/components/move_ammo_group_component.ex +++ b/lib/cannery_web/components/move_ammo_group_component.ex @@ -22,7 +22,7 @@ defmodule CanneryWeb.Components.MoveAmmoGroupComponent do assigns, socket ) do - changeset = Ammo.change_ammo_group(ammo_group) + changeset = ammo_group |> AmmoGroup.update_changeset(%{}) containers = Containers.list_containers(current_user) diff --git a/lib/cannery_web/live/ammo_group_live/form_component.ex b/lib/cannery_web/live/ammo_group_live/form_component.ex index 2e79341..b17a1db 100644 --- a/lib/cannery_web/live/ammo_group_live/form_component.ex +++ b/lib/cannery_web/live/ammo_group_live/form_component.ex @@ -25,7 +25,7 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do socket = socket |> assign(:ammo_group_create_limit, @ammo_group_create_limit) - |> assign(:changeset, Ammo.change_ammo_group(ammo_group)) + |> assign(:changeset, ammo_group |> AmmoGroup.update_changeset(%{})) |> assign(:ammo_types, Ammo.list_ammo_types(current_user)) |> assign_new(:containers, fn -> Containers.list_containers(current_user) end) @@ -36,7 +36,7 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do def handle_event( "validate", %{"ammo_group" => ammo_group_params}, - %{assigns: %{action: action, ammo_group: ammo_group}} = socket + %{assigns: %{action: action, ammo_group: ammo_group, current_user: user}} = socket ) do changeset_action = case action do @@ -44,7 +44,24 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do :edit -> :update end - changeset = ammo_group |> Ammo.change_ammo_group(ammo_group_params) + changeset = + case action do + :new -> + ammo_type = + if ammo_group_params |> Map.has_key?("ammo_type_id"), + do: ammo_group_params |> Map.get("ammo_type_id") |> Ammo.get_ammo_type!(user), + else: nil + + container = + if ammo_group_params |> Map.has_key?("container_id"), + do: ammo_group_params |> Map.get("container_id") |> Containers.get_container!(user), + else: nil + + ammo_group |> AmmoGroup.create_changeset(ammo_type, container, user, ammo_group_params) + + :edit -> + ammo_group |> AmmoGroup.update_changeset(ammo_group_params) + end changeset = case changeset |> Changeset.apply_action(changeset_action) do diff --git a/priv/gettext/de/LC_MESSAGES/errors.po b/priv/gettext/de/LC_MESSAGES/errors.po index 7a3b94d..0289b9b 100644 --- a/priv/gettext/de/LC_MESSAGES/errors.po +++ b/priv/gettext/de/LC_MESSAGES/errors.po @@ -152,13 +152,13 @@ msgid "Tag could not be added" msgstr "Tag konnte nicht hinzugefügt werden" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:102 +#: lib/cannery/activity_log/shot_group.ex:115 msgid "Count must be at least 1" msgstr "Anzahl muss mindestens 1 sein" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:61 -#: lib/cannery/activity_log/shot_group.ex:98 +#: lib/cannery/activity_log/shot_group.ex:74 +#: lib/cannery/activity_log/shot_group.ex:111 msgid "Count must be less than %{count}" msgstr "Anzahl muss weniger als %{count} betragen" @@ -176,13 +176,28 @@ msgid "Tag could not be removed" msgstr "Tag konnte nicht gelöscht werden" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:126 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:143 msgid "Could not parse number of copies" msgstr "Konnte die Anzahl der Kopien nicht verstehen" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:111 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:128 msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" "Ungültige Nummer an Kopien. Muss zwischen 1 and %{max} liegen. War " "%{multiplier}" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo.ex:407 +msgid "Invalid multiplier" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo/ammo_group.ex:84 +msgid "Please select an ammo type and container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/activity_log/shot_group.ex:69 +msgid "Please select a valid user and ammo group" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/prompts.po b/priv/gettext/de/LC_MESSAGES/prompts.po index e4ca75a..82cf45f 100644 --- a/priv/gettext/de/LC_MESSAGES/prompts.po +++ b/priv/gettext/de/LC_MESSAGES/prompts.po @@ -283,12 +283,12 @@ msgid "Ammo unstaged succesfully" msgstr "Munition erfolgreich demarkiert" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:105 msgid "Ammo updated successfully" msgstr "Munitionsgruppe erfolgreich aktualisiert" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:164 msgid "Ammo added successfully" msgid_plural "Ammo added successfully" msgstr[0] "Munitionsgruppe erfolgreich aktualisiert" diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po index d303a0f..dfb3bf9 100644 --- a/priv/gettext/en/LC_MESSAGES/errors.po +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -139,13 +139,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:102 +#: lib/cannery/activity_log/shot_group.ex:115 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:61 -#: lib/cannery/activity_log/shot_group.ex:98 +#: lib/cannery/activity_log/shot_group.ex:74 +#: lib/cannery/activity_log/shot_group.ex:111 msgid "Count must be less than %{count}" msgstr "" @@ -161,11 +161,26 @@ msgid "Tag could not be removed" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:126 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:143 msgid "Could not parse number of copies" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:111 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:128 msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo.ex:407 +msgid "Invalid multiplier" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo/ammo_group.ex:84 +msgid "Please select an ammo type and container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/activity_log/shot_group.ex:69 +msgid "Please select a valid user and ammo group" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/prompts.po b/priv/gettext/en/LC_MESSAGES/prompts.po index ce081ea..19aac89 100644 --- a/priv/gettext/en/LC_MESSAGES/prompts.po +++ b/priv/gettext/en/LC_MESSAGES/prompts.po @@ -263,12 +263,12 @@ msgid "Ammo unstaged succesfully" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:105 msgid "Ammo updated successfully" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:164 msgid "Ammo added successfully" msgid_plural "Ammo added successfully" msgstr[0] "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 6b3a922..e2d2ce8 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -138,13 +138,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:102 +#: lib/cannery/activity_log/shot_group.ex:115 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:61 -#: lib/cannery/activity_log/shot_group.ex:98 +#: lib/cannery/activity_log/shot_group.ex:74 +#: lib/cannery/activity_log/shot_group.ex:111 msgid "Count must be less than %{count}" msgstr "" @@ -160,11 +160,26 @@ msgid "Tag could not be removed" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:126 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:143 msgid "Could not parse number of copies" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:111 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:128 msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo.ex:407 +msgid "Invalid multiplier" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo/ammo_group.ex:84 +msgid "Please select an ammo type and container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/activity_log/shot_group.ex:69 +msgid "Please select a valid user and ammo group" +msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/errors.po b/priv/gettext/es/LC_MESSAGES/errors.po index aac6461..d1a1f11 100644 --- a/priv/gettext/es/LC_MESSAGES/errors.po +++ b/priv/gettext/es/LC_MESSAGES/errors.po @@ -149,13 +149,13 @@ msgid "Tag could not be added" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:102 +#: lib/cannery/activity_log/shot_group.ex:115 msgid "Count must be at least 1" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:61 -#: lib/cannery/activity_log/shot_group.ex:98 +#: lib/cannery/activity_log/shot_group.ex:74 +#: lib/cannery/activity_log/shot_group.ex:111 msgid "Count must be less than %{count}" msgstr "" @@ -171,11 +171,26 @@ msgid "Tag could not be removed" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:126 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:143 msgid "Could not parse number of copies" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:111 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:128 msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo.ex:407 +msgid "Invalid multiplier" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo/ammo_group.ex:84 +msgid "Please select an ammo type and container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/activity_log/shot_group.ex:69 +msgid "Please select a valid user and ammo group" +msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/prompts.po b/priv/gettext/es/LC_MESSAGES/prompts.po index 095eda8..1504ad3 100644 --- a/priv/gettext/es/LC_MESSAGES/prompts.po +++ b/priv/gettext/es/LC_MESSAGES/prompts.po @@ -273,12 +273,12 @@ msgid "Ammo unstaged succesfully" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:105 msgid "Ammo updated successfully" msgstr "" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:164 msgid "Ammo added successfully" msgid_plural "Ammo added successfully" msgstr[0] "" diff --git a/priv/gettext/fr/LC_MESSAGES/errors.po b/priv/gettext/fr/LC_MESSAGES/errors.po index 013a47f..d391eff 100644 --- a/priv/gettext/fr/LC_MESSAGES/errors.po +++ b/priv/gettext/fr/LC_MESSAGES/errors.po @@ -153,13 +153,13 @@ msgid "Tag could not be added" msgstr "Le tag n’a pas pu être ajouté" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:102 +#: lib/cannery/activity_log/shot_group.ex:115 msgid "Count must be at least 1" msgstr "Le nombre doit être au moins égal à 1" #, elixir-autogen, elixir-format -#: lib/cannery/activity_log/shot_group.ex:61 -#: lib/cannery/activity_log/shot_group.ex:98 +#: lib/cannery/activity_log/shot_group.ex:74 +#: lib/cannery/activity_log/shot_group.ex:111 msgid "Count must be less than %{count}" msgstr "La quantité doit être inférieur à %{count}" @@ -177,11 +177,26 @@ msgid "Tag could not be removed" msgstr "Le tag n’a pas pu être retiré" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:126 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:143 msgid "Could not parse number of copies" msgstr "Impossible d'analyser le nombre de copies" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:111 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:128 msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "Nombre de copies invalide, doit être 1 et %{max}. Été %{multiplier}" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo.ex:407 +msgid "Invalid multiplier" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/ammo/ammo_group.ex:84 +msgid "Please select an ammo type and container" +msgstr "" + +#, elixir-autogen, elixir-format +#: lib/cannery/activity_log/shot_group.ex:69 +msgid "Please select a valid user and ammo group" +msgstr "" diff --git a/priv/gettext/fr/LC_MESSAGES/prompts.po b/priv/gettext/fr/LC_MESSAGES/prompts.po index 0328cab..3f5aae1 100644 --- a/priv/gettext/fr/LC_MESSAGES/prompts.po +++ b/priv/gettext/fr/LC_MESSAGES/prompts.po @@ -284,12 +284,12 @@ msgid "Ammo unstaged succesfully" msgstr "Groupe de munition désélectionner avec succès" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:105 msgid "Ammo updated successfully" msgstr "Groupe de munition mis à jour avec succès" #, elixir-autogen, elixir-format, fuzzy -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:164 msgid "Ammo added successfully" msgid_plural "Ammo added successfully" msgstr[0] "Groupe de munition mis à jour avec succès" diff --git a/priv/gettext/prompts.pot b/priv/gettext/prompts.pot index 364f8e4..7981b0a 100644 --- a/priv/gettext/prompts.pot +++ b/priv/gettext/prompts.pot @@ -262,12 +262,12 @@ msgid "Ammo unstaged succesfully" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:88 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:105 msgid "Ammo updated successfully" msgstr "" #, elixir-autogen, elixir-format -#: lib/cannery_web/live/ammo_group_live/form_component.ex:147 +#: lib/cannery_web/live/ammo_group_live/form_component.ex:164 msgid "Ammo added successfully" msgid_plural "Ammo added successfully" msgstr[0] "" diff --git a/test/cannery/ammo_test.exs b/test/cannery/ammo_test.exs index 2ae4e6e..317c5a5 100644 --- a/test/cannery/ammo_test.exs +++ b/test/cannery/ammo_test.exs @@ -180,9 +180,5 @@ defmodule Cannery.AmmoTest do Ammo.get_ammo_group!(ammo_group.id, current_user) end end - - test "change_ammo_group/1 returns a ammo_group changeset", %{ammo_group: ammo_group} do - assert %Changeset{} = Ammo.change_ammo_group(ammo_group) - end end end From 41bcc2f4568d6c4ff98f80c37536613844357fc3 Mon Sep 17 00:00:00 2001 From: shibao Date: Mon, 4 Jul 2022 20:19:03 -0400 Subject: [PATCH 13/32] =?UTF-8?q?add=20logo=20=F0=9F=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- assets/static/images/cannery.png | Bin 0 -> 85873 bytes assets/static/images/cannery.svg | 38 +++++++++++++++++ lib/cannery_web/components/topbar.ex | 14 ++++-- lib/cannery_web/live/home_live.ex | 8 ++++ priv/gettext/actions.pot | 4 +- priv/gettext/de/LC_MESSAGES/actions.po | 4 +- priv/gettext/de/LC_MESSAGES/default.po | 57 +++++++++++++++---------- priv/gettext/de/LC_MESSAGES/prompts.po | 4 +- priv/gettext/default.pot | 57 +++++++++++++++---------- priv/gettext/en/LC_MESSAGES/actions.po | 4 +- priv/gettext/en/LC_MESSAGES/default.po | 57 +++++++++++++++---------- priv/gettext/en/LC_MESSAGES/prompts.po | 4 +- priv/gettext/es/LC_MESSAGES/actions.po | 4 +- priv/gettext/es/LC_MESSAGES/default.po | 57 +++++++++++++++---------- priv/gettext/es/LC_MESSAGES/prompts.po | 4 +- priv/gettext/fr/LC_MESSAGES/actions.po | 4 +- priv/gettext/fr/LC_MESSAGES/default.po | 57 +++++++++++++++---------- priv/gettext/fr/LC_MESSAGES/prompts.po | 4 +- priv/gettext/prompts.pot | 4 +- 20 files changed, 248 insertions(+), 140 deletions(-) create mode 100644 assets/static/images/cannery.png create mode 100644 assets/static/images/cannery.svg diff --git a/README.md b/README.md index 6102d3a..418018b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Cannery -![screenshot](https://gitea.bubbletea.dev/shibao/cannery/raw/branch/stable/home.png) +![logo](https://gitea.bubbletea.dev/shibao/cannery/raw/branch/stable/assets/static/images/cannery.png) +![old screenshot](https://gitea.bubbletea.dev/shibao/cannery/raw/branch/stable/home.png) The self-hosted firearm tracker website. diff --git a/assets/static/images/cannery.png b/assets/static/images/cannery.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2652a2d2adaa8cbaffddbf48fcbd31c24981ff GIT binary patch literal 85873 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 literal 0 HcmV?d00001 diff --git a/assets/static/images/cannery.svg b/assets/static/images/cannery.svg new file mode 100644 index 0000000..e10f526 --- /dev/null +++ b/assets/static/images/cannery.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/cannery_web/components/topbar.ex b/lib/cannery_web/components/topbar.ex index 130f454..5843838 100644 --- a/lib/cannery_web/components/topbar.ex +++ b/lib/cannery_web/components/topbar.ex @@ -16,10 +16,16 @@ defmodule CanneryWeb.Components.Topbar do