Compare commits
	
		
			14 Commits
		
	
	
		
			0.8.5
			...
			0cae7c2940
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0cae7c2940 | |||
| 1e645b5bb8 | |||
| bab2b26c13 | |||
| 8c95536ffd | |||
| d9251c7e4c | |||
| fe4e4f4f17 | |||
| e5e5449e8b | |||
| 355752598c | |||
| 03f8a2e8a7 | |||
| 071eb1b3c9 | |||
| 2987e4ff37 | |||
| ca81924ebe | |||
| 40e4f6fe0a | |||
| 213dcca973 | 
							
								
								
									
										20
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,3 +1,23 @@ | |||||||
|  | # v0.9.1 | ||||||
|  | - Rename ammo_type's type to class to avoid confusion | ||||||
|  | - Code quality improvements | ||||||
|  |  | ||||||
|  | # v0.9.0 | ||||||
|  | - Add length limits to all string fields | ||||||
|  | - Add selectable ammo types | ||||||
|  | - Improve onboarding experience slightly | ||||||
|  | - Remove show used view from a container since it doesn't really make that much | ||||||
|  |   sense | ||||||
|  |  | ||||||
|  | # v0.8.6 | ||||||
|  | - Fix duplicate entries showing up | ||||||
|  | - Show ammo packs under a type in a table by default | ||||||
|  | - Only show historical ammo type information when displaying "Show used" in table | ||||||
|  | - Only show historical ammo pack information when displaying "Show used" in table | ||||||
|  | - Fix some values not being sorted in tables properly | ||||||
|  | - Code quality improvements | ||||||
|  | - Show link to ammo pack in ammo pack table while viewing ammo type | ||||||
|  |  | ||||||
| # v0.8.5 | # v0.8.5 | ||||||
| - Add link in readme to github mirror | - Add link in readme to github mirror | ||||||
| - Fix tables unable to sort on empty dates | - Fix tables unable to sort on empty dates | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ module.exports = (env, options) => { | |||||||
|         { |         { | ||||||
|           test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/, |           test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/, | ||||||
|           type: 'asset/resource', |           type: 'asset/resource', | ||||||
|           generator: { filename: 'fonts/[name][ext]' } |           generator: { filename: 'fonts/[name].[ext]' } | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -48,8 +48,9 @@ defmodule Cannery.Accounts.Invite do | |||||||
|     %__MODULE__{} |     %__MODULE__{} | ||||||
|     |> change(token: token, created_by_id: user_id) |     |> change(token: token, created_by_id: user_id) | ||||||
|     |> cast(attrs, [:name, :uses_left, :disabled_at]) |     |> cast(attrs, [:name, :uses_left, :disabled_at]) | ||||||
|     |> validate_required([:name, :token, :created_by_id]) |     |> validate_length(:name, max: 255) | ||||||
|     |> validate_number(:uses_left, greater_than_or_equal_to: 0) |     |> validate_number(:uses_left, greater_than_or_equal_to: 0) | ||||||
|  |     |> validate_required([:name, :token, :created_by_id]) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc false |   @doc false | ||||||
| @@ -57,7 +58,8 @@ defmodule Cannery.Accounts.Invite do | |||||||
|   def update_changeset(invite, attrs) do |   def update_changeset(invite, attrs) do | ||||||
|     invite |     invite | ||||||
|     |> cast(attrs, [:name, :uses_left, :disabled_at]) |     |> cast(attrs, [:name, :uses_left, :disabled_at]) | ||||||
|     |> validate_required([:name]) |     |> validate_length(:name, max: 255) | ||||||
|     |> validate_number(:uses_left, greater_than_or_equal_to: 0) |     |> validate_number(:uses_left, greater_than_or_equal_to: 0) | ||||||
|  |     |> validate_required([:name]) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -79,6 +79,7 @@ defmodule Cannery.Accounts.User do | |||||||
|     %User{} |     %User{} | ||||||
|     |> cast(attrs, [:email, :password, :locale]) |     |> cast(attrs, [:email, :password, :locale]) | ||||||
|     |> put_change(:invite_id, if(invite, do: invite.id)) |     |> put_change(:invite_id, if(invite, do: invite.id)) | ||||||
|  |     |> validate_length(:locale, max: 255) | ||||||
|     |> validate_email() |     |> validate_email() | ||||||
|     |> validate_password(opts) |     |> validate_password(opts) | ||||||
|   end |   end | ||||||
| @@ -209,6 +210,7 @@ defmodule Cannery.Accounts.User do | |||||||
|   def locale_changeset(user_or_changeset, locale) do |   def locale_changeset(user_or_changeset, locale) do | ||||||
|     user_or_changeset |     user_or_changeset | ||||||
|     |> cast(%{"locale" => locale}, [:locale]) |     |> cast(%{"locale" => locale}, [:locale]) | ||||||
|  |     |> validate_length(:locale, max: 255) | ||||||
|     |> validate_required(:locale) |     |> validate_required(:locale) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -6,38 +6,53 @@ defmodule Cannery.ActivityLog do | |||||||
|   import Ecto.Query, warn: false |   import Ecto.Query, warn: false | ||||||
|   alias Cannery.Ammo.{AmmoGroup, AmmoType} |   alias Cannery.Ammo.{AmmoGroup, AmmoType} | ||||||
|   alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Repo} |   alias Cannery.{Accounts.User, ActivityLog.ShotGroup, Repo} | ||||||
|   alias Ecto.Multi |   alias Ecto.{Multi, Queryable} | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
|   Returns the list of shot_groups. |   Returns the list of shot_groups. | ||||||
|  |  | ||||||
|   ## Examples |   ## Examples | ||||||
|  |  | ||||||
|       iex> list_shot_groups(%User{id: 123}) |       iex> list_shot_groups(:all, %User{id: 123}) | ||||||
|       [%ShotGroup{}, ...] |       [%ShotGroup{}, ...] | ||||||
|  |  | ||||||
|       iex> list_shot_groups("cool", %User{id: 123}) |       iex> list_shot_groups("cool", :all, %User{id: 123}) | ||||||
|       [%ShotGroup{notes: "My cool shot group"}, ...] |       [%ShotGroup{notes: "My cool shot group"}, ...] | ||||||
|  |  | ||||||
|  |       iex> list_shot_groups("cool", :rifle, %User{id: 123}) | ||||||
|  |       [%ShotGroup{notes: "Shot some rifle rounds"}, ...] | ||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec list_shot_groups(User.t()) :: [ShotGroup.t()] |   @spec list_shot_groups(AmmoType.class() | :all, User.t()) :: [ShotGroup.t()] | ||||||
|   @spec list_shot_groups(search :: nil | String.t(), User.t()) :: [ShotGroup.t()] |   @spec list_shot_groups(search :: nil | String.t(), AmmoType.class() | :all, User.t()) :: | ||||||
|   def list_shot_groups(search \\ nil, user) |           [ShotGroup.t()] | ||||||
|  |   def list_shot_groups(search \\ nil, type, %{id: user_id}) do | ||||||
|   def list_shot_groups(search, %{id: user_id}) when search |> is_nil() or search == "", |     from(sg in ShotGroup, | ||||||
|     do: Repo.all(from sg in ShotGroup, where: sg.user_id == ^user_id) |       as: :sg, | ||||||
|  |  | ||||||
|   def list_shot_groups(search, %{id: user_id}) when search |> is_binary() do |  | ||||||
|     trimmed_search = String.trim(search) |  | ||||||
|  |  | ||||||
|     Repo.all( |  | ||||||
|       from sg in ShotGroup, |  | ||||||
|       left_join: ag in AmmoGroup, |       left_join: ag in AmmoGroup, | ||||||
|  |       as: :ag, | ||||||
|       on: sg.ammo_group_id == ag.id, |       on: sg.ammo_group_id == ag.id, | ||||||
|       left_join: at in AmmoType, |       left_join: at in AmmoType, | ||||||
|  |       as: :at, | ||||||
|       on: ag.ammo_type_id == at.id, |       on: ag.ammo_type_id == at.id, | ||||||
|       where: sg.user_id == ^user_id, |       where: sg.user_id == ^user_id, | ||||||
|         where: |       distinct: sg.id | ||||||
|  |     ) | ||||||
|  |     |> list_shot_groups_search(search) | ||||||
|  |     |> list_shot_groups_filter_type(type) | ||||||
|  |     |> Repo.all() | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   @spec list_shot_groups_search(Queryable.t(), search :: String.t() | nil) :: | ||||||
|  |           Queryable.t() | ||||||
|  |   defp list_shot_groups_search(query, search) when search in ["", nil], do: query | ||||||
|  |  | ||||||
|  |   defp list_shot_groups_search(query, search) when search |> is_binary() do | ||||||
|  |     trimmed_search = String.trim(search) | ||||||
|  |  | ||||||
|  |     query | ||||||
|  |     |> where( | ||||||
|  |       [sg: sg, ag: ag, at: at], | ||||||
|       fragment( |       fragment( | ||||||
|         "? @@ websearch_to_tsquery('english', ?)", |         "? @@ websearch_to_tsquery('english', ?)", | ||||||
|         sg.search, |         sg.search, | ||||||
| @@ -52,18 +67,31 @@ defmodule Cannery.ActivityLog do | |||||||
|           "? @@ websearch_to_tsquery('english', ?)", |           "? @@ websearch_to_tsquery('english', ?)", | ||||||
|           at.search, |           at.search, | ||||||
|           ^trimmed_search |           ^trimmed_search | ||||||
|             ), |         ) | ||||||
|         order_by: { |     ) | ||||||
|  |     |> order_by([sg: sg], { | ||||||
|       :desc, |       :desc, | ||||||
|       fragment( |       fragment( | ||||||
|         "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", |         "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", | ||||||
|         sg.search, |         sg.search, | ||||||
|         ^trimmed_search |         ^trimmed_search | ||||||
|       ) |       ) | ||||||
|         } |     }) | ||||||
|     ) |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @spec list_shot_groups_filter_type(Queryable.t(), AmmoType.class() | :all) :: | ||||||
|  |           Queryable.t() | ||||||
|  |   defp list_shot_groups_filter_type(query, :rifle), | ||||||
|  |     do: query |> where([at: at], at.class == :rifle) | ||||||
|  |  | ||||||
|  |   defp list_shot_groups_filter_type(query, :pistol), | ||||||
|  |     do: query |> where([at: at], at.class == :pistol) | ||||||
|  |  | ||||||
|  |   defp list_shot_groups_filter_type(query, :shotgun), | ||||||
|  |     do: query |> where([at: at], at.class == :shotgun) | ||||||
|  |  | ||||||
|  |   defp list_shot_groups_filter_type(query, _all), do: query | ||||||
|  |  | ||||||
|   @spec list_shot_groups_for_ammo_group(AmmoGroup.t(), User.t()) :: [ShotGroup.t()] |   @spec list_shot_groups_for_ammo_group(AmmoGroup.t(), User.t()) :: [ShotGroup.t()] | ||||||
|   def list_shot_groups_for_ammo_group( |   def list_shot_groups_for_ammo_group( | ||||||
|         %AmmoGroup{id: ammo_group_id, user_id: user_id}, |         %AmmoGroup{id: ammo_group_id, user_id: user_id}, | ||||||
|   | |||||||
| @@ -61,6 +61,7 @@ defmodule Cannery.ActivityLog.ShotGroup do | |||||||
|     |> change(user_id: user_id) |     |> change(user_id: user_id) | ||||||
|     |> change(ammo_group_id: ammo_group_id) |     |> change(ammo_group_id: ammo_group_id) | ||||||
|     |> cast(attrs, [:count, :notes, :date]) |     |> cast(attrs, [:count, :notes, :date]) | ||||||
|  |     |> validate_length(:notes, max: 255) | ||||||
|     |> validate_create_shot_group_count(ammo_group) |     |> validate_create_shot_group_count(ammo_group) | ||||||
|     |> validate_required([:date, :ammo_group_id, :user_id]) |     |> validate_required([:date, :ammo_group_id, :user_id]) | ||||||
|   end |   end | ||||||
| @@ -68,6 +69,7 @@ defmodule Cannery.ActivityLog.ShotGroup do | |||||||
|   def create_changeset(shot_group, _invalid_user, _invalid_ammo_group, attrs) do |   def create_changeset(shot_group, _invalid_user, _invalid_ammo_group, attrs) do | ||||||
|     shot_group |     shot_group | ||||||
|     |> cast(attrs, [:count, :notes, :date]) |     |> cast(attrs, [:count, :notes, :date]) | ||||||
|  |     |> validate_length(:notes, max: 255) | ||||||
|     |> validate_required([:ammo_group_id, :user_id]) |     |> validate_required([:ammo_group_id, :user_id]) | ||||||
|     |> add_error(:invalid, dgettext("errors", "Please select a valid user and ammo pack")) |     |> add_error(:invalid, dgettext("errors", "Please select a valid user and ammo pack")) | ||||||
|   end |   end | ||||||
| @@ -99,6 +101,7 @@ defmodule Cannery.ActivityLog.ShotGroup do | |||||||
|   def update_changeset(%__MODULE__{} = shot_group, user, attrs) do |   def update_changeset(%__MODULE__{} = shot_group, user, attrs) do | ||||||
|     shot_group |     shot_group | ||||||
|     |> cast(attrs, [:count, :notes, :date]) |     |> cast(attrs, [:count, :notes, :date]) | ||||||
|  |     |> validate_length(:notes, max: 255) | ||||||
|     |> validate_number(:count, greater_than: 0) |     |> validate_number(:count, greater_than: 0) | ||||||
|     |> validate_required([:count, :date]) |     |> validate_required([:count, :date]) | ||||||
|     |> validate_update_shot_group_count(shot_group, user) |     |> validate_update_shot_group_count(shot_group, user) | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ defmodule Cannery.Ammo do | |||||||
|   alias Cannery.Containers.{Container, ContainerTag, Tag} |   alias Cannery.Containers.{Container, ContainerTag, Tag} | ||||||
|   alias Cannery.{ActivityLog, ActivityLog.ShotGroup} |   alias Cannery.{ActivityLog, ActivityLog.ShotGroup} | ||||||
|   alias Cannery.Ammo.{AmmoGroup, AmmoType} |   alias Cannery.Ammo.{AmmoGroup, AmmoType} | ||||||
|   alias Ecto.Changeset |   alias Ecto.{Changeset, Queryable} | ||||||
|  |  | ||||||
|   @ammo_group_create_limit 10_000 |   @ammo_group_create_limit 10_000 | ||||||
|   @ammo_group_preloads [:ammo_type] |   @ammo_group_preloads [:ammo_type] | ||||||
| @@ -20,50 +20,70 @@ defmodule Cannery.Ammo do | |||||||
|  |  | ||||||
|   ## Examples |   ## Examples | ||||||
|  |  | ||||||
|       iex> list_ammo_types(%User{id: 123}) |       iex> list_ammo_types(%User{id: 123}, :all) | ||||||
|       [%AmmoType{}, ...] |       [%AmmoType{}, ...] | ||||||
|  |  | ||||||
|       iex> list_ammo_types("cool", %User{id: 123}) |       iex> list_ammo_types("cool", %User{id: 123}, :shotgun) | ||||||
|       [%AmmoType{name: "My cool ammo type"}, ...] |       [%AmmoType{name: "My cool ammo type", class: :shotgun}, ...] | ||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec list_ammo_types(User.t()) :: [AmmoType.t()] |   @spec list_ammo_types(User.t(), AmmoType.class() | :all) :: [AmmoType.t()] | ||||||
|   @spec list_ammo_types(search :: nil | String.t(), User.t()) :: [AmmoType.t()] |   @spec list_ammo_types(search :: nil | String.t(), User.t(), AmmoType.class() | :all) :: | ||||||
|   def list_ammo_types(search \\ nil, user) |           [AmmoType.t()] | ||||||
|  |   def list_ammo_types(search \\ nil, user, type) | ||||||
|  |  | ||||||
|   def list_ammo_types(search, %{id: user_id}) when search |> is_nil() or search == "" do |   def list_ammo_types(search, %{id: user_id}, type) do | ||||||
|     Repo.all( |     from(at in AmmoType, | ||||||
|       from at in AmmoType, |       as: :at, | ||||||
|       where: at.user_id == ^user_id, |       where: at.user_id == ^user_id, | ||||||
|         order_by: at.name, |  | ||||||
|       preload: ^@ammo_type_preloads |       preload: ^@ammo_type_preloads | ||||||
|     ) |     ) | ||||||
|  |     |> list_ammo_types_filter_type(type) | ||||||
|  |     |> list_ammo_types_filter_search(search) | ||||||
|  |     |> Repo.all() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def list_ammo_types(search, %{id: user_id}) when search |> is_binary() do |   @spec list_ammo_types_filter_search(Queryable.t(), search :: String.t() | nil) :: Queryable.t() | ||||||
|  |   defp list_ammo_types_filter_search(query, search) when search in ["", nil], | ||||||
|  |     do: query |> order_by([at: at], at.name) | ||||||
|  |  | ||||||
|  |   defp list_ammo_types_filter_search(query, search) when search |> is_binary() do | ||||||
|     trimmed_search = String.trim(search) |     trimmed_search = String.trim(search) | ||||||
|  |  | ||||||
|     Repo.all( |     query | ||||||
|       from at in AmmoType, |     |> where( | ||||||
|         where: at.user_id == ^user_id, |       [at: at], | ||||||
|         where: |  | ||||||
|       fragment( |       fragment( | ||||||
|         "? @@ websearch_to_tsquery('english', ?)", |         "? @@ websearch_to_tsquery('english', ?)", | ||||||
|         at.search, |         at.search, | ||||||
|         ^trimmed_search |         ^trimmed_search | ||||||
|           ), |       ) | ||||||
|         order_by: { |     ) | ||||||
|  |     |> order_by( | ||||||
|  |       [at: at], | ||||||
|  |       { | ||||||
|         :desc, |         :desc, | ||||||
|         fragment( |         fragment( | ||||||
|           "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", |           "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)", | ||||||
|           at.search, |           at.search, | ||||||
|           ^trimmed_search |           ^trimmed_search | ||||||
|         ) |         ) | ||||||
|         }, |       } | ||||||
|         preload: ^@ammo_type_preloads |  | ||||||
|     ) |     ) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @spec list_ammo_types_filter_type(Queryable.t(), AmmoType.class() | :all) :: Queryable.t() | ||||||
|  |   defp list_ammo_types_filter_type(query, :rifle), | ||||||
|  |     do: query |> where([at: at], at.class == :rifle) | ||||||
|  |  | ||||||
|  |   defp list_ammo_types_filter_type(query, :pistol), | ||||||
|  |     do: query |> where([at: at], at.class == :pistol) | ||||||
|  |  | ||||||
|  |   defp list_ammo_types_filter_type(query, :shotgun), | ||||||
|  |     do: query |> where([at: at], at.class == :shotgun) | ||||||
|  |  | ||||||
|  |   defp list_ammo_types_filter_type(query, _all), do: query | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
|   Returns a count of ammo_types. |   Returns a count of ammo_types. | ||||||
|  |  | ||||||
| @@ -80,7 +100,7 @@ defmodule Cannery.Ammo do | |||||||
|         where: at.user_id == ^user_id, |         where: at.user_id == ^user_id, | ||||||
|         select: count(at.id), |         select: count(at.id), | ||||||
|         distinct: true |         distinct: true | ||||||
|     ) |     ) || 0 | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
| @@ -375,36 +395,31 @@ defmodule Cannery.Ammo do | |||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec list_ammo_groups_for_type(AmmoType.t(), User.t()) :: [AmmoGroup.t()] |   @spec list_ammo_groups_for_type(AmmoType.t(), User.t()) :: [AmmoGroup.t()] | ||||||
|   @spec list_ammo_groups_for_type(AmmoType.t(), User.t(), include_empty :: boolean()) :: |   @spec list_ammo_groups_for_type(AmmoType.t(), User.t(), show_used :: boolean()) :: | ||||||
|           [AmmoGroup.t()] |           [AmmoGroup.t()] | ||||||
|   def list_ammo_groups_for_type(ammo_type, user, include_empty \\ false) |   def list_ammo_groups_for_type(ammo_type, user, show_used \\ false) | ||||||
|  |  | ||||||
|   def list_ammo_groups_for_type( |   def list_ammo_groups_for_type( | ||||||
|         %AmmoType{id: ammo_type_id, user_id: user_id}, |         %AmmoType{id: ammo_type_id, user_id: user_id}, | ||||||
|         %User{id: user_id}, |         %User{id: user_id}, | ||||||
|         true = _include_empty |         show_used | ||||||
|       ) do |       ) do | ||||||
|     Repo.all( |     from(ag in AmmoGroup, | ||||||
|       from ag in AmmoGroup, |       as: :ag, | ||||||
|       where: ag.ammo_type_id == ^ammo_type_id, |       where: ag.ammo_type_id == ^ammo_type_id, | ||||||
|       where: ag.user_id == ^user_id, |       where: ag.user_id == ^user_id, | ||||||
|       preload: ^@ammo_group_preloads |       preload: ^@ammo_group_preloads | ||||||
|     ) |     ) | ||||||
|  |     |> list_ammo_groups_for_type_show_used(show_used) | ||||||
|  |     |> Repo.all() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def list_ammo_groups_for_type( |   @spec list_ammo_groups_for_type_show_used(Queryable.t(), show_used :: boolean()) :: | ||||||
|         %AmmoType{id: ammo_type_id, user_id: user_id}, |           Queryable.t() | ||||||
|         %User{id: user_id}, |   def list_ammo_groups_for_type_show_used(query, false), | ||||||
|         false = _include_empty |     do: query |> where([ag: ag], ag.count > 0) | ||||||
|       ) do |  | ||||||
|     Repo.all( |   def list_ammo_groups_for_type_show_used(query, _true), do: query | ||||||
|       from ag in AmmoGroup, |  | ||||||
|         where: ag.ammo_type_id == ^ammo_type_id, |  | ||||||
|         where: ag.user_id == ^user_id, |  | ||||||
|         where: not (ag.count == 0), |  | ||||||
|         preload: ^@ammo_group_preloads |  | ||||||
|     ) |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
|   Returns the list of ammo_groups for a user and container. |   Returns the list of ammo_groups for a user and container. | ||||||
| @@ -413,50 +428,86 @@ defmodule Cannery.Ammo do | |||||||
|  |  | ||||||
|       iex> list_ammo_groups_for_container( |       iex> list_ammo_groups_for_container( | ||||||
|       ...>   %Container{id: 123, user_id: 456}, |       ...>   %Container{id: 123, user_id: 456}, | ||||||
|  |       ...>   :rifle, | ||||||
|       ...>   %User{id: 456} |       ...>   %User{id: 456} | ||||||
|       ...> ) |       ...> ) | ||||||
|       [%AmmoGroup{}, ...] |       [%AmmoGroup{}, ...] | ||||||
|  |  | ||||||
|       iex> list_ammo_groups_for_container( |       iex> list_ammo_groups_for_container( | ||||||
|       ...>   %Container{id: 123, user_id: 456}, |       ...>   %Container{id: 123, user_id: 456}, | ||||||
|       ...>   %User{id: 456}, |       ...>   :all, | ||||||
|       ...>   true |       ...>   %User{id: 456} | ||||||
|       ...> ) |       ...> ) | ||||||
|       [%AmmoGroup{}, %AmmoGroup{}, ...] |       [%AmmoGroup{}, %AmmoGroup{}, ...] | ||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec list_ammo_groups_for_container(Container.t(), User.t()) :: [AmmoGroup.t()] |   @spec list_ammo_groups_for_container( | ||||||
|   @spec list_ammo_groups_for_container(Container.t(), User.t(), include_empty :: boolean()) :: |           Container.t(), | ||||||
|           [AmmoGroup.t()] |           AmmoType.t() | :all, | ||||||
|   def list_ammo_groups_for_container(container, user, include_empty \\ false) |           User.t() | ||||||
|  |         ) :: [AmmoGroup.t()] | ||||||
|   def list_ammo_groups_for_container( |   def list_ammo_groups_for_container( | ||||||
|         %Container{id: container_id, user_id: user_id}, |         %Container{id: container_id, user_id: user_id}, | ||||||
|         %User{id: user_id}, |         type, | ||||||
|         true = _include_empty |         %User{id: user_id} | ||||||
|       ) do |       ) do | ||||||
|     Repo.all( |     from(ag in AmmoGroup, | ||||||
|       from ag in AmmoGroup, |       as: :ag, | ||||||
|  |       join: at in assoc(ag, :ammo_type), | ||||||
|  |       as: :at, | ||||||
|       where: ag.container_id == ^container_id, |       where: ag.container_id == ^container_id, | ||||||
|       where: ag.user_id == ^user_id, |       where: ag.user_id == ^user_id, | ||||||
|  |       where: ag.count > 0, | ||||||
|       preload: ^@ammo_group_preloads |       preload: ^@ammo_group_preloads | ||||||
|     ) |     ) | ||||||
|  |     |> list_ammo_groups_for_container_filter_type(type) | ||||||
|  |     |> Repo.all() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def list_ammo_groups_for_container( |   @spec list_ammo_groups_for_container_filter_type(Queryable.t(), AmmoType.class() | :all) :: | ||||||
|         %Container{id: container_id, user_id: user_id}, |           Queryable.t() | ||||||
|         %User{id: user_id}, |   defp list_ammo_groups_for_container_filter_type(query, :rifle), | ||||||
|         false = _include_empty |     do: query |> where([at: at], at.class == :rifle) | ||||||
|       ) do |  | ||||||
|     Repo.all( |   defp list_ammo_groups_for_container_filter_type(query, :pistol), | ||||||
|       from ag in AmmoGroup, |     do: query |> where([at: at], at.class == :pistol) | ||||||
|         where: ag.container_id == ^container_id, |  | ||||||
|  |   defp list_ammo_groups_for_container_filter_type(query, :shotgun), | ||||||
|  |     do: query |> where([at: at], at.class == :shotgun) | ||||||
|  |  | ||||||
|  |   defp list_ammo_groups_for_container_filter_type(query, _all), do: query | ||||||
|  |  | ||||||
|  |   @doc """ | ||||||
|  |   Returns a count of ammo_groups. | ||||||
|  |  | ||||||
|  |   ## Examples | ||||||
|  |  | ||||||
|  |       iex> get_ammo_groups_count!(%User{id: 123}) | ||||||
|  |       3 | ||||||
|  |  | ||||||
|  |       iex> get_ammo_groups_count!(%User{id: 123}, true) | ||||||
|  |       4 | ||||||
|  |  | ||||||
|  |   """ | ||||||
|  |   @spec get_ammo_groups_count!(User.t()) :: integer() | ||||||
|  |   @spec get_ammo_groups_count!(User.t(), show_used :: boolean()) :: integer() | ||||||
|  |   def get_ammo_groups_count!(%User{id: user_id}, show_used \\ false) do | ||||||
|  |     from(ag in AmmoGroup, | ||||||
|  |       as: :ag, | ||||||
|       where: ag.user_id == ^user_id, |       where: ag.user_id == ^user_id, | ||||||
|         where: not (ag.count == 0), |       select: count(ag.id), | ||||||
|         preload: ^@ammo_group_preloads |       distinct: true | ||||||
|     ) |     ) | ||||||
|  |     |> get_ammo_groups_count_show_used(show_used) | ||||||
|  |     |> Repo.one() || 0 | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @spec get_ammo_groups_count_show_used(Queryable.t(), show_used :: boolean()) :: Queryable.t() | ||||||
|  |   defp get_ammo_groups_count_show_used(query, false), | ||||||
|  |     do: query |> where([ag: ag], ag.count > 0) | ||||||
|  |  | ||||||
|  |   defp get_ammo_groups_count_show_used(query, _true), do: query | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
|   Returns the count of ammo_groups for an ammo type. |   Returns the count of ammo_groups for an ammo type. | ||||||
|  |  | ||||||
| @@ -477,15 +528,15 @@ defmodule Cannery.Ammo do | |||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec get_ammo_groups_count_for_type(AmmoType.t(), User.t()) :: non_neg_integer() |   @spec get_ammo_groups_count_for_type(AmmoType.t(), User.t()) :: non_neg_integer() | ||||||
|   @spec get_ammo_groups_count_for_type(AmmoType.t(), User.t(), include_empty :: boolean()) :: |   @spec get_ammo_groups_count_for_type(AmmoType.t(), User.t(), show_used :: boolean()) :: | ||||||
|           non_neg_integer() |           non_neg_integer() | ||||||
|   def get_ammo_groups_count_for_type( |   def get_ammo_groups_count_for_type( | ||||||
|         %AmmoType{id: ammo_type_id} = ammo_type, |         %AmmoType{id: ammo_type_id} = ammo_type, | ||||||
|         user, |         user, | ||||||
|         include_empty \\ false |         show_used \\ false | ||||||
|       ) do |       ) do | ||||||
|     [ammo_type] |     [ammo_type] | ||||||
|     |> get_ammo_groups_count_for_types(user, include_empty) |     |> get_ammo_groups_count_for_types(user, show_used) | ||||||
|     |> Map.get(ammo_type_id, 0) |     |> Map.get(ammo_type_id, 0) | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -510,28 +561,31 @@ defmodule Cannery.Ammo do | |||||||
|   """ |   """ | ||||||
|   @spec get_ammo_groups_count_for_types([AmmoType.t()], User.t()) :: |   @spec get_ammo_groups_count_for_types([AmmoType.t()], User.t()) :: | ||||||
|           %{optional(AmmoType.id()) => non_neg_integer()} |           %{optional(AmmoType.id()) => non_neg_integer()} | ||||||
|   @spec get_ammo_groups_count_for_types([AmmoType.t()], User.t(), include_empty :: boolean()) :: |   @spec get_ammo_groups_count_for_types([AmmoType.t()], User.t(), show_used :: boolean()) :: | ||||||
|           %{optional(AmmoType.id()) => non_neg_integer()} |           %{optional(AmmoType.id()) => non_neg_integer()} | ||||||
|   def get_ammo_groups_count_for_types(ammo_types, %User{id: user_id}, include_empty \\ false) do |   def get_ammo_groups_count_for_types(ammo_types, %User{id: user_id}, show_used \\ false) do | ||||||
|     ammo_type_ids = |     ammo_type_ids = | ||||||
|       ammo_types |       ammo_types | ||||||
|       |> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end) |       |> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end) | ||||||
|  |  | ||||||
|     from(ag in AmmoGroup, |     from(ag in AmmoGroup, | ||||||
|  |       as: :ag, | ||||||
|       where: ag.user_id == ^user_id, |       where: ag.user_id == ^user_id, | ||||||
|       where: ag.ammo_type_id in ^ammo_type_ids, |       where: ag.ammo_type_id in ^ammo_type_ids, | ||||||
|       group_by: ag.ammo_type_id, |       group_by: ag.ammo_type_id, | ||||||
|       select: {ag.ammo_type_id, count(ag.id)} |       select: {ag.ammo_type_id, count(ag.id)} | ||||||
|     ) |     ) | ||||||
|     |> maybe_include_empty(include_empty) |     |> get_ammo_groups_count_for_types_maybe_show_used(show_used) | ||||||
|     |> Repo.all() |     |> Repo.all() | ||||||
|     |> Map.new() |     |> Map.new() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp maybe_include_empty(query, true), do: query |   @spec get_ammo_groups_count_for_types_maybe_show_used(Queryable.t(), show_used :: boolean()) :: | ||||||
|  |           Queryable.t() | ||||||
|  |   defp get_ammo_groups_count_for_types_maybe_show_used(query, true), do: query | ||||||
|  |  | ||||||
|   defp maybe_include_empty(query, _false) do |   defp get_ammo_groups_count_for_types_maybe_show_used(query, _false) do | ||||||
|     query |> where([ag], not (ag.count == 0)) |     query |> where([ag: ag], not (ag.count == 0)) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
| @@ -628,7 +682,7 @@ defmodule Cannery.Ammo do | |||||||
|     Repo.all( |     Repo.all( | ||||||
|       from ag in AmmoGroup, |       from ag in AmmoGroup, | ||||||
|         where: ag.container_id in ^container_ids, |         where: ag.container_id in ^container_ids, | ||||||
|         where: ag.count != 0, |         where: ag.count > 0, | ||||||
|         group_by: ag.container_id, |         group_by: ag.container_id, | ||||||
|         select: {ag.container_id, count(ag.id)} |         select: {ag.container_id, count(ag.id)} | ||||||
|     ) |     ) | ||||||
| @@ -690,17 +744,20 @@ defmodule Cannery.Ammo do | |||||||
|       iex> list_ammo_groups(%User{id: 123}) |       iex> list_ammo_groups(%User{id: 123}) | ||||||
|       [%AmmoGroup{}, ...] |       [%AmmoGroup{}, ...] | ||||||
|  |  | ||||||
|       iex> list_ammo_groups("cool", true, %User{id: 123}) |       iex> list_ammo_groups("cool", %User{id: 123}, true) | ||||||
|       [%AmmoGroup{notes: "My cool ammo group"}, ...] |       [%AmmoGroup{notes: "My cool ammo group"}, ...] | ||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec list_ammo_groups(User.t()) :: [AmmoGroup.t()] |   @spec list_ammo_groups(search :: String.t() | nil, AmmoType.class() | :all, User.t()) :: | ||||||
|   @spec list_ammo_groups(search :: nil | String.t(), User.t()) :: [AmmoGroup.t()] |  | ||||||
|   @spec list_ammo_groups(search :: nil | String.t(), include_empty :: boolean(), User.t()) :: |  | ||||||
|           [AmmoGroup.t()] |           [AmmoGroup.t()] | ||||||
|   def list_ammo_groups(search \\ nil, include_empty \\ false, %{id: user_id}) do |   @spec list_ammo_groups( | ||||||
|     from( |           search :: nil | String.t(), | ||||||
|       ag in AmmoGroup, |           AmmoType.class() | :all, | ||||||
|  |           User.t(), | ||||||
|  |           show_used :: boolean() | ||||||
|  |         ) :: [AmmoGroup.t()] | ||||||
|  |   def list_ammo_groups(search, type, %{id: user_id}, show_used \\ false) do | ||||||
|  |     from(ag in AmmoGroup, | ||||||
|       as: :ag, |       as: :ag, | ||||||
|       join: at in assoc(ag, :ammo_type), |       join: at in assoc(ag, :ammo_type), | ||||||
|       as: :at, |       as: :at, | ||||||
| @@ -715,19 +772,35 @@ defmodule Cannery.Ammo do | |||||||
|       on: c.user_id == t.user_id, |       on: c.user_id == t.user_id, | ||||||
|       as: :t, |       as: :t, | ||||||
|       where: ag.user_id == ^user_id, |       where: ag.user_id == ^user_id, | ||||||
|  |       distinct: ag.id, | ||||||
|       preload: ^@ammo_group_preloads |       preload: ^@ammo_group_preloads | ||||||
|     ) |     ) | ||||||
|     |> list_ammo_groups_include_empty(include_empty) |     |> list_ammo_groups_filter_on_type(type) | ||||||
|  |     |> list_ammo_groups_show_used(show_used) | ||||||
|     |> list_ammo_groups_search(search) |     |> list_ammo_groups_search(search) | ||||||
|     |> Repo.all() |     |> Repo.all() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp list_ammo_groups_include_empty(query, true), do: query |   @spec list_ammo_groups_filter_on_type(Queryable.t(), AmmoType.class() | :all) :: Queryable.t() | ||||||
|  |   defp list_ammo_groups_filter_on_type(query, :rifle), | ||||||
|  |     do: query |> where([at: at], at.class == :rifle) | ||||||
|  |  | ||||||
|   defp list_ammo_groups_include_empty(query, false) do |   defp list_ammo_groups_filter_on_type(query, :pistol), | ||||||
|     query |> where([ag], not (ag.count == 0)) |     do: query |> where([at: at], at.class == :pistol) | ||||||
|  |  | ||||||
|  |   defp list_ammo_groups_filter_on_type(query, :shotgun), | ||||||
|  |     do: query |> where([at: at], at.class == :shotgun) | ||||||
|  |  | ||||||
|  |   defp list_ammo_groups_filter_on_type(query, _all), do: query | ||||||
|  |  | ||||||
|  |   @spec list_ammo_groups_show_used(Queryable.t(), show_used :: boolean()) :: Queryable.t() | ||||||
|  |   defp list_ammo_groups_show_used(query, true), do: query | ||||||
|  |  | ||||||
|  |   defp list_ammo_groups_show_used(query, _false) do | ||||||
|  |     query |> where([ag: ag], not (ag.count == 0)) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @spec list_ammo_groups_show_used(Queryable.t(), search :: String.t() | nil) :: Queryable.t() | ||||||
|   defp list_ammo_groups_search(query, nil), do: query |   defp list_ammo_groups_search(query, nil), do: query | ||||||
|   defp list_ammo_groups_search(query, ""), do: query |   defp list_ammo_groups_search(query, ""), do: query | ||||||
|  |  | ||||||
| @@ -842,12 +915,39 @@ defmodule Cannery.Ammo do | |||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec get_percentage_remaining(AmmoGroup.t(), User.t()) :: non_neg_integer() |   @spec get_percentage_remaining(AmmoGroup.t(), User.t()) :: non_neg_integer() | ||||||
|   def get_percentage_remaining(%AmmoGroup{count: 0, user_id: user_id}, %User{id: user_id}) do |   def get_percentage_remaining(%AmmoGroup{id: ammo_group_id} = ammo_group, user) do | ||||||
|     0 |     [ammo_group] | ||||||
|  |     |> get_percentages_remaining(user) | ||||||
|  |     |> Map.fetch!(ammo_group_id) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def get_percentage_remaining(%AmmoGroup{count: count} = ammo_group, current_user) do |   @doc """ | ||||||
|     round(count / get_original_count(ammo_group, current_user) * 100) |   Calculates the percentages remaining of multiple ammo groups out of 100 | ||||||
|  |  | ||||||
|  |   ## Examples | ||||||
|  |  | ||||||
|  |       iex> get_percentages_remaining( | ||||||
|  |       ...>   [%AmmoGroup{id: 123, count: 5, user_id: 456}], | ||||||
|  |       ...>   %User{id: 456} | ||||||
|  |       ...> ) | ||||||
|  |       %{123 => 100} | ||||||
|  |  | ||||||
|  |   """ | ||||||
|  |   @spec get_percentages_remaining([AmmoGroup.t()], User.t()) :: | ||||||
|  |           %{optional(AmmoGroup.id()) => non_neg_integer()} | ||||||
|  |   def get_percentages_remaining(ammo_groups, %User{id: user_id} = user) do | ||||||
|  |     original_counts = get_original_counts(ammo_groups, user) | ||||||
|  |  | ||||||
|  |     ammo_groups | ||||||
|  |     |> Map.new(fn %AmmoGroup{id: ammo_group_id, count: count, user_id: ^user_id} -> | ||||||
|  |       percentage = | ||||||
|  |         case count do | ||||||
|  |           0 -> 0 | ||||||
|  |           count -> round(count / Map.fetch!(original_counts, ammo_group_id) * 100) | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |       {ammo_group_id, percentage} | ||||||
|  |     end) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
| @@ -956,13 +1056,21 @@ defmodule Cannery.Ammo do | |||||||
|   @spec create_ammo_groups(attrs :: map(), multiplier :: non_neg_integer(), User.t()) :: |   @spec create_ammo_groups(attrs :: map(), multiplier :: non_neg_integer(), User.t()) :: | ||||||
|           {:ok, {count :: non_neg_integer(), [AmmoGroup.t()] | nil}} |           {:ok, {count :: non_neg_integer(), [AmmoGroup.t()] | nil}} | ||||||
|           | {:error, AmmoGroup.changeset()} |           | {:error, AmmoGroup.changeset()} | ||||||
|   def create_ammo_groups( |   def create_ammo_groups(attrs, multiplier, %User{} = user) do | ||||||
|  |     attrs | ||||||
|  |     |> Map.new(fn {k, v} -> {to_string(k), v} end) | ||||||
|  |     |> do_create_ammo_groups(multiplier, user) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   defp do_create_ammo_groups( | ||||||
|          %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, |          %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, | ||||||
|          multiplier, |          multiplier, | ||||||
|         %User{} = user |          user | ||||||
|        ) |        ) | ||||||
|       when multiplier >= 1 and multiplier <= @ammo_group_create_limit and |        when multiplier >= 1 and | ||||||
|              not (ammo_type_id |> is_nil()) and not (container_id |> is_nil()) do |               multiplier <= @ammo_group_create_limit and | ||||||
|  |               ammo_type_id |> is_binary() and | ||||||
|  |               container_id |> is_binary() do | ||||||
|     now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) |     now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) | ||||||
|  |  | ||||||
|     changesets = |     changesets = | ||||||
| @@ -998,7 +1106,7 @@ defmodule Cannery.Ammo do | |||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def create_ammo_groups( |   defp do_create_ammo_groups( | ||||||
|          %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, |          %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs, | ||||||
|          _multiplier, |          _multiplier, | ||||||
|          user |          user | ||||||
| @@ -1017,7 +1125,7 @@ defmodule Cannery.Ammo do | |||||||
|     {:error, changeset} |     {:error, changeset} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def create_ammo_groups(invalid_attrs, _multiplier, user) do |   defp do_create_ammo_groups(invalid_attrs, _multiplier, user) do | ||||||
|     {:error, %AmmoGroup{} |> AmmoGroup.create_changeset(nil, nil, user, invalid_attrs)} |     {:error, %AmmoGroup{} |> AmmoGroup.create_changeset(nil, nil, user, invalid_attrs)} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,30 +42,47 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|     field :name, :string |     field :name, :string | ||||||
|     field :desc, :string |     field :desc, :string | ||||||
|  |  | ||||||
|     # https://en.wikipedia.org/wiki/Bullet#Abbreviations |     field :class, Ecto.Enum, values: [:rifle, :shotgun, :pistol] | ||||||
|  |  | ||||||
|  |     # common fields | ||||||
|  |     # https://shootersreference.com/reloadingdata/bullet_abbreviations/ | ||||||
|     field :bullet_type, :string |     field :bullet_type, :string | ||||||
|     field :bullet_core, :string |     field :bullet_core, :string | ||||||
|     field :cartridge, :string |     # also gauge for shotguns | ||||||
|     field :caliber, :string |     field :caliber, :string | ||||||
|     field :case_material, :string |     field :case_material, :string | ||||||
|     field :jacket_type, :string |  | ||||||
|     field :muzzle_velocity, :integer |  | ||||||
|     field :powder_type, :string |     field :powder_type, :string | ||||||
|     field :powder_grains_per_charge, :integer |  | ||||||
|     field :grains, :integer |     field :grains, :integer | ||||||
|     field :pressure, :string |     field :pressure, :string | ||||||
|     field :primer_type, :string |     field :primer_type, :string | ||||||
|     field :firing_type, :string |     field :firing_type, :string | ||||||
|  |     field :manufacturer, :string | ||||||
|  |     field :upc, :string | ||||||
|  |  | ||||||
|     field :tracer, :boolean, default: false |     field :tracer, :boolean, default: false | ||||||
|     field :incendiary, :boolean, default: false |     field :incendiary, :boolean, default: false | ||||||
|     field :blank, :boolean, default: false |     field :blank, :boolean, default: false | ||||||
|     field :corrosive, :boolean, default: false |     field :corrosive, :boolean, default: false | ||||||
|  |  | ||||||
|     field :manufacturer, :string |     # rifle/pistol fields | ||||||
|     field :upc, :string |     field :cartridge, :string | ||||||
|  |     field :jacket_type, :string | ||||||
|  |     field :powder_grains_per_charge, :integer | ||||||
|  |     field :muzzle_velocity, :integer | ||||||
|  |  | ||||||
|  |     # shotgun fields | ||||||
|  |     field :wadding, :string | ||||||
|  |     field :shot_type, :string | ||||||
|  |     field :shot_material, :string | ||||||
|  |     field :shot_size, :string | ||||||
|  |     field :unfired_length, :string | ||||||
|  |     field :brass_height, :string | ||||||
|  |     field :chamber_size, :string | ||||||
|  |     field :load_grains, :integer | ||||||
|  |     field :shot_charge_weight, :string | ||||||
|  |     field :dram_equivalent, :string | ||||||
|  |  | ||||||
|     field :user_id, :binary_id |     field :user_id, :binary_id | ||||||
|  |  | ||||||
|     has_many :ammo_groups, AmmoGroup |     has_many :ammo_groups, AmmoGroup | ||||||
|  |  | ||||||
|     timestamps() |     timestamps() | ||||||
| @@ -75,6 +92,7 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|           id: id(), |           id: id(), | ||||||
|           name: String.t(), |           name: String.t(), | ||||||
|           desc: String.t() | nil, |           desc: String.t() | nil, | ||||||
|  |           class: class(), | ||||||
|           bullet_type: String.t() | nil, |           bullet_type: String.t() | nil, | ||||||
|           bullet_core: String.t() | nil, |           bullet_core: String.t() | nil, | ||||||
|           cartridge: String.t() | nil, |           cartridge: String.t() | nil, | ||||||
| @@ -88,6 +106,16 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|           pressure: String.t() | nil, |           pressure: String.t() | nil, | ||||||
|           primer_type: String.t() | nil, |           primer_type: String.t() | nil, | ||||||
|           firing_type: String.t() | nil, |           firing_type: String.t() | nil, | ||||||
|  |           wadding: String.t() | nil, | ||||||
|  |           shot_type: String.t() | nil, | ||||||
|  |           shot_material: String.t() | nil, | ||||||
|  |           shot_size: String.t() | nil, | ||||||
|  |           unfired_length: String.t() | nil, | ||||||
|  |           brass_height: String.t() | nil, | ||||||
|  |           chamber_size: String.t() | nil, | ||||||
|  |           load_grains: integer() | nil, | ||||||
|  |           shot_charge_weight: String.t() | nil, | ||||||
|  |           dram_equivalent: String.t() | nil, | ||||||
|           tracer: boolean(), |           tracer: boolean(), | ||||||
|           incendiary: boolean(), |           incendiary: boolean(), | ||||||
|           blank: boolean(), |           blank: boolean(), | ||||||
| @@ -102,12 +130,14 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|   @type new_ammo_type :: %__MODULE__{} |   @type new_ammo_type :: %__MODULE__{} | ||||||
|   @type id :: UUID.t() |   @type id :: UUID.t() | ||||||
|   @type changeset :: Changeset.t(t() | new_ammo_type()) |   @type changeset :: Changeset.t(t() | new_ammo_type()) | ||||||
|  |   @type class :: :rifle | :shotgun | :pistol | nil | ||||||
|  |  | ||||||
|   @spec changeset_fields() :: [atom()] |   @spec changeset_fields() :: [atom()] | ||||||
|   defp changeset_fields, |   defp changeset_fields, | ||||||
|     do: [ |     do: [ | ||||||
|       :name, |       :name, | ||||||
|       :desc, |       :desc, | ||||||
|  |       :class, | ||||||
|       :bullet_type, |       :bullet_type, | ||||||
|       :bullet_core, |       :bullet_core, | ||||||
|       :cartridge, |       :cartridge, | ||||||
| @@ -121,6 +151,16 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|       :pressure, |       :pressure, | ||||||
|       :primer_type, |       :primer_type, | ||||||
|       :firing_type, |       :firing_type, | ||||||
|  |       :wadding, | ||||||
|  |       :shot_type, | ||||||
|  |       :shot_material, | ||||||
|  |       :shot_size, | ||||||
|  |       :unfired_length, | ||||||
|  |       :brass_height, | ||||||
|  |       :chamber_size, | ||||||
|  |       :load_grains, | ||||||
|  |       :shot_charge_weight, | ||||||
|  |       :dram_equivalent, | ||||||
|       :tracer, |       :tracer, | ||||||
|       :incendiary, |       :incendiary, | ||||||
|       :blank, |       :blank, | ||||||
| @@ -129,20 +169,55 @@ defmodule Cannery.Ammo.AmmoType do | |||||||
|       :upc |       :upc | ||||||
|     ] |     ] | ||||||
|  |  | ||||||
|  |   @spec string_fields() :: [atom()] | ||||||
|  |   defp string_fields, | ||||||
|  |     do: [ | ||||||
|  |       :name, | ||||||
|  |       :bullet_type, | ||||||
|  |       :bullet_core, | ||||||
|  |       :cartridge, | ||||||
|  |       :caliber, | ||||||
|  |       :case_material, | ||||||
|  |       :jacket_type, | ||||||
|  |       :powder_type, | ||||||
|  |       :pressure, | ||||||
|  |       :primer_type, | ||||||
|  |       :firing_type, | ||||||
|  |       :wadding, | ||||||
|  |       :shot_type, | ||||||
|  |       :shot_material, | ||||||
|  |       :shot_size, | ||||||
|  |       :unfired_length, | ||||||
|  |       :brass_height, | ||||||
|  |       :chamber_size, | ||||||
|  |       :shot_charge_weight, | ||||||
|  |       :dram_equivalent, | ||||||
|  |       :manufacturer, | ||||||
|  |       :upc | ||||||
|  |     ] | ||||||
|  |  | ||||||
|   @doc false |   @doc false | ||||||
|   @spec create_changeset(new_ammo_type(), User.t(), attrs :: map()) :: changeset() |   @spec create_changeset(new_ammo_type(), User.t(), attrs :: map()) :: changeset() | ||||||
|   def create_changeset(ammo_type, %User{id: user_id}, attrs) do |   def create_changeset(ammo_type, %User{id: user_id}, attrs) do | ||||||
|  |     changeset = | ||||||
|       ammo_type |       ammo_type | ||||||
|       |> change(user_id: user_id) |       |> change(user_id: user_id) | ||||||
|       |> cast(attrs, changeset_fields()) |       |> cast(attrs, changeset_fields()) | ||||||
|  |  | ||||||
|  |     string_fields() | ||||||
|  |     |> Enum.reduce(changeset, fn field, acc -> acc |> validate_length(field, max: 255) end) | ||||||
|     |> validate_required([:name, :user_id]) |     |> validate_required([:name, :user_id]) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc false |   @doc false | ||||||
|   @spec update_changeset(t() | new_ammo_type(), attrs :: map()) :: changeset() |   @spec update_changeset(t() | new_ammo_type(), attrs :: map()) :: changeset() | ||||||
|   def update_changeset(ammo_type, attrs) do |   def update_changeset(ammo_type, attrs) do | ||||||
|  |     changeset = | ||||||
|       ammo_type |       ammo_type | ||||||
|       |> cast(attrs, changeset_fields()) |       |> cast(attrs, changeset_fields()) | ||||||
|  |  | ||||||
|  |     string_fields() | ||||||
|  |     |> Enum.reduce(changeset, fn field, acc -> acc |> validate_length(field, max: 255) end) | ||||||
|     |> validate_required(:name) |     |> validate_required(:name) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ defmodule Cannery.Containers do | |||||||
|       as: :t, |       as: :t, | ||||||
|       where: c.user_id == ^user_id, |       where: c.user_id == ^user_id, | ||||||
|       order_by: c.name, |       order_by: c.name, | ||||||
|  |       distinct: c.id, | ||||||
|       preload: ^@container_preloads |       preload: ^@container_preloads | ||||||
|     ) |     ) | ||||||
|     |> list_containers_search(search) |     |> list_containers_search(search) | ||||||
| @@ -91,7 +92,7 @@ defmodule Cannery.Containers do | |||||||
|   @doc """ |   @doc """ | ||||||
|   Gets a single container. |   Gets a single container. | ||||||
|  |  | ||||||
|   Raises `Ecto.NoResultsError` if the Container does not exist. |   Raises `KeyError` if the Container does not exist. | ||||||
|  |  | ||||||
|   ## Examples |   ## Examples | ||||||
|  |  | ||||||
| @@ -99,18 +100,37 @@ defmodule Cannery.Containers do | |||||||
|       %Container{} |       %Container{} | ||||||
|  |  | ||||||
|       iex> get_container!(456, %User{id: 123}) |       iex> get_container!(456, %User{id: 123}) | ||||||
|       ** (Ecto.NoResultsError) |       ** (KeyError) | ||||||
|  |  | ||||||
|   """ |   """ | ||||||
|   @spec get_container!(Container.id(), User.t()) :: Container.t() |   @spec get_container!(Container.id(), User.t()) :: Container.t() | ||||||
|   def get_container!(id, %User{id: user_id}) do |   def get_container!(id, user) do | ||||||
|     Repo.one!( |     [id] | ||||||
|  |     |> get_containers(user) | ||||||
|  |     |> Map.fetch!(id) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   @doc """ | ||||||
|  |   Gets multiple containers. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   ## Examples | ||||||
|  |  | ||||||
|  |       iex> get_containers([123], %User{id: 123}) | ||||||
|  |       %{123 => %Container{}} | ||||||
|  |  | ||||||
|  |   """ | ||||||
|  |   @spec get_containers([Container.id()], User.t()) :: %{optional(Container.id()) => Container.t()} | ||||||
|  |   def get_containers(ids, %User{id: user_id}) do | ||||||
|  |     Repo.all( | ||||||
|       from c in Container, |       from c in Container, | ||||||
|         where: c.user_id == ^user_id, |         where: c.user_id == ^user_id, | ||||||
|         where: c.id == ^id, |         where: c.id in ^ids, | ||||||
|         order_by: c.name, |         order_by: c.name, | ||||||
|         preload: ^@container_preloads |         preload: ^@container_preloads, | ||||||
|  |         select: {c.id, c} | ||||||
|     ) |     ) | ||||||
|  |     |> Map.new() | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @doc """ |   @doc """ | ||||||
|   | |||||||
| @@ -53,6 +53,8 @@ defmodule Cannery.Containers.Container do | |||||||
|     container |     container | ||||||
|     |> change(user_id: user_id) |     |> change(user_id: user_id) | ||||||
|     |> cast(attrs, [:name, :desc, :type, :location]) |     |> cast(attrs, [:name, :desc, :type, :location]) | ||||||
|  |     |> validate_length(:name, max: 255) | ||||||
|  |     |> validate_length(:type, max: 255) | ||||||
|     |> validate_required([:name, :type, :user_id]) |     |> validate_required([:name, :type, :user_id]) | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -61,6 +63,8 @@ defmodule Cannery.Containers.Container do | |||||||
|   def update_changeset(container, attrs) do |   def update_changeset(container, attrs) do | ||||||
|     container |     container | ||||||
|     |> cast(attrs, [:name, :desc, :type, :location]) |     |> cast(attrs, [:name, :desc, :type, :location]) | ||||||
|  |     |> validate_length(:name, max: 255) | ||||||
|  |     |> validate_length(:type, max: 255) | ||||||
|     |> validate_required([:name, :type]) |     |> validate_required([:name, :type]) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -47,6 +47,9 @@ defmodule Cannery.Containers.Tag do | |||||||
|     tag |     tag | ||||||
|     |> change(user_id: user_id) |     |> change(user_id: user_id) | ||||||
|     |> cast(attrs, [:name, :bg_color, :text_color]) |     |> cast(attrs, [:name, :bg_color, :text_color]) | ||||||
|  |     |> validate_length(:name, max: 255) | ||||||
|  |     |> validate_length(:bg_color, max: 12) | ||||||
|  |     |> validate_length(:text_color, max: 12) | ||||||
|     |> validate_required([:name, :bg_color, :text_color, :user_id]) |     |> validate_required([:name, :bg_color, :text_color, :user_id]) | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -55,6 +58,9 @@ defmodule Cannery.Containers.Tag do | |||||||
|   def update_changeset(tag, attrs) do |   def update_changeset(tag, attrs) do | ||||||
|     tag |     tag | ||||||
|     |> cast(attrs, [:name, :bg_color, :text_color]) |     |> cast(attrs, [:name, :bg_color, :text_color]) | ||||||
|  |     |> validate_length(:name, max: 255) | ||||||
|  |     |> validate_length(:bg_color, max: 12) | ||||||
|  |     |> validate_length(:text_color, max: 12) | ||||||
|     |> validate_required([:name, :bg_color, :text_color]) |     |> validate_required([:name, :bg_color, :text_color]) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ | |||||||
|     <%= textarea(f, :notes, |     <%= textarea(f, :notes, | ||||||
|       id: "add-shot-group-form-notes", |       id: "add-shot-group-form-notes", | ||||||
|       class: "input input-primary col-span-2", |       class: "input input-primary col-span-2", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext("Really great weather"), |       placeholder: gettext("Really great weather"), | ||||||
|       phx_hook: "MaintainAttrs", |       phx_hook: "MaintainAttrs", | ||||||
|       phx_update: "ignore" |       phx_update: "ignore" | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|   use CanneryWeb, :live_component |   use CanneryWeb, :live_component | ||||||
|   alias Cannery.{Accounts.User, Ammo.AmmoGroup, ComparableDate} |   alias Cannery.{Accounts.User, Ammo.AmmoGroup, ComparableDate} | ||||||
|   alias Cannery.{ActivityLog, Ammo, Containers} |   alias Cannery.{ActivityLog, Ammo, Containers} | ||||||
|  |   alias CanneryWeb.Components.TableComponent | ||||||
|   alias Ecto.UUID |   alias Ecto.UUID | ||||||
|   alias Phoenix.LiveView.{Rendered, Socket} |   alias Phoenix.LiveView.{Rendered, Socket} | ||||||
|  |  | ||||||
| @@ -14,6 +15,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|             required(:id) => UUID.t(), |             required(:id) => UUID.t(), | ||||||
|             required(:current_user) => User.t(), |             required(:current_user) => User.t(), | ||||||
|             required(:ammo_groups) => [AmmoGroup.t()], |             required(:ammo_groups) => [AmmoGroup.t()], | ||||||
|  |             required(:show_used) => boolean(), | ||||||
|             optional(:ammo_type) => Rendered.t(), |             optional(:ammo_type) => Rendered.t(), | ||||||
|             optional(:range) => Rendered.t(), |             optional(:range) => Rendered.t(), | ||||||
|             optional(:container) => Rendered.t(), |             optional(:container) => Rendered.t(), | ||||||
| @@ -22,7 +24,11 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|           }, |           }, | ||||||
|           Socket.t() |           Socket.t() | ||||||
|         ) :: {:ok, Socket.t()} |         ) :: {:ok, Socket.t()} | ||||||
|   def update(%{id: _id, ammo_groups: _ammo_group, current_user: _current_user} = assigns, socket) do |   def update( | ||||||
|  |         %{id: _id, ammo_groups: _ammo_group, current_user: _current_user, show_used: _show_used} = | ||||||
|  |           assigns, | ||||||
|  |         socket | ||||||
|  |       ) do | ||||||
|     socket = |     socket = | ||||||
|       socket |       socket | ||||||
|       |> assign(assigns) |       |> assign(assigns) | ||||||
| @@ -43,61 +49,69 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|              ammo_type: ammo_type, |              ammo_type: ammo_type, | ||||||
|              range: range, |              range: range, | ||||||
|              container: container, |              container: container, | ||||||
|              actions: actions |              actions: actions, | ||||||
|  |              show_used: show_used | ||||||
|            } |            } | ||||||
|          } = socket |          } = socket | ||||||
|        ) do |        ) do | ||||||
|     columns = |     columns = | ||||||
|       if actions == [] do |  | ||||||
|       [] |       [] | ||||||
|       else |       |> TableComponent.maybe_compose_columns( | ||||||
|         [%{label: gettext("Actions"), key: :actions, sortable: false}] |         %{label: gettext("Actions"), key: :actions, sortable: false}, | ||||||
|       end |         actions != [] | ||||||
|  |       ) | ||||||
|     columns = [ |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|       %{label: gettext("Purchased on"), key: :purchased_on, type: ComparableDate}, |         label: gettext("Last used on"), | ||||||
|       %{label: gettext("Last used on"), key: :used_up_on, type: ComparableDate} | columns |         key: :used_up_on, | ||||||
|     ] |         type: ComparableDate | ||||||
|  |       }) | ||||||
|     columns = |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|       if container == [] do |         label: gettext("Purchased on"), | ||||||
|         columns |         key: :purchased_on, | ||||||
|       else |         type: ComparableDate | ||||||
|         [%{label: gettext("Container"), key: :container} | columns] |       }) | ||||||
|       end |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{label: gettext("Container"), key: :container}, | ||||||
|     columns = |         container != [] | ||||||
|       if range == [] do |       ) | ||||||
|         columns |       |> TableComponent.maybe_compose_columns( | ||||||
|       else |         %{label: gettext("Range"), key: :range}, | ||||||
|         [%{label: gettext("Range"), key: :range} | columns] |         range != [] | ||||||
|       end |       ) | ||||||
|  |       |> TableComponent.maybe_compose_columns(%{label: gettext("CPR"), key: :cpr}) | ||||||
|     columns = [ |       |> TableComponent.maybe_compose_columns(%{label: gettext("Price paid"), key: :price_paid}) | ||||||
|       %{label: gettext("Count"), key: :count}, |       |> TableComponent.maybe_compose_columns( | ||||||
|       %{label: gettext("Original Count"), key: :original_count}, |  | ||||||
|       %{label: gettext("Price paid"), key: :price_paid}, |  | ||||||
|       %{label: gettext("CPR"), key: :cpr}, |  | ||||||
|         %{label: gettext("% left"), key: :remaining}, |         %{label: gettext("% left"), key: :remaining}, | ||||||
|       %{label: gettext("Notes"), key: :notes} |         show_used | ||||||
|       | columns |       ) | ||||||
|     ] |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{label: gettext("Original Count"), key: :original_count}, | ||||||
|  |         show_used | ||||||
|  |       ) | ||||||
|  |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|  |         label: if(show_used, do: gettext("Current Count"), else: gettext("Count")), | ||||||
|  |         key: :count | ||||||
|  |       }) | ||||||
|  |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{label: gettext("Ammo type"), key: :ammo_type}, | ||||||
|  |         ammo_type != [] | ||||||
|  |       ) | ||||||
|  |  | ||||||
|     columns = |     containers = | ||||||
|       if ammo_type == [] do |       ammo_groups | ||||||
|         columns |       |> Enum.map(fn %{container_id: container_id} -> container_id end) | ||||||
|       else |       |> Containers.get_containers(current_user) | ||||||
|         [%{label: gettext("Ammo type"), key: :ammo_type} | columns] |  | ||||||
|       end |  | ||||||
|  |  | ||||||
|     extra_data = %{ |     extra_data = %{ | ||||||
|       current_user: current_user, |       current_user: current_user, | ||||||
|       ammo_type: ammo_type, |       ammo_type: ammo_type, | ||||||
|       columns: columns, |       columns: columns, | ||||||
|       container: container, |       container: container, | ||||||
|  |       containers: containers, | ||||||
|       original_counts: Ammo.get_original_counts(ammo_groups, current_user), |       original_counts: Ammo.get_original_counts(ammo_groups, current_user), | ||||||
|       cprs: Ammo.get_cprs(ammo_groups, current_user), |       cprs: Ammo.get_cprs(ammo_groups, current_user), | ||||||
|       last_used_dates: ActivityLog.get_last_used_dates(ammo_groups, current_user), |       last_used_dates: ActivityLog.get_last_used_dates(ammo_groups, current_user), | ||||||
|  |       percentages_remaining: Ammo.get_percentages_remaining(ammo_groups, current_user), | ||||||
|       actions: actions, |       actions: actions, | ||||||
|       range: range |       range: range | ||||||
|     } |     } | ||||||
| @@ -115,12 +129,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|   def render(assigns) do |   def render(assigns) do | ||||||
|     ~H""" |     ~H""" | ||||||
|     <div id={@id} class="w-full"> |     <div id={@id} class="w-full"> | ||||||
|       <.live_component |       <.live_component module={TableComponent} id={"table-#{@id}"} columns={@columns} rows={@rows} /> | ||||||
|         module={CanneryWeb.Components.TableComponent} |  | ||||||
|         id={"table-#{@id}"} |  | ||||||
|         columns={@columns} |  | ||||||
|         rows={@rows} |  | ||||||
|       /> |  | ||||||
|     </div> |     </div> | ||||||
|     """ |     """ | ||||||
|   end |   end | ||||||
| @@ -148,10 +157,11 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|      """} |      """} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:price_paid, %{price_paid: nil}, _additional_data), do: {"", nil} |   defp get_value_for_key(:price_paid, %{price_paid: nil}, _additional_data), | ||||||
|  |     do: {0, gettext("No cost information")} | ||||||
|  |  | ||||||
|   defp get_value_for_key(:price_paid, %{price_paid: price_paid}, _additional_data), |   defp get_value_for_key(:price_paid, %{price_paid: price_paid}, _additional_data), | ||||||
|     do: gettext("$%{amount}", amount: display_currency(price_paid)) |     do: {price_paid, gettext("$%{amount}", amount: display_currency(price_paid))} | ||||||
|  |  | ||||||
|   defp get_value_for_key(:purchased_on, %{purchased_on: purchased_on} = assigns, _additional_data) do |   defp get_value_for_key(:purchased_on, %{purchased_on: purchased_on} = assigns, _additional_data) do | ||||||
|     {purchased_on, |     {purchased_on, | ||||||
| @@ -183,11 +193,14 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|      """} |      """} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:remaining, ammo_group, %{current_user: current_user}), |   defp get_value_for_key( | ||||||
|     do: |          :remaining, | ||||||
|       gettext("%{percentage}%", |          %{id: ammo_group_id}, | ||||||
|         percentage: ammo_group |> Ammo.get_percentage_remaining(current_user) |          %{percentages_remaining: percentages_remaining} | ||||||
|       ) |        ) do | ||||||
|  |     percentage = Map.fetch!(percentages_remaining, ammo_group_id) | ||||||
|  |     {percentage, gettext("%{percentage}%", percentage: percentage)} | ||||||
|  |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:actions, ammo_group, %{actions: actions}) do |   defp get_value_for_key(:actions, ammo_group, %{actions: actions}) do | ||||||
|     assigns = %{actions: actions, ammo_group: ammo_group} |     assigns = %{actions: actions, ammo_group: ammo_group} | ||||||
| @@ -202,12 +215,13 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|   defp get_value_for_key( |   defp get_value_for_key( | ||||||
|          :container, |          :container, | ||||||
|          %{container_id: container_id} = ammo_group, |          %{container_id: container_id} = ammo_group, | ||||||
|          %{container: container, current_user: current_user} |          %{container: container_block, containers: containers} | ||||||
|        ) do |        ) do | ||||||
|  |     container = %{name: container_name} = Map.fetch!(containers, container_id) | ||||||
|  |  | ||||||
|     assigns = %{ |     assigns = %{ | ||||||
|       container: |       container: container, | ||||||
|         %{name: container_name} = container_id |> Containers.get_container!(current_user), |       container_block: container_block, | ||||||
|       container_block: container, |  | ||||||
|       ammo_group: ammo_group |       ammo_group: ammo_group | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -217,21 +231,24 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do | |||||||
|      """} |      """} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:original_count, %{id: ammo_group_id}, %{ |   defp get_value_for_key( | ||||||
|          original_counts: original_counts |          :original_count, | ||||||
|        }) do |          %{id: ammo_group_id}, | ||||||
|  |          %{original_counts: original_counts} | ||||||
|  |        ) do | ||||||
|     Map.fetch!(original_counts, ammo_group_id) |     Map.fetch!(original_counts, ammo_group_id) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:cpr, %{price_paid: nil}, _additional_data), |   defp get_value_for_key(:cpr, %{price_paid: nil}, _additional_data), | ||||||
|     do: gettext("No cost information") |     do: {0, gettext("No cost information")} | ||||||
|  |  | ||||||
|   defp get_value_for_key(:cpr, %{id: ammo_group_id}, %{cprs: cprs}) do |   defp get_value_for_key(:cpr, %{id: ammo_group_id}, %{cprs: cprs}) do | ||||||
|     gettext("$%{amount}", amount: display_currency(Map.fetch!(cprs, ammo_group_id))) |     amount = Map.fetch!(cprs, ammo_group_id) | ||||||
|  |     {amount, gettext("$%{amount}", amount: display_currency(amount))} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_value_for_key(:count, %{count: count}, _additional_data), |   defp get_value_for_key(:count, %{count: count}, _additional_data), | ||||||
|     do: if(count == 0, do: gettext("Empty"), else: count) |     do: if(count == 0, do: {0, gettext("Empty")}, else: count) | ||||||
|  |  | ||||||
|   defp get_value_for_key(key, ammo_group, _additional_data), do: ammo_group |> Map.get(key) |   defp get_value_for_key(key, ammo_group, _additional_data), do: ammo_group |> Map.get(key) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|   """ |   """ | ||||||
|   use CanneryWeb, :live_component |   use CanneryWeb, :live_component | ||||||
|   alias Cannery.{Accounts.User, ActivityLog, Ammo, Ammo.AmmoType} |   alias Cannery.{Accounts.User, ActivityLog, Ammo, Ammo.AmmoType} | ||||||
|  |   alias CanneryWeb.Components.TableComponent | ||||||
|   alias Ecto.UUID |   alias Ecto.UUID | ||||||
|   alias Phoenix.LiveView.{Rendered, Socket} |   alias Phoenix.LiveView.{Rendered, Socket} | ||||||
|  |  | ||||||
| @@ -12,6 +13,7 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|           %{ |           %{ | ||||||
|             required(:id) => UUID.t(), |             required(:id) => UUID.t(), | ||||||
|             required(:current_user) => User.t(), |             required(:current_user) => User.t(), | ||||||
|  |             optional(:class) => AmmoType.class() | nil, | ||||||
|             optional(:show_used) => boolean(), |             optional(:show_used) => boolean(), | ||||||
|             optional(:ammo_types) => [AmmoType.t()], |             optional(:ammo_types) => [AmmoType.t()], | ||||||
|             optional(:actions) => Rendered.t(), |             optional(:actions) => Rendered.t(), | ||||||
| @@ -24,6 +26,7 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|       socket |       socket | ||||||
|       |> assign(assigns) |       |> assign(assigns) | ||||||
|       |> assign_new(:show_used, fn -> false end) |       |> assign_new(:show_used, fn -> false end) | ||||||
|  |       |> assign_new(:class, fn -> :all end) | ||||||
|       |> assign_new(:actions, fn -> [] end) |       |> assign_new(:actions, fn -> [] end) | ||||||
|       |> display_ammo_types() |       |> display_ammo_types() | ||||||
|  |  | ||||||
| @@ -36,109 +39,135 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|              ammo_types: ammo_types, |              ammo_types: ammo_types, | ||||||
|              current_user: current_user, |              current_user: current_user, | ||||||
|              show_used: show_used, |              show_used: show_used, | ||||||
|  |              class: class, | ||||||
|              actions: actions |              actions: actions | ||||||
|            } |            } | ||||||
|          } = socket |          } = socket | ||||||
|        ) do |        ) do | ||||||
|     columns = |     filtered_columns = | ||||||
|       [ |       [ | ||||||
|         %{label: gettext("Name"), key: :name, type: :name}, |  | ||||||
|         %{label: gettext("Bullet type"), key: :bullet_type, type: :string}, |  | ||||||
|         %{label: gettext("Bullet core"), key: :bullet_core, type: :string}, |  | ||||||
|         %{label: gettext("Cartridge"), key: :cartridge, type: :string}, |         %{label: gettext("Cartridge"), key: :cartridge, type: :string}, | ||||||
|         %{label: gettext("Caliber"), key: :caliber, type: :string}, |         %{ | ||||||
|         %{label: gettext("Case material"), key: :case_material, type: :string}, |           label: if(class == :shotgun, do: gettext("Gauge"), else: gettext("Caliber")), | ||||||
|  |           key: :caliber, | ||||||
|  |           type: :string | ||||||
|  |         }, | ||||||
|  |         %{label: gettext("Unfired shell length"), key: :unfired_length, type: :string}, | ||||||
|  |         %{label: gettext("Brass height"), key: :brass_height, type: :string}, | ||||||
|  |         %{label: gettext("Chamber size"), key: :chamber_size, type: :string}, | ||||||
|  |         %{label: gettext("Chamber size"), key: :chamber_size, type: :string}, | ||||||
|  |         %{label: gettext("Grains"), key: :grains, type: :string}, | ||||||
|  |         %{label: gettext("Bullet type"), key: :bullet_type, type: :string}, | ||||||
|  |         %{ | ||||||
|  |           label: if(class == :shotgun, do: gettext("Slug core"), else: gettext("Bullet core")), | ||||||
|  |           key: :bullet_core, | ||||||
|  |           type: :string | ||||||
|  |         }, | ||||||
|         %{label: gettext("Jacket type"), key: :jacket_type, type: :string}, |         %{label: gettext("Jacket type"), key: :jacket_type, type: :string}, | ||||||
|         %{label: gettext("Muzzle velocity"), key: :muzzle_velocity, type: :string}, |         %{label: gettext("Case material"), key: :case_material, type: :string}, | ||||||
|  |         %{label: gettext("Wadding"), key: :wadding, type: :string}, | ||||||
|  |         %{label: gettext("Shot type"), key: :shot_type, type: :string}, | ||||||
|  |         %{label: gettext("Shot material"), key: :shot_material, type: :string}, | ||||||
|  |         %{label: gettext("Shot size"), key: :shot_size, type: :string}, | ||||||
|  |         %{label: gettext("Load grains"), key: :load_grains, type: :string}, | ||||||
|  |         %{label: gettext("Shot charge weight"), key: :shot_charge_weight, type: :string}, | ||||||
|         %{label: gettext("Powder type"), key: :powder_type, type: :string}, |         %{label: gettext("Powder type"), key: :powder_type, type: :string}, | ||||||
|         %{ |         %{ | ||||||
|           label: gettext("Powder grains per charge"), |           label: gettext("Powder grains per charge"), | ||||||
|           key: :powder_grains_per_charge, |           key: :powder_grains_per_charge, | ||||||
|           type: :string |           type: :string | ||||||
|         }, |         }, | ||||||
|         %{label: gettext("Grains"), key: :grains, type: :string}, |  | ||||||
|         %{label: gettext("Pressure"), key: :pressure, type: :string}, |         %{label: gettext("Pressure"), key: :pressure, type: :string}, | ||||||
|  |         %{label: gettext("Dram equivalent"), key: :dram_equivalent, type: :string}, | ||||||
|  |         %{label: gettext("Muzzle velocity"), key: :muzzle_velocity, type: :string}, | ||||||
|         %{label: gettext("Primer type"), key: :primer_type, type: :string}, |         %{label: gettext("Primer type"), key: :primer_type, type: :string}, | ||||||
|         %{label: gettext("Firing type"), key: :firing_type, type: :string}, |         %{label: gettext("Firing type"), key: :firing_type, type: :string}, | ||||||
|         %{label: gettext("Tracer"), key: :tracer, type: :boolean}, |         %{label: gettext("Tracer"), key: :tracer, type: :atom}, | ||||||
|         %{label: gettext("Incendiary"), key: :incendiary, type: :boolean}, |         %{label: gettext("Incendiary"), key: :incendiary, type: :atom}, | ||||||
|         %{label: gettext("Blank"), key: :blank, type: :boolean}, |         %{label: gettext("Blank"), key: :blank, type: :atom}, | ||||||
|         %{label: gettext("Corrosive"), key: :corrosive, type: :boolean}, |         %{label: gettext("Corrosive"), key: :corrosive, type: :atom}, | ||||||
|         %{label: gettext("Manufacturer"), key: :manufacturer, type: :string}, |         %{label: gettext("Manufacturer"), key: :manufacturer, type: :string} | ||||||
|         %{label: gettext("UPC"), key: "upc", type: :string} |  | ||||||
|       ] |       ] | ||||||
|       |> Enum.filter(fn %{key: key, type: type} -> |       |> Enum.filter(fn %{key: key, type: type} -> | ||||||
|         # remove columns if all values match defaults |         # remove columns if all values match defaults | ||||||
|         default_value = if type == :boolean, do: false, else: nil |         default_value = if type == :atom, do: false, else: nil | ||||||
|  |  | ||||||
|         ammo_types |         ammo_types | ||||||
|         |> Enum.any?(fn ammo_type -> |         |> Enum.any?(fn ammo_type -> Map.get(ammo_type, key, default_value) != default_value end) | ||||||
|           not (ammo_type |> Map.get(key) == default_value) |  | ||||||
|       end) |       end) | ||||||
|       end) |  | ||||||
|       |> Kernel.++([ |     columns = | ||||||
|         %{label: gettext("Rounds"), key: :round_count, type: :round_count} |       [%{label: gettext("Actions"), key: "actions", type: :actions, sortable: false}] | ||||||
|       ]) |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|       |> Kernel.++( |         label: gettext("Average CPR"), | ||||||
|         if show_used do |         key: :avg_price_paid, | ||||||
|           [ |         type: :avg_price_paid | ||||||
|  |       }) | ||||||
|  |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{ | ||||||
|  |           label: gettext("Total ever packs"), | ||||||
|  |           key: :historical_pack_count, | ||||||
|  |           type: :historical_pack_count | ||||||
|  |         }, | ||||||
|  |         show_used | ||||||
|  |       ) | ||||||
|  |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{ | ||||||
|  |           label: gettext("Used packs"), | ||||||
|  |           key: :used_pack_count, | ||||||
|  |           type: :used_pack_count | ||||||
|  |         }, | ||||||
|  |         show_used | ||||||
|  |       ) | ||||||
|  |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|  |         label: gettext("Packs"), | ||||||
|  |         key: :ammo_count, | ||||||
|  |         type: :ammo_count | ||||||
|  |       }) | ||||||
|  |       |> TableComponent.maybe_compose_columns( | ||||||
|  |         %{ | ||||||
|  |           label: gettext("Total ever rounds"), | ||||||
|  |           key: :historical_round_count, | ||||||
|  |           type: :historical_round_count | ||||||
|  |         }, | ||||||
|  |         show_used | ||||||
|  |       ) | ||||||
|  |       |> TableComponent.maybe_compose_columns( | ||||||
|         %{ |         %{ | ||||||
|           label: gettext("Used rounds"), |           label: gettext("Used rounds"), | ||||||
|           key: :used_round_count, |           key: :used_round_count, | ||||||
|           type: :used_round_count |           type: :used_round_count | ||||||
|         }, |         }, | ||||||
|             %{ |         show_used | ||||||
|               label: gettext("Total ever rounds"), |  | ||||||
|               key: :historical_round_count, |  | ||||||
|               type: :historical_round_count |  | ||||||
|             } |  | ||||||
|           ] |  | ||||||
|         else |  | ||||||
|           [] |  | ||||||
|         end |  | ||||||
|       ) |       ) | ||||||
|       |> Kernel.++([%{label: gettext("Packs"), key: :ammo_count, type: :ammo_count}]) |       |> TableComponent.maybe_compose_columns(%{ | ||||||
|       |> Kernel.++( |         label: gettext("Rounds"), | ||||||
|         if show_used do |         key: :round_count, | ||||||
|           [ |         type: :round_count | ||||||
|             %{ |       }) | ||||||
|               label: gettext("Used packs"), |       |> TableComponent.maybe_compose_columns(filtered_columns) | ||||||
|               key: :used_packs_count, |       |> TableComponent.maybe_compose_columns( | ||||||
|               type: :used_packs_count |         %{label: gettext("Class"), key: :type, type: :atom}, | ||||||
|             }, |         class in [:all, nil] | ||||||
|             %{ |  | ||||||
|               label: gettext("Total ever packs"), |  | ||||||
|               key: :historical_packs_count, |  | ||||||
|               type: :historical_packs_count |  | ||||||
|             } |  | ||||||
|           ] |  | ||||||
|         else |  | ||||||
|           [] |  | ||||||
|         end |  | ||||||
|       ) |       ) | ||||||
|       |> Kernel.++([ |       |> TableComponent.maybe_compose_columns(%{label: gettext("Name"), key: :name, type: :name}) | ||||||
|         %{label: gettext("Average CPR"), key: :avg_price_paid, type: :avg_price_paid}, |  | ||||||
|         %{label: gettext("Actions"), key: "actions", type: :actions, sortable: false} |  | ||||||
|       ]) |  | ||||||
|  |  | ||||||
|     round_counts = ammo_types |> Ammo.get_round_count_for_ammo_types(current_user) |     round_counts = ammo_types |> Ammo.get_round_count_for_ammo_types(current_user) | ||||||
|  |  | ||||||
|     used_counts = |  | ||||||
|       show_used && ammo_types |> ActivityLog.get_used_count_for_ammo_types(current_user) |  | ||||||
|  |  | ||||||
|     historical_round_counts = |  | ||||||
|       show_used && ammo_types |> Ammo.get_historical_count_for_ammo_types(current_user) |  | ||||||
|  |  | ||||||
|     packs_count = ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user) |     packs_count = ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user) | ||||||
|  |  | ||||||
|     historical_packs_count = |  | ||||||
|       show_used && ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user, true) |  | ||||||
|  |  | ||||||
|     used_packs_count = |  | ||||||
|       show_used && ammo_types |> Ammo.get_used_ammo_groups_count_for_types(current_user) |  | ||||||
|  |  | ||||||
|     average_costs = ammo_types |> Ammo.get_average_cost_for_ammo_types(current_user) |     average_costs = ammo_types |> Ammo.get_average_cost_for_ammo_types(current_user) | ||||||
|  |  | ||||||
|  |     [used_counts, historical_round_counts, historical_pack_counts, used_pack_counts] = | ||||||
|  |       if show_used do | ||||||
|  |         [ | ||||||
|  |           ammo_types |> ActivityLog.get_used_count_for_ammo_types(current_user), | ||||||
|  |           ammo_types |> Ammo.get_historical_count_for_ammo_types(current_user), | ||||||
|  |           ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user, true), | ||||||
|  |           ammo_types |> Ammo.get_used_ammo_groups_count_for_types(current_user) | ||||||
|  |         ] | ||||||
|  |       else | ||||||
|  |         [nil, nil, nil, nil] | ||||||
|  |       end | ||||||
|  |  | ||||||
|     extra_data = %{ |     extra_data = %{ | ||||||
|       actions: actions, |       actions: actions, | ||||||
|       current_user: current_user, |       current_user: current_user, | ||||||
| @@ -146,8 +175,8 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|       round_counts: round_counts, |       round_counts: round_counts, | ||||||
|       historical_round_counts: historical_round_counts, |       historical_round_counts: historical_round_counts, | ||||||
|       packs_count: packs_count, |       packs_count: packs_count, | ||||||
|       used_packs_count: used_packs_count, |       used_pack_counts: used_pack_counts, | ||||||
|       historical_packs_count: historical_packs_count, |       historical_pack_counts: historical_pack_counts, | ||||||
|       average_costs: average_costs |       average_costs: average_costs | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -164,12 +193,7 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|   def render(assigns) do |   def render(assigns) do | ||||||
|     ~H""" |     ~H""" | ||||||
|     <div id={@id} class="w-full"> |     <div id={@id} class="w-full"> | ||||||
|       <.live_component |       <.live_component module={TableComponent} id={"table-#{@id}"} columns={@columns} rows={@rows} /> | ||||||
|         module={CanneryWeb.Components.TableComponent} |  | ||||||
|         id={"table-#{@id}"} |  | ||||||
|         columns={@columns} |  | ||||||
|         rows={@rows} |  | ||||||
|       /> |  | ||||||
|     </div> |     </div> | ||||||
|     """ |     """ | ||||||
|   end |   end | ||||||
| @@ -181,58 +205,72 @@ defmodule CanneryWeb.Components.AmmoTypeTableComponent do | |||||||
|     end) |     end) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:boolean, key, ammo_type, _other_data), |   defp get_ammo_type_value(:atom, key, ammo_type, _other_data), | ||||||
|     do: ammo_type |> Map.get(key) |> humanize() |     do: ammo_type |> Map.get(key) |> humanize() | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:round_count, _key, %{id: ammo_type_id}, %{round_counts: round_counts}), |   defp get_ammo_type_value(:round_count, _key, %{id: ammo_type_id}, %{round_counts: round_counts}), | ||||||
|     do: Map.get(round_counts, ammo_type_id) |     do: Map.get(round_counts, ammo_type_id, 0) | ||||||
|  |  | ||||||
|   defp get_ammo_type_value( |   defp get_ammo_type_value( | ||||||
|          :historical_round_count, |          :historical_round_count, | ||||||
|          _key, |          _key, | ||||||
|          %{id: ammo_type_id}, |          %{id: ammo_type_id}, | ||||||
|          %{historical_round_counts: historical_round_counts} |          %{historical_round_counts: historical_round_counts} | ||||||
|        ), |        ) do | ||||||
|        do: Map.get(historical_round_counts, ammo_type_id) |     Map.get(historical_round_counts, ammo_type_id, 0) | ||||||
|  |   end | ||||||
|   defp get_ammo_type_value(:used_round_count, _key, %{id: ammo_type_id}, %{ |  | ||||||
|          used_counts: used_counts |  | ||||||
|        }), |  | ||||||
|        do: Map.get(used_counts, ammo_type_id) |  | ||||||
|  |  | ||||||
|   defp get_ammo_type_value( |   defp get_ammo_type_value( | ||||||
|          :historical_packs_count, |          :used_round_count, | ||||||
|          _key, |          _key, | ||||||
|          %{id: ammo_type_id}, |          %{id: ammo_type_id}, | ||||||
|          %{historical_packs_count: historical_packs_count} |          %{used_counts: used_counts} | ||||||
|        ), |        ) do | ||||||
|        do: Map.get(historical_packs_count, ammo_type_id) |     Map.get(used_counts, ammo_type_id, 0) | ||||||
|  |   end | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:used_packs_count, _key, %{id: ammo_type_id}, %{ |   defp get_ammo_type_value( | ||||||
|          used_packs_count: used_packs_count |          :historical_pack_count, | ||||||
|        }), |          _key, | ||||||
|        do: Map.get(used_packs_count, ammo_type_id) |          %{id: ammo_type_id}, | ||||||
|  |          %{historical_pack_counts: historical_pack_counts} | ||||||
|  |        ) do | ||||||
|  |     Map.get(historical_pack_counts, ammo_type_id, 0) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   defp get_ammo_type_value( | ||||||
|  |          :used_pack_count, | ||||||
|  |          _key, | ||||||
|  |          %{id: ammo_type_id}, | ||||||
|  |          %{used_pack_counts: used_pack_counts} | ||||||
|  |        ) do | ||||||
|  |     Map.get(used_pack_counts, ammo_type_id, 0) | ||||||
|  |   end | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:ammo_count, _key, %{id: ammo_type_id}, %{packs_count: packs_count}), |   defp get_ammo_type_value(:ammo_count, _key, %{id: ammo_type_id}, %{packs_count: packs_count}), | ||||||
|     do: Map.get(packs_count, ammo_type_id) |     do: Map.get(packs_count, ammo_type_id) | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:avg_price_paid, _key, %{id: ammo_type_id}, %{ |   defp get_ammo_type_value( | ||||||
|          average_costs: average_costs |          :avg_price_paid, | ||||||
|        }) do |          _key, | ||||||
|  |          %{id: ammo_type_id}, | ||||||
|  |          %{average_costs: average_costs} | ||||||
|  |        ) do | ||||||
|     case Map.get(average_costs, ammo_type_id) do |     case Map.get(average_costs, ammo_type_id) do | ||||||
|       nil -> gettext("No cost information") |       nil -> {0, gettext("No cost information")} | ||||||
|       count -> gettext("$%{amount}", amount: display_currency(count)) |       count -> {count, gettext("$%{amount}", amount: display_currency(count))} | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:name, _key, ammo_type, _other_data) do |   defp get_ammo_type_value(:name, _key, %{name: ammo_type_name} = ammo_type, _other_data) do | ||||||
|     assigns = %{ammo_type: ammo_type} |     assigns = %{ammo_type: ammo_type} | ||||||
|  |  | ||||||
|  |     {ammo_type_name, | ||||||
|      ~H""" |      ~H""" | ||||||
|      <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, @ammo_type)} class="link"> |      <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, @ammo_type)} class="link"> | ||||||
|        <%= @ammo_type.name %> |        <%= @ammo_type.name %> | ||||||
|      </.link> |      </.link> | ||||||
|     """ |      """} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp get_ammo_type_value(:actions, _key, ammo_type, %{actions: actions}) do |   defp get_ammo_type_value(:actions, _key, ammo_type, %{actions: actions}) do | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ defmodule CanneryWeb.CoreComponents do | |||||||
|   import CanneryWeb.{Gettext, ViewHelpers} |   import CanneryWeb.{Gettext, ViewHelpers} | ||||||
|   alias Cannery.{Accounts, Accounts.Invite, Accounts.User} |   alias Cannery.{Accounts, Accounts.Invite, Accounts.User} | ||||||
|   alias Cannery.{Ammo, Ammo.AmmoGroup} |   alias Cannery.{Ammo, Ammo.AmmoGroup} | ||||||
|   alias Cannery.{Containers, Containers.Container, Containers.Tag} |   alias Cannery.{Containers.Container, Containers.Tag} | ||||||
|   alias CanneryWeb.{Endpoint, HomeLive} |   alias CanneryWeb.{Endpoint, HomeLive} | ||||||
|   alias CanneryWeb.Router.Helpers, as: Routes |   alias CanneryWeb.Router.Helpers, as: Routes | ||||||
|   alias Phoenix.LiveView.{JS, Rendered} |   alias Phoenix.LiveView.{JS, Rendered} | ||||||
| @@ -91,7 +91,7 @@ defmodule CanneryWeb.CoreComponents do | |||||||
|   attr :original_count, :integer, default: nil |   attr :original_count, :integer, default: nil | ||||||
|   attr :cpr, :integer, default: nil |   attr :cpr, :integer, default: nil | ||||||
|   attr :last_used_date, Date, default: nil |   attr :last_used_date, Date, default: nil | ||||||
|   attr :show_container, :boolean, default: false |   attr :container, Container, default: nil | ||||||
|   slot(:inner_block) |   slot(:inner_block) | ||||||
|  |  | ||||||
|   def ammo_group_card(assigns) |   def ammo_group_card(assigns) | ||||||
|   | |||||||
| @@ -50,17 +50,11 @@ | |||||||
|       <%= gettext("$%{amount}", amount: display_currency(@cpr)) %> |       <%= gettext("$%{amount}", amount: display_currency(@cpr)) %> | ||||||
|     </span> |     </span> | ||||||
|  |  | ||||||
|     <span |     <span :if={@container} class="rounded-lg title text-lg"> | ||||||
|       :if={@show_container && Containers.get_container!(@ammo_group.container_id, @current_user)} |  | ||||||
|       class="rounded-lg title text-lg" |  | ||||||
|     > |  | ||||||
|       <%= gettext("Container:") %> |       <%= gettext("Container:") %> | ||||||
|  |  | ||||||
|       <.link |       <.link navigate={Routes.container_show_path(Endpoint, :show, @container)} class="link"> | ||||||
|         navigate={Routes.container_show_path(Endpoint, :show, @ammo_group.container_id)} |         <%= @container.name %> | ||||||
|         class="link" |  | ||||||
|       > |  | ||||||
|         <%= Containers.get_container!(@ammo_group.container_id, @current_user).name %> |  | ||||||
|       </.link> |       </.link> | ||||||
|     </span> |     </span> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
|     p-8 flex flex-col justify-center items-center cursor-auto" |     p-8 flex flex-col justify-center items-center cursor-auto" | ||||||
|   style="background-color: rgba(0,0,0,0.4);" |   style="background-color: rgba(0,0,0,0.4);" | ||||||
|   phx-remove={hide_modal()} |   phx-remove={hide_modal()} | ||||||
|  |   aria-label={gettext("Close modal")} | ||||||
| > | > | ||||||
|   <span class="hidden"></span> |   <span class="hidden"></span> | ||||||
| </.link> | </.link> | ||||||
| @@ -31,6 +32,7 @@ | |||||||
|         text-gray-500 hover:text-gray-800 |         text-gray-500 hover:text-gray-800 | ||||||
|         transition-all duration-500 ease-in-out" |         transition-all duration-500 ease-in-out" | ||||||
|       phx-remove={hide_modal()} |       phx-remove={hide_modal()} | ||||||
|  |       aria-label={gettext("Close modal")} | ||||||
|     > |     > | ||||||
|       <i class="fa-fw fa-lg fas fa-times"></i> |       <i class="fa-fw fa-lg fas fa-times"></i> | ||||||
|     </.link> |     </.link> | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| <label for={@id || @action} class="inline-flex relative items-center cursor-pointer"> | <label for={@id || @action} class="relative inline-flex items-center cursor-pointer"> | ||||||
|   <input |   <input | ||||||
|     id={@id || @action} |     id={@id || @action} | ||||||
|     type="checkbox" |     type="checkbox" | ||||||
| @@ -23,7 +23,7 @@ | |||||||
|   </div> |   </div> | ||||||
|   <span |   <span | ||||||
|     id={"#{@id || @action}-label"} |     id={"#{@id || @action}-label"} | ||||||
|     class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300" |     class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300 whitespace-nowrap" | ||||||
|   > |   > | ||||||
|     <%= render_slot(@inner_block) %> |     <%= render_slot(@inner_block) %> | ||||||
|   </span> |   </span> | ||||||
|   | |||||||
| @@ -135,4 +135,25 @@ defmodule CanneryWeb.Components.TableComponent do | |||||||
|       sort_mode |       sort_mode | ||||||
|     ) |     ) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @doc """ | ||||||
|  |   Conditionally composes elements into the columns list, supports maps and | ||||||
|  |   lists. Works tail to front in order for efficiency | ||||||
|  |  | ||||||
|  |       iex> [] | ||||||
|  |       ...> |> maybe_compose_columns(%{label: "Column 3"}, true) | ||||||
|  |       ...> |> maybe_compose_columns(%{label: "Column 2"}, false) | ||||||
|  |       ...> |> maybe_compose_columns(%{label: "Column 1"}) | ||||||
|  |       [%{label: "Column 1"}, %{label: "Column 3"}] | ||||||
|  |  | ||||||
|  |   """ | ||||||
|  |   @spec maybe_compose_columns(list(), element_to_add :: list() | map()) :: list() | ||||||
|  |   @spec maybe_compose_columns(list(), element_to_add :: list() | map(), boolean()) :: list() | ||||||
|  |   def maybe_compose_columns(columns, element_or_elements, add? \\ true) | ||||||
|  |  | ||||||
|  |   def maybe_compose_columns(columns, elements, true) when is_list(elements), | ||||||
|  |     do: Enum.concat(elements, columns) | ||||||
|  |  | ||||||
|  |   def maybe_compose_columns(columns, element, true) when is_map(element), do: [element | columns] | ||||||
|  |   def maybe_compose_columns(columns, _element_or_elements, false), do: columns | ||||||
| end | end | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ defmodule CanneryWeb.ExportController do | |||||||
|   alias Cannery.{ActivityLog, Ammo, Containers} |   alias Cannery.{ActivityLog, Ammo, Containers} | ||||||
|  |  | ||||||
|   def export(%{assigns: %{current_user: current_user}} = conn, %{"mode" => "json"}) do |   def export(%{assigns: %{current_user: current_user}} = conn, %{"mode" => "json"}) do | ||||||
|     ammo_types = Ammo.list_ammo_types(current_user) |     ammo_types = Ammo.list_ammo_types(current_user, :all) | ||||||
|     used_counts = ammo_types |> ActivityLog.get_used_count_for_ammo_types(current_user) |     used_counts = ammo_types |> ActivityLog.get_used_count_for_ammo_types(current_user) | ||||||
|     round_counts = ammo_types |> Ammo.get_round_count_for_ammo_types(current_user) |     round_counts = ammo_types |> Ammo.get_round_count_for_ammo_types(current_user) | ||||||
|     ammo_group_counts = ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user) |     ammo_group_counts = ammo_types |> Ammo.get_ammo_groups_count_for_types(current_user) | ||||||
| @@ -28,28 +28,27 @@ defmodule CanneryWeb.ExportController do | |||||||
|         }) |         }) | ||||||
|       end) |       end) | ||||||
|  |  | ||||||
|     ammo_groups = Ammo.list_ammo_groups(nil, true, current_user) |     ammo_groups = Ammo.list_ammo_groups(nil, :all, current_user, true) | ||||||
|     used_counts = ammo_groups |> ActivityLog.get_used_counts(current_user) |     used_counts = ammo_groups |> ActivityLog.get_used_counts(current_user) | ||||||
|     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) |     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) | ||||||
|     cprs = ammo_groups |> Ammo.get_cprs(current_user) |     cprs = ammo_groups |> Ammo.get_cprs(current_user) | ||||||
|  |     percentages_remaining = ammo_groups |> Ammo.get_percentages_remaining(current_user) | ||||||
|  |  | ||||||
|     ammo_groups = |     ammo_groups = | ||||||
|       ammo_groups |       ammo_groups | ||||||
|       |> Enum.map(fn %{id: ammo_group_id} = ammo_group -> |       |> Enum.map(fn %{id: ammo_group_id} = ammo_group -> | ||||||
|         percentage_remaining = ammo_group |> Ammo.get_percentage_remaining(current_user) |  | ||||||
|  |  | ||||||
|         ammo_group |         ammo_group | ||||||
|         |> Jason.encode!() |         |> Jason.encode!() | ||||||
|         |> Jason.decode!() |         |> Jason.decode!() | ||||||
|         |> Map.merge(%{ |         |> Map.merge(%{ | ||||||
|           "used_count" => Map.get(used_counts, ammo_group_id), |           "used_count" => Map.get(used_counts, ammo_group_id), | ||||||
|           "percentage_remaining" => percentage_remaining, |           "percentage_remaining" => Map.fetch!(percentages_remaining, ammo_group_id), | ||||||
|           "original_count" => Map.get(original_counts, ammo_group_id), |           "original_count" => Map.get(original_counts, ammo_group_id), | ||||||
|           "cpr" => Map.get(cprs, ammo_group_id) |           "cpr" => Map.get(cprs, ammo_group_id) | ||||||
|         }) |         }) | ||||||
|       end) |       end) | ||||||
|  |  | ||||||
|     shot_groups = ActivityLog.list_shot_groups(current_user) |     shot_groups = ActivityLog.list_shot_groups(:all, current_user) | ||||||
|  |  | ||||||
|     containers = |     containers = | ||||||
|       Containers.list_containers(current_user) |       Containers.list_containers(current_user) | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do | |||||||
|       socket = |       socket = | ||||||
|       socket |       socket | ||||||
|       |> assign(:ammo_group_create_limit, @ammo_group_create_limit) |       |> assign(:ammo_group_create_limit, @ammo_group_create_limit) | ||||||
|       |> assign(:ammo_types, Ammo.list_ammo_types(current_user)) |       |> assign(:ammo_types, Ammo.list_ammo_types(current_user, :all)) | ||||||
|       |> assign_new(:containers, fn -> Containers.list_containers(current_user) end) |       |> assign_new(:containers, fn -> Containers.list_containers(current_user) end) | ||||||
|  |  | ||||||
|     params = |     params = | ||||||
|   | |||||||
| @@ -8,11 +8,16 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | |||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def mount(%{"search" => search}, _session, socket) do |   def mount(%{"search" => search}, _session, socket) do | ||||||
|     {:ok, socket |> assign(show_used: false, search: search) |> display_ammo_groups()} |     socket = | ||||||
|  |       socket | ||||||
|  |       |> assign(class: :all, show_used: false, search: search) | ||||||
|  |       |> display_ammo_groups() | ||||||
|  |  | ||||||
|  |     {:ok, socket} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def mount(_params, _session, socket) do |   def mount(_params, _session, socket) do | ||||||
|     {:ok, socket |> assign(show_used: false, search: nil) |> display_ammo_groups()} |     {:ok, socket |> assign(class: :all, show_used: false, search: nil) |> display_ammo_groups()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
| @@ -119,10 +124,36 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | |||||||
|     {:noreply, socket} |     {:noreply, socket} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "rifle"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :rifle) |> display_ammo_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "shotgun"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :shotgun) |> display_ammo_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "pistol"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :pistol) |> display_ammo_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => _all}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :all) |> display_ammo_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|   defp display_ammo_groups( |   defp display_ammo_groups( | ||||||
|          %{assigns: %{search: search, current_user: current_user, show_used: show_used}} = socket |          %{ | ||||||
|  |            assigns: %{ | ||||||
|  |              class: class, | ||||||
|  |              search: search, | ||||||
|  |              current_user: current_user, | ||||||
|  |              show_used: show_used | ||||||
|  |            } | ||||||
|  |          } = socket | ||||||
|        ) do |        ) do | ||||||
|     ammo_groups = Ammo.list_ammo_groups(search, show_used, current_user) |     # get total number of ammo groups to determine whether to display onboarding | ||||||
|  |     # prompts | ||||||
|  |     ammo_groups_count = Ammo.get_ammo_groups_count!(current_user, true) | ||||||
|  |     ammo_groups = Ammo.list_ammo_groups(search, class, current_user, show_used) | ||||||
|     ammo_types_count = Ammo.get_ammo_types_count!(current_user) |     ammo_types_count = Ammo.get_ammo_types_count!(current_user) | ||||||
|     containers_count = Containers.get_containers_count!(current_user) |     containers_count = Containers.get_containers_count!(current_user) | ||||||
|  |  | ||||||
| @@ -130,7 +161,8 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | |||||||
|     |> assign( |     |> assign( | ||||||
|       ammo_groups: ammo_groups, |       ammo_groups: ammo_groups, | ||||||
|       ammo_types_count: ammo_types_count, |       ammo_types_count: ammo_types_count, | ||||||
|       containers_count: containers_count |       containers_count: containers_count, | ||||||
|  |       ammo_groups_count: ammo_groups_count | ||||||
|     ) |     ) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -3,14 +3,6 @@ | |||||||
|     <%= gettext("Ammo") %> |     <%= gettext("Ammo") %> | ||||||
|   </h1> |   </h1> | ||||||
|  |  | ||||||
|   <h2 |  | ||||||
|     :if={@ammo_groups |> Enum.empty?() and @search |> is_nil()} |  | ||||||
|     class="title text-xl text-primary-600" |  | ||||||
|   > |  | ||||||
|     <%= gettext("No Ammo") %> |  | ||||||
|     <%= display_emoji("😔") %> |  | ||||||
|   </h2> |  | ||||||
|  |  | ||||||
|   <%= cond do %> |   <%= cond do %> | ||||||
|     <% @containers_count == 0 -> %> |     <% @containers_count == 0 -> %> | ||||||
|       <div class="flex justify-center items-center"> |       <div class="flex justify-center items-center"> | ||||||
| @@ -32,7 +24,12 @@ | |||||||
|           <%= dgettext("actions", "add an ammo type first") %> |           <%= dgettext("actions", "add an ammo type first") %> | ||||||
|         </.link> |         </.link> | ||||||
|       </div> |       </div> | ||||||
|     <% @ammo_groups |> Enum.empty?() and @search |> is_nil() -> %> |     <% @ammo_groups_count == 0 -> %> | ||||||
|  |       <h2 class="title text-xl text-primary-600"> | ||||||
|  |         <%= gettext("No ammo") %> | ||||||
|  |         <%= display_emoji("😔") %> | ||||||
|  |       </h2> | ||||||
|  |  | ||||||
|       <.link patch={Routes.ammo_group_index_path(Endpoint, :new)} class="btn btn-primary"> |       <.link patch={Routes.ammo_group_index_path(Endpoint, :new)} class="btn btn-primary"> | ||||||
|         <%= dgettext("actions", "Add your first box!") %> |         <%= dgettext("actions", "Add your first box!") %> | ||||||
|       </.link> |       </.link> | ||||||
| @@ -40,19 +37,44 @@ | |||||||
|       <.link patch={Routes.ammo_group_index_path(Endpoint, :new)} class="btn btn-primary"> |       <.link patch={Routes.ammo_group_index_path(Endpoint, :new)} class="btn btn-primary"> | ||||||
|         <%= dgettext("actions", "Add Ammo") %> |         <%= dgettext("actions", "Add Ammo") %> | ||||||
|       </.link> |       </.link> | ||||||
|   <% end %> |  | ||||||
|  |  | ||||||
|   <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl"> |       <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-2xl"> | ||||||
|  |         <.form | ||||||
|  |           :let={f} | ||||||
|  |           for={%{}} | ||||||
|  |           as={:ammo_type} | ||||||
|  |           phx-change="change_class" | ||||||
|  |           phx-submit="change_class" | ||||||
|  |           class="flex items-center" | ||||||
|  |         > | ||||||
|  |           <%= label(f, :class, gettext("Class"), | ||||||
|  |             class: "title text-primary-600 text-lg text-center" | ||||||
|  |           ) %> | ||||||
|  |  | ||||||
|  |           <%= select( | ||||||
|  |             f, | ||||||
|  |             :class, | ||||||
|  |             [ | ||||||
|  |               {gettext("All"), :all}, | ||||||
|  |               {gettext("Rifle"), :rifle}, | ||||||
|  |               {gettext("Shotgun"), :shotgun}, | ||||||
|  |               {gettext("Pistol"), :pistol} | ||||||
|  |             ], | ||||||
|  |             class: "mx-2 my-1 min-w-md input input-primary", | ||||||
|  |             value: @class | ||||||
|  |           ) %> | ||||||
|  |         </.form> | ||||||
|  |  | ||||||
|         <.form |         <.form | ||||||
|           :let={f} |           :let={f} | ||||||
|           for={%{}} |           for={%{}} | ||||||
|           as={:search} |           as={:search} | ||||||
|           phx-change="search" |           phx-change="search" | ||||||
|           phx-submit="search" |           phx-submit="search" | ||||||
|       class="grow self-stretch flex flex-col items-stretch" |           class="grow flex items-center" | ||||||
|         > |         > | ||||||
|           <%= text_input(f, :search_term, |           <%= text_input(f, :search_term, | ||||||
|         class: "input input-primary", |             class: "grow input input-primary", | ||||||
|             value: @search, |             value: @search, | ||||||
|             role: "search", |             role: "search", | ||||||
|             phx_debounce: 300, |             phx_debounce: 300, | ||||||
| @@ -78,6 +100,7 @@ | |||||||
|           id="ammo-group-index-table" |           id="ammo-group-index-table" | ||||||
|           ammo_groups={@ammo_groups} |           ammo_groups={@ammo_groups} | ||||||
|           current_user={@current_user} |           current_user={@current_user} | ||||||
|  |           show_used={@show_used} | ||||||
|         > |         > | ||||||
|           <:ammo_type :let={%{name: ammo_type_name} = ammo_type}> |           <:ammo_type :let={%{name: ammo_type_name} = ammo_type}> | ||||||
|             <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, ammo_type)} class="link"> |             <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, ammo_type)} class="link"> | ||||||
| @@ -178,6 +201,7 @@ | |||||||
|           </:actions> |           </:actions> | ||||||
|         </.live_component> |         </.live_component> | ||||||
|       <% end %> |       <% end %> | ||||||
|  |   <% end %> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <%= case @live_action do %> | <%= case @live_action do %> | ||||||
|   | |||||||
| @@ -15,11 +15,24 @@ | |||||||
|       :if={@changeset.action && not @changeset.valid?()} |       :if={@changeset.action && not @changeset.valid?()} | ||||||
|       class="invalid-feedback col-span-3 text-center" |       class="invalid-feedback col-span-3 text-center" | ||||||
|     > |     > | ||||||
|       <%= changeset_errors(@changeset) %> |       <%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|  |     <%= label(f, :class, gettext("Class"), class: "title text-lg text-primary-600") %> | ||||||
|  |     <%= select( | ||||||
|  |       f, | ||||||
|  |       :class, | ||||||
|  |       [{gettext("Rifle"), :rifle}, {gettext("Shotgun"), :shotgun}, {gettext("Pistol"), :pistol}], | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|  |     <%= error_tag(f, :class, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> |     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :name, class: "text-center col-span-2 input input-primary") %> |     <%= text_input(f, :name, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|     <%= error_tag(f, :name, "col-span-3 text-center") %> |     <%= error_tag(f, :name, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= label(f, :desc, gettext("Description"), class: "title text-lg text-primary-600") %> |     <%= label(f, :desc, gettext("Description"), class: "title text-lg text-primary-600") %> | ||||||
| @@ -31,77 +44,70 @@ | |||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :desc, "col-span-3 text-center") %> |     <%= error_tag(f, :desc, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <.link |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|       href="https://shootersreference.com/reloadingdata/bullet_abbreviations/" |       <%= gettext("Dimensions") %> | ||||||
|       class="col-span-3 text-center link title text-md text-primary-600" |     </h2> | ||||||
|     > |  | ||||||
|       <%= gettext("Example bullet type abbreviations") %> |  | ||||||
|     </.link> |  | ||||||
|     <%= label(f, :bullet_type, gettext("Bullet type"), class: "title text-lg text-primary-600") %> |  | ||||||
|     <%= text_input(f, :bullet_type, |  | ||||||
|       class: "text-center col-span-2 input input-primary", |  | ||||||
|       placeholder: gettext("FMJ") |  | ||||||
|     ) %> |  | ||||||
|     <%= error_tag(f, :bullet_type, "col-span-3 text-center") %> |  | ||||||
|  |  | ||||||
|     <%= label(f, :bullet_core, gettext("Bullet core"), class: "title text-lg text-primary-600") %> |  | ||||||
|     <%= text_input(f, :bullet_core, |  | ||||||
|       class: "text-center col-span-2 input input-primary", |  | ||||||
|       placeholder: gettext("Steel") |  | ||||||
|     ) %> |  | ||||||
|     <%= error_tag(f, :bullet_core, "col-span-3 text-center") %> |  | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) in [:rifle, :pistol] do %> | ||||||
|       <%= label(f, :cartridge, gettext("Cartridge"), class: "title text-lg text-primary-600") %> |       <%= label(f, :cartridge, gettext("Cartridge"), class: "title text-lg text-primary-600") %> | ||||||
|       <%= text_input(f, :cartridge, |       <%= text_input(f, :cartridge, | ||||||
|         class: "text-center col-span-2 input input-primary", |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255, | ||||||
|         placeholder: gettext("5.56x46mm NATO") |         placeholder: gettext("5.56x46mm NATO") | ||||||
|       ) %> |       ) %> | ||||||
|       <%= error_tag(f, :cartridge, "col-span-3 text-center") %> |       <%= error_tag(f, :cartridge, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :cartridge, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|     <%= label(f, :caliber, gettext("Caliber"), class: "title text-lg text-primary-600") %> |     <%= label( | ||||||
|  |       f, | ||||||
|  |       :caliber, | ||||||
|  |       if(Changeset.get_field(@changeset, :class) == :shotgun, | ||||||
|  |         do: gettext("Gauge"), | ||||||
|  |         else: gettext("Caliber") | ||||||
|  |       ), | ||||||
|  |       class: "title text-lg text-primary-600" | ||||||
|  |     ) %> | ||||||
|     <%= text_input(f, :caliber, |     <%= text_input(f, :caliber, | ||||||
|       class: "text-center col-span-2 input input-primary", |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext(".223") |       placeholder: gettext(".223") | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :caliber, "col-span-3 text-center") %> |     <%= error_tag(f, :caliber, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= label(f, :case_material, gettext("Case material"), class: "title text-lg text-primary-600") %> |     <%= if Changeset.get_field(@changeset, :class) == :shotgun do %> | ||||||
|     <%= text_input(f, :case_material, |       <%= label(f, :unfired_length, gettext("Unfired shell length"), | ||||||
|       class: "text-center col-span-2 input input-primary", |  | ||||||
|       placeholder: gettext("Brass") |  | ||||||
|     ) %> |  | ||||||
|     <%= error_tag(f, :case_material, "col-span-3 text-center") %> |  | ||||||
|  |  | ||||||
|     <%= label(f, :jacket_type, gettext("Jacket type"), class: "title text-lg text-primary-600") %> |  | ||||||
|     <%= text_input(f, :jacket_type, |  | ||||||
|       class: "text-center col-span-2 input input-primary", |  | ||||||
|       placeholder: gettext("Bimetal") |  | ||||||
|     ) %> |  | ||||||
|     <%= error_tag(f, :case_material, "col-span-3 text-center") %> |  | ||||||
|  |  | ||||||
|     <%= label(f, :muzzle_velocity, gettext("Muzzle velocity"), |  | ||||||
|         class: "title text-lg text-primary-600" |         class: "title text-lg text-primary-600" | ||||||
|       ) %> |       ) %> | ||||||
|     <%= number_input(f, :muzzle_velocity, |       <%= text_input(f, :unfired_length, | ||||||
|       step: "1", |  | ||||||
|         class: "text-center col-span-2 input input-primary", |         class: "text-center col-span-2 input input-primary", | ||||||
|       min: 1 |         maxlength: 255 | ||||||
|       ) %> |       ) %> | ||||||
|     <%= error_tag(f, :muzzle_velocity, "col-span-3 text-center") %> |       <%= error_tag(f, :unfired_length, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= label(f, :powder_type, gettext("Powder type"), class: "title text-lg text-primary-600") %> |       <%= label(f, :brass_height, gettext("Brass height"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :powder_type, class: "text-center col-span-2 input input-primary") %> |       <%= text_input(f, :brass_height, | ||||||
|     <%= error_tag(f, :powder_type, "col-span-3 text-center") %> |  | ||||||
|  |  | ||||||
|     <%= label(f, :powder_grains_per_charge, gettext("Powder grains per charge"), |  | ||||||
|       class: "title text-lg text-primary-600" |  | ||||||
|     ) %> |  | ||||||
|     <%= number_input(f, :powder_grains_per_charge, |  | ||||||
|       step: "1", |  | ||||||
|         class: "text-center col-span-2 input input-primary", |         class: "text-center col-span-2 input input-primary", | ||||||
|       min: 1 |         maxlength: 255 | ||||||
|       ) %> |       ) %> | ||||||
|     <%= error_tag(f, :powder_grains_per_charge, "col-span-3 text-center") %> |       <%= error_tag(f, :brass_height, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :chamber_size, gettext("Chamber size"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= text_input(f, :chamber_size, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :chamber_size, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :unfired_length, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :brass_height, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :chamber_size, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|  |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|  |       <%= gettext("Projectile") %> | ||||||
|  |     </h2> | ||||||
|  |  | ||||||
|     <%= label(f, :grains, gettext("Grains"), class: "title text-lg text-primary-600") %> |     <%= label(f, :grains, gettext("Grains"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= number_input(f, :grains, |     <%= number_input(f, :grains, | ||||||
| @@ -111,16 +117,186 @@ | |||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :grains, "col-span-3 text-center") %> |     <%= error_tag(f, :grains, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= label f, :bullet_type, class: "flex title text-lg text-primary-600 space-x-2" do %> | ||||||
|  |       <p><%= gettext("Bullet type") %></p> | ||||||
|  |  | ||||||
|  |       <.link | ||||||
|  |         href="https://shootersreference.com/reloadingdata/bullet_abbreviations/" | ||||||
|  |         class="link" | ||||||
|  |         target="_blank" | ||||||
|  |         rel="noopener noreferrer" | ||||||
|  |       > | ||||||
|  |         <i class="fas fa-md fa-external-link-alt"></i> | ||||||
|  |       </.link> | ||||||
|  |     <% end %> | ||||||
|  |     <%= text_input(f, :bullet_type, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|  |       placeholder: gettext("FMJ") | ||||||
|  |     ) %> | ||||||
|  |     <%= error_tag(f, :bullet_type, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= label( | ||||||
|  |       f, | ||||||
|  |       :bullet_core, | ||||||
|  |       if(Changeset.get_field(@changeset, :class) == :shotgun, | ||||||
|  |         do: gettext("Slug core"), | ||||||
|  |         else: gettext("Bullet core") | ||||||
|  |       ), | ||||||
|  |       class: "title text-lg text-primary-600" | ||||||
|  |     ) %> | ||||||
|  |     <%= text_input(f, :bullet_core, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|  |       placeholder: gettext("Steel") | ||||||
|  |     ) %> | ||||||
|  |     <%= error_tag(f, :bullet_core, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) in [:rifle, :pistol] do %> | ||||||
|  |       <%= label(f, :jacket_type, gettext("Jacket type"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= text_input(f, :jacket_type, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255, | ||||||
|  |         placeholder: gettext("Bimetal") | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :jacket_type, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :jacket_type, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|  |     <%= label(f, :case_material, gettext("Case material"), class: "title text-lg text-primary-600") %> | ||||||
|  |     <%= text_input(f, :case_material, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|  |       placeholder: gettext("Brass") | ||||||
|  |     ) %> | ||||||
|  |     <%= error_tag(f, :case_material, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) == :shotgun do %> | ||||||
|  |       <%= label(f, :wadding, gettext("Wadding"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= text_input(f, :wadding, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :wadding, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :shot_type, gettext("Shot type"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= text_input(f, :shot_type, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255, | ||||||
|  |         placeholder: gettext("Target, bird, buck, etc") | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :shot_type, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :shot_material, gettext("Shot material"), | ||||||
|  |         class: "title text-lg text-primary-600" | ||||||
|  |       ) %> | ||||||
|  |       <%= text_input(f, :shot_material, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :shot_material, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :shot_size, gettext("Shot size"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= text_input(f, :shot_size, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :shot_size, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :load_grains, gettext("Load grains"), class: "title text-lg text-primary-600") %> | ||||||
|  |       <%= number_input(f, :load_grains, | ||||||
|  |         step: "1", | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         min: 1 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :load_grains, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |       <%= label(f, :shot_charge_weight, gettext("Shot charge weight"), | ||||||
|  |         class: "title text-lg text-primary-600" | ||||||
|  |       ) %> | ||||||
|  |       <%= text_input(f, :shot_charge_weight, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :shot_charge_weight, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :wadding, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :shot_type, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :shot_material, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :shot_size, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :load_grains, value: nil) %> | ||||||
|  |       <%= hidden_input(f, :shot_charge_weight, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|  |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|  |       <%= gettext("Powder") %> | ||||||
|  |     </h2> | ||||||
|  |  | ||||||
|  |     <%= label(f, :powder_type, gettext("Powder type"), class: "title text-lg text-primary-600") %> | ||||||
|  |     <%= text_input(f, :powder_type, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|  |     <%= error_tag(f, :powder_type, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) in [:rifle, :pistol] do %> | ||||||
|  |       <%= label(f, :powder_grains_per_charge, gettext("Powder grains per charge"), | ||||||
|  |         class: "title text-lg text-primary-600" | ||||||
|  |       ) %> | ||||||
|  |       <%= number_input(f, :powder_grains_per_charge, | ||||||
|  |         step: "1", | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         min: 1 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :powder_grains_per_charge, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :powder_grains_per_charge, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|     <%= label(f, :pressure, gettext("Pressure"), class: "title text-lg text-primary-600") %> |     <%= label(f, :pressure, gettext("Pressure"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :pressure, |     <%= text_input(f, :pressure, | ||||||
|       class: "text-center col-span-2 input input-primary", |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext("+P") |       placeholder: gettext("+P") | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :pressure, "col-span-3 text-center") %> |     <%= error_tag(f, :pressure, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) == :shotgun do %> | ||||||
|  |       <%= label(f, :dram_equivalent, gettext("Dram equivalent"), | ||||||
|  |         class: "title text-lg text-primary-600" | ||||||
|  |       ) %> | ||||||
|  |       <%= text_input(f, :dram_equivalent, | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         maxlength: 255 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :dram_equivalent, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :dram_equivalent, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|  |     <%= if Changeset.get_field(@changeset, :class) in [:rifle, :pistol] do %> | ||||||
|  |       <%= label(f, :muzzle_velocity, gettext("Muzzle velocity"), | ||||||
|  |         class: "title text-lg text-primary-600" | ||||||
|  |       ) %> | ||||||
|  |       <%= number_input(f, :muzzle_velocity, | ||||||
|  |         step: "1", | ||||||
|  |         class: "text-center col-span-2 input input-primary", | ||||||
|  |         min: 1 | ||||||
|  |       ) %> | ||||||
|  |       <%= error_tag(f, :muzzle_velocity, "col-span-3 text-center") %> | ||||||
|  |     <% else %> | ||||||
|  |       <%= hidden_input(f, :muzzle_velocity, value: nil) %> | ||||||
|  |     <% end %> | ||||||
|  |  | ||||||
|  |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|  |       <%= gettext("Primer") %> | ||||||
|  |     </h2> | ||||||
|  |  | ||||||
|     <%= label(f, :primer_type, gettext("Primer type"), class: "title text-lg text-primary-600") %> |     <%= label(f, :primer_type, gettext("Primer type"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :primer_type, |     <%= text_input(f, :primer_type, | ||||||
|       class: "text-center col-span-2 input input-primary", |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext("Boxer") |       placeholder: gettext("Boxer") | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :primer_type, "col-span-3 text-center") %> |     <%= error_tag(f, :primer_type, "col-span-3 text-center") %> | ||||||
| @@ -128,10 +304,15 @@ | |||||||
|     <%= label(f, :firing_type, gettext("Firing type"), class: "title text-lg text-primary-600") %> |     <%= label(f, :firing_type, gettext("Firing type"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :firing_type, |     <%= text_input(f, :firing_type, | ||||||
|       class: "text-center col-span-2 input input-primary", |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext("Centerfire") |       placeholder: gettext("Centerfire") | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :firing_type, "col-span-3 text-center") %> |     <%= error_tag(f, :firing_type, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|  |       <%= gettext("Attributes") %> | ||||||
|  |     </h2> | ||||||
|  |  | ||||||
|     <%= label(f, :tracer, gettext("Tracer"), class: "title text-lg text-primary-600") %> |     <%= label(f, :tracer, gettext("Tracer"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= checkbox(f, :tracer, class: "text-center col-span-2 checkbox") %> |     <%= checkbox(f, :tracer, class: "text-center col-span-2 checkbox") %> | ||||||
|     <%= error_tag(f, :tracer, "col-span-3 text-center") %> |     <%= error_tag(f, :tracer, "col-span-3 text-center") %> | ||||||
| @@ -148,12 +329,22 @@ | |||||||
|     <%= checkbox(f, :corrosive, class: "text-center col-span-2 checkbox") %> |     <%= checkbox(f, :corrosive, class: "text-center col-span-2 checkbox") %> | ||||||
|     <%= error_tag(f, :corrosive, "col-span-3 text-center") %> |     <%= error_tag(f, :corrosive, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|  |     <h2 class="text-center title text-lg text-primary-600 col-span-3"> | ||||||
|  |       <%= gettext("Manufacturer") %> | ||||||
|  |     </h2> | ||||||
|  |  | ||||||
|     <%= label(f, :manufacturer, gettext("Manufacturer"), class: "title text-lg text-primary-600") %> |     <%= label(f, :manufacturer, gettext("Manufacturer"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :manufacturer, class: "text-center col-span-2 input input-primary") %> |     <%= text_input(f, :manufacturer, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|     <%= error_tag(f, :manufacturer, "col-span-3 text-center") %> |     <%= error_tag(f, :manufacturer, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= label(f, :upc, gettext("UPC"), class: "title text-lg text-primary-600") %> |     <%= label(f, :upc, gettext("UPC"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :upc, class: "text-center col-span-2 input input-primary") %> |     <%= text_input(f, :upc, | ||||||
|  |       class: "text-center col-span-2 input input-primary", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|     <%= error_tag(f, :upc, "col-span-3 text-center") %> |     <%= error_tag(f, :upc, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|     <%= submit(dgettext("actions", "Save"), |     <%= submit(dgettext("actions", "Save"), | ||||||
|   | |||||||
| @@ -8,11 +8,11 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | |||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def mount(%{"search" => search}, _session, socket) do |   def mount(%{"search" => search}, _session, socket) do | ||||||
|     {:ok, socket |> assign(show_used: false, search: search) |> list_ammo_types()} |     {:ok, socket |> assign(class: :all, show_used: false, search: search) |> list_ammo_types()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def mount(_params, _session, socket) do |   def mount(_params, _session, socket) do | ||||||
|     {:ok, socket |> assign(show_used: false, search: nil) |> list_ammo_types()} |     {:ok, socket |> assign(class: :all, show_used: false, search: nil) |> list_ammo_types()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
| @@ -86,7 +86,29 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | |||||||
|     {:noreply, socket |> push_patch(to: search_path)} |     {:noreply, socket |> push_patch(to: search_path)} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp list_ammo_types(%{assigns: %{search: search, current_user: current_user}} = socket) do |   def handle_event("change_class", %{"ammo_type" => %{"class" => "rifle"}}, socket) do | ||||||
|     socket |> assign(ammo_types: Ammo.list_ammo_types(search, current_user)) |     {:noreply, socket |> assign(:class, :rifle) |> list_ammo_types()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "shotgun"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :shotgun) |> list_ammo_types()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "pistol"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :pistol) |> list_ammo_types()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => _all}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :all) |> list_ammo_types()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   defp list_ammo_types( | ||||||
|  |          %{assigns: %{class: class, search: search, current_user: current_user}} = socket | ||||||
|  |        ) do | ||||||
|  |     socket | ||||||
|  |     |> assign( | ||||||
|  |       ammo_types: Ammo.list_ammo_types(search, current_user, class), | ||||||
|  |       ammo_types_count: Ammo.get_ammo_types_count!(current_user) | ||||||
|  |     ) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
|     <%= gettext("Catalog") %> |     <%= gettext("Catalog") %> | ||||||
|   </h1> |   </h1> | ||||||
|  |  | ||||||
|   <%= if @ammo_types |> Enum.empty?() and @search |> is_nil() do %> |   <%= if @ammo_types_count == 0 do %> | ||||||
|     <h2 class="title text-xl text-primary-600"> |     <h2 class="title text-xl text-primary-600"> | ||||||
|       <%= gettext("No Ammo types") %> |       <%= gettext("No Ammo types") %> | ||||||
|       <%= display_emoji("😔") %> |       <%= display_emoji("😔") %> | ||||||
| @@ -17,17 +17,41 @@ | |||||||
|       <%= dgettext("actions", "New Ammo type") %> |       <%= dgettext("actions", "New Ammo type") %> | ||||||
|     </.link> |     </.link> | ||||||
|  |  | ||||||
|     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl"> |     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-2xl"> | ||||||
|  |       <.form | ||||||
|  |         :let={f} | ||||||
|  |         for={%{}} | ||||||
|  |         as={:ammo_type} | ||||||
|  |         phx-change="change_class" | ||||||
|  |         phx-submit="change_class" | ||||||
|  |         class="flex items-center" | ||||||
|  |       > | ||||||
|  |         <%= label(f, :class, gettext("Class"), class: "title text-primary-600 text-lg text-center") %> | ||||||
|  |  | ||||||
|  |         <%= select( | ||||||
|  |           f, | ||||||
|  |           :class, | ||||||
|  |           [ | ||||||
|  |             {gettext("All"), :all}, | ||||||
|  |             {gettext("Rifle"), :rifle}, | ||||||
|  |             {gettext("Shotgun"), :shotgun}, | ||||||
|  |             {gettext("Pistol"), :pistol} | ||||||
|  |           ], | ||||||
|  |           class: "mx-2 my-1 min-w-md input input-primary", | ||||||
|  |           value: @class | ||||||
|  |         ) %> | ||||||
|  |       </.form> | ||||||
|  |  | ||||||
|       <.form |       <.form | ||||||
|         :let={f} |         :let={f} | ||||||
|         for={%{}} |         for={%{}} | ||||||
|         as={:search} |         as={:search} | ||||||
|         phx-change="search" |         phx-change="search" | ||||||
|         phx-submit="search" |         phx-submit="search" | ||||||
|         class="grow self-stretch flex flex-col items-stretch" |         class="grow flex items-center" | ||||||
|       > |       > | ||||||
|         <%= text_input(f, :search_term, |         <%= text_input(f, :search_term, | ||||||
|           class: "input input-primary", |           class: "grow input input-primary", | ||||||
|           value: @search, |           value: @search, | ||||||
|           role: "search", |           role: "search", | ||||||
|           phx_debounce: 300, |           phx_debounce: 300, | ||||||
| @@ -55,6 +79,7 @@ | |||||||
|         ammo_types={@ammo_types} |         ammo_types={@ammo_types} | ||||||
|         current_user={@current_user} |         current_user={@current_user} | ||||||
|         show_used={@show_used} |         show_used={@show_used} | ||||||
|  |         class={@class} | ||||||
|       > |       > | ||||||
|         <:actions :let={ammo_type}> |         <:actions :let={ammo_type}> | ||||||
|           <div class="px-4 py-2 space-x-4 flex justify-center items-center"> |           <div class="px-4 py-2 space-x-4 flex justify-center items-center"> | ||||||
|   | |||||||
| @@ -4,43 +4,16 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb, :live_view |   use CanneryWeb, :live_view | ||||||
|   alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType} |   alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType, Containers} | ||||||
|   alias CanneryWeb.Endpoint |   alias CanneryWeb.Endpoint | ||||||
|  |  | ||||||
|   @fields_list [ |   @impl true | ||||||
|     %{label: gettext("Bullet type:"), key: :bullet_type, type: :string}, |   def mount(_params, _session, socket), | ||||||
|     %{label: gettext("Bullet core:"), key: :bullet_core, type: :string}, |     do: {:ok, socket |> assign(show_used: false, view_table: true)} | ||||||
|     %{label: gettext("Cartridge:"), key: :cartridge, type: :string}, |  | ||||||
|     %{label: gettext("Caliber:"), key: :caliber, type: :string}, |  | ||||||
|     %{label: gettext("Case material:"), key: :case_material, type: :string}, |  | ||||||
|     %{label: gettext("Jacket type:"), key: :jacket_type, type: :string}, |  | ||||||
|     %{label: gettext("Muzzle velocity:"), key: :muzzle_velocity, type: :string}, |  | ||||||
|     %{label: gettext("Powder type:"), key: :powder_type, type: :string}, |  | ||||||
|     %{label: gettext("Powder grains per charge:"), key: :powder_grains_per_charge, type: :string}, |  | ||||||
|     %{label: gettext("Grains:"), key: :grains, type: :string}, |  | ||||||
|     %{label: gettext("Pressure:"), key: :pressure, type: :string}, |  | ||||||
|     %{label: gettext("Primer type:"), key: :primer_type, type: :string}, |  | ||||||
|     %{label: gettext("Firing type:"), key: :firing_type, type: :string}, |  | ||||||
|     %{label: gettext("Tracer:"), key: :tracer, type: :boolean}, |  | ||||||
|     %{label: gettext("Incendiary:"), key: :incendiary, type: :boolean}, |  | ||||||
|     %{label: gettext("Blank:"), key: :blank, type: :boolean}, |  | ||||||
|     %{label: gettext("Corrosive:"), key: :corrosive, type: :boolean}, |  | ||||||
|     %{label: gettext("Manufacturer:"), key: :manufacturer, type: :string}, |  | ||||||
|     %{label: gettext("UPC:"), key: :upc, type: :string} |  | ||||||
|   ] |  | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def mount(_params, _session, %{assigns: %{live_action: live_action}} = socket), |   def handle_params(%{"id" => id}, _params, socket) do | ||||||
|     do: {:ok, socket |> assign(show_used: false, view_table: live_action == :table)} |     {:noreply, socket |> display_ammo_type(id)} | ||||||
|  |  | ||||||
|   @impl true |  | ||||||
|   def handle_params(%{"id" => id}, _params, %{assigns: %{live_action: live_action}} = socket) do |  | ||||||
|     socket = |  | ||||||
|       socket |  | ||||||
|       |> assign(view_table: live_action == :table) |  | ||||||
|       |> display_ammo_type(id) |  | ||||||
|  |  | ||||||
|     {:noreply, socket} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
| @@ -61,26 +34,17 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | |||||||
|     {:noreply, socket |> assign(:show_used, !show_used) |> display_ammo_type()} |     {:noreply, socket |> assign(:show_used, !show_used) |> display_ammo_type()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def handle_event( |   def handle_event("toggle_table", _params, %{assigns: %{view_table: view_table}} = socket) do | ||||||
|         "toggle_table", |     {:noreply, socket |> assign(:view_table, !view_table)} | ||||||
|         _params, |  | ||||||
|         %{assigns: %{view_table: view_table, ammo_type: ammo_type}} = socket |  | ||||||
|       ) do |  | ||||||
|     new_path = |  | ||||||
|       if view_table, |  | ||||||
|         do: Routes.ammo_type_show_path(Endpoint, :show, ammo_type), |  | ||||||
|         else: Routes.ammo_type_show_path(Endpoint, :table, ammo_type) |  | ||||||
|  |  | ||||||
|     {:noreply, socket |> push_patch(to: new_path)} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp display_ammo_type( |   defp display_ammo_type( | ||||||
|          %{assigns: %{live_action: live_action, current_user: current_user, show_used: show_used}} = |          %{assigns: %{live_action: live_action, current_user: current_user, show_used: show_used}} = | ||||||
|            socket, |            socket, | ||||||
|          %AmmoType{} = ammo_type |          %AmmoType{name: ammo_type_name} = ammo_type | ||||||
|        ) do |        ) do | ||||||
|     fields_to_display = |     custom_fields? = | ||||||
|       @fields_list |       fields_to_display(ammo_type) | ||||||
|       |> Enum.any?(fn %{key: field, type: type} -> |       |> Enum.any?(fn %{key: field, type: type} -> | ||||||
|         default_value = |         default_value = | ||||||
|           case type do |           case type do | ||||||
| @@ -112,11 +76,23 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | |||||||
|         [nil, nil, nil, nil, nil] |         [nil, nil, nil, nil, nil] | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  |     page_title = | ||||||
|  |       case live_action do | ||||||
|  |         :show -> ammo_type_name | ||||||
|  |         :edit -> gettext("Edit %{ammo_type_name}", ammo_type_name: ammo_type_name) | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |     containers = | ||||||
|  |       ammo_groups | ||||||
|  |       |> Enum.map(fn %{container_id: container_id} -> container_id end) | ||||||
|  |       |> Containers.get_containers(current_user) | ||||||
|  |  | ||||||
|     socket |     socket | ||||||
|     |> assign( |     |> assign( | ||||||
|       page_title: page_title(live_action, ammo_type), |       page_title: page_title, | ||||||
|       ammo_type: ammo_type, |       ammo_type: ammo_type, | ||||||
|       ammo_groups: ammo_groups, |       ammo_groups: ammo_groups, | ||||||
|  |       containers: containers, | ||||||
|       cprs: ammo_groups |> Ammo.get_cprs(current_user), |       cprs: ammo_groups |> Ammo.get_cprs(current_user), | ||||||
|       last_used_dates: ammo_groups |> ActivityLog.get_last_used_dates(current_user), |       last_used_dates: ammo_groups |> ActivityLog.get_last_used_dates(current_user), | ||||||
|       avg_cost_per_round: ammo_type |> Ammo.get_average_cost_for_ammo_type(current_user), |       avg_cost_per_round: ammo_type |> Ammo.get_average_cost_for_ammo_type(current_user), | ||||||
| @@ -127,8 +103,8 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | |||||||
|       packs_count: ammo_type |> Ammo.get_ammo_groups_count_for_type(current_user), |       packs_count: ammo_type |> Ammo.get_ammo_groups_count_for_type(current_user), | ||||||
|       used_packs_count: used_packs_count, |       used_packs_count: used_packs_count, | ||||||
|       historical_packs_count: historical_packs_count, |       historical_packs_count: historical_packs_count, | ||||||
|       fields_list: @fields_list, |       fields_to_display: fields_to_display(ammo_type), | ||||||
|       fields_to_display: fields_to_display |       custom_fields?: custom_fields? | ||||||
|     ) |     ) | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -140,12 +116,48 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | |||||||
|     socket |> display_ammo_type(ammo_type) |     socket |> display_ammo_type(ammo_type) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   defp fields_to_display(%AmmoType{class: class}) do | ||||||
|  |     [ | ||||||
|  |       %{label: gettext("Cartridge:"), key: :cartridge, type: :string}, | ||||||
|  |       %{ | ||||||
|  |         label: if(class == :shotgun, do: gettext("Gauge:"), else: gettext("Caliber:")), | ||||||
|  |         key: :caliber, | ||||||
|  |         type: :string | ||||||
|  |       }, | ||||||
|  |       %{label: gettext("Unfired length:"), key: :unfired_length, type: :string}, | ||||||
|  |       %{label: gettext("Brass height:"), key: :brass_height, type: :string}, | ||||||
|  |       %{label: gettext("Chamber size:"), key: :chamber_size, type: :string}, | ||||||
|  |       %{label: gettext("Grains:"), key: :grains, type: :string}, | ||||||
|  |       %{label: gettext("Bullet type:"), key: :bullet_type, type: :string}, | ||||||
|  |       %{label: gettext("Bullet core:"), key: :bullet_core, type: :string}, | ||||||
|  |       %{label: gettext("Jacket type:"), key: :jacket_type, type: :string}, | ||||||
|  |       %{label: gettext("Case material:"), key: :case_material, type: :string}, | ||||||
|  |       %{label: gettext("Wadding:"), key: :wadding, type: :string}, | ||||||
|  |       %{label: gettext("Shot type:"), key: :shot_type, type: :string}, | ||||||
|  |       %{label: gettext("Shot material:"), key: :shot_material, type: :string}, | ||||||
|  |       %{label: gettext("Shot size:"), key: :shot_size, type: :string}, | ||||||
|  |       %{label: gettext("Load grains:"), key: :load_grains, type: :string}, | ||||||
|  |       %{label: gettext("Shot charge weight:"), key: :shot_charge_weight, type: :string}, | ||||||
|  |       %{label: gettext("Powder type:"), key: :powder_type, type: :string}, | ||||||
|  |       %{ | ||||||
|  |         label: gettext("Powder grains per charge:"), | ||||||
|  |         key: :powder_grains_per_charge, | ||||||
|  |         type: :string | ||||||
|  |       }, | ||||||
|  |       %{label: gettext("Pressure:"), key: :pressure, type: :string}, | ||||||
|  |       %{label: gettext("Dram equivalent:"), key: :dram_equivalent, type: :string}, | ||||||
|  |       %{label: gettext("Muzzle velocity:"), key: :muzzle_velocity, type: :string}, | ||||||
|  |       %{label: gettext("Primer type:"), key: :primer_type, type: :string}, | ||||||
|  |       %{label: gettext("Firing type:"), key: :firing_type, type: :string}, | ||||||
|  |       %{label: gettext("Tracer:"), key: :tracer, type: :boolean}, | ||||||
|  |       %{label: gettext("Incendiary:"), key: :incendiary, type: :boolean}, | ||||||
|  |       %{label: gettext("Blank:"), key: :blank, type: :boolean}, | ||||||
|  |       %{label: gettext("Corrosive:"), key: :corrosive, type: :boolean}, | ||||||
|  |       %{label: gettext("Manufacturer:"), key: :manufacturer, type: :string}, | ||||||
|  |       %{label: gettext("UPC:"), key: :upc, type: :string} | ||||||
|  |     ] | ||||||
|  |   end | ||||||
|  |  | ||||||
|   @spec display_currency(float()) :: String.t() |   @spec display_currency(float()) :: String.t() | ||||||
|   defp display_currency(float), do: :erlang.float_to_binary(float, decimals: 2) |   defp display_currency(float), do: :erlang.float_to_binary(float, decimals: 2) | ||||||
|  |  | ||||||
|   defp page_title(action, %{name: ammo_type_name}) when action in [:show, :table], |  | ||||||
|     do: ammo_type_name |  | ||||||
|  |  | ||||||
|   defp page_title(:edit, %{name: ammo_type_name}), |  | ||||||
|     do: gettext("Edit %{ammo_type_name}", ammo_type_name: ammo_type_name) |  | ||||||
| end | end | ||||||
|   | |||||||
| @@ -42,9 +42,26 @@ | |||||||
|  |  | ||||||
|   <hr class="hr" /> |   <hr class="hr" /> | ||||||
|  |  | ||||||
|   <%= if @fields_to_display do %> |   <%= if @ammo_type.class || @custom_fields? do %> | ||||||
|     <div class="grid sm:grid-cols-2 gap-4 text-center justify-center items-center"> |     <div class="grid sm:grid-cols-2 gap-4 text-center justify-center items-center"> | ||||||
|       <%= for %{label: label, key: key, type: type} <- @fields_list do %> |       <h3 class="title text-lg"> | ||||||
|  |         <%= gettext("Class") %> | ||||||
|  |       </h3> | ||||||
|  |  | ||||||
|  |       <span class="text-primary-600"> | ||||||
|  |         <%= case @ammo_type.class do %> | ||||||
|  |           <% :shotgun -> %> | ||||||
|  |             <%= gettext("Shotgun") %> | ||||||
|  |           <% :rifle -> %> | ||||||
|  |             <%= gettext("Rifle") %> | ||||||
|  |           <% :pistol -> %> | ||||||
|  |             <%= gettext("Pistol") %> | ||||||
|  |           <% _ -> %> | ||||||
|  |             <%= gettext("None specified") %> | ||||||
|  |         <% end %> | ||||||
|  |       </span> | ||||||
|  |  | ||||||
|  |       <%= for %{label: label, key: key, type: type} <- @fields_to_display do %> | ||||||
|         <%= if @ammo_type |> Map.get(key) do %> |         <%= if @ammo_type |> Map.get(key) do %> | ||||||
|           <h3 class="title text-lg"> |           <h3 class="title text-lg"> | ||||||
|             <%= label %> |             <%= label %> | ||||||
| @@ -170,6 +187,7 @@ | |||||||
|           id="ammo-type-show-table" |           id="ammo-type-show-table" | ||||||
|           ammo_groups={@ammo_groups} |           ammo_groups={@ammo_groups} | ||||||
|           current_user={@current_user} |           current_user={@current_user} | ||||||
|  |           show_used={@show_used} | ||||||
|         > |         > | ||||||
|           <:container :let={{_ammo_group, %{name: container_name} = container}}> |           <:container :let={{_ammo_group, %{name: container_name} = container}}> | ||||||
|             <.link |             <.link | ||||||
| @@ -179,17 +197,32 @@ | |||||||
|               <%= container_name %> |               <%= container_name %> | ||||||
|             </.link> |             </.link> | ||||||
|           </:container> |           </:container> | ||||||
|  |           <:actions :let={%{count: ammo_group_count} = ammo_group}> | ||||||
|  |             <div class="py-2 px-4 h-full space-x-4 flex justify-center items-center"> | ||||||
|  |               <.link | ||||||
|  |                 navigate={Routes.ammo_group_show_path(Endpoint, :show, ammo_group)} | ||||||
|  |                 class="text-primary-600 link" | ||||||
|  |                 aria-label={ | ||||||
|  |                   dgettext("actions", "View ammo group of %{ammo_group_count} bullets", | ||||||
|  |                     ammo_group_count: ammo_group_count | ||||||
|  |                   ) | ||||||
|  |                 } | ||||||
|  |               > | ||||||
|  |                 <i class="fa-fw fa-lg fas fa-eye"></i> | ||||||
|  |               </.link> | ||||||
|  |             </div> | ||||||
|  |           </:actions> | ||||||
|         </.live_component> |         </.live_component> | ||||||
|       <% else %> |       <% else %> | ||||||
|         <div class="flex flex-wrap justify-center items-stretch"> |         <div class="flex flex-wrap justify-center items-stretch"> | ||||||
|           <.ammo_group_card |           <.ammo_group_card | ||||||
|             :for={%{id: ammo_group_id} = ammo_group <- @ammo_groups} |             :for={%{id: ammo_group_id, container_id: container_id} = ammo_group <- @ammo_groups} | ||||||
|             ammo_group={ammo_group} |             ammo_group={ammo_group} | ||||||
|             original_count={@original_counts && Map.fetch!(@original_counts, ammo_group_id)} |             original_count={@original_counts && Map.fetch!(@original_counts, ammo_group_id)} | ||||||
|             cpr={Map.get(@cprs, ammo_group_id)} |             cpr={Map.get(@cprs, ammo_group_id)} | ||||||
|             last_used_date={Map.get(@last_used_dates, ammo_group_id)} |             last_used_date={Map.get(@last_used_dates, ammo_group_id)} | ||||||
|             current_user={@current_user} |             current_user={@current_user} | ||||||
|             show_container={true} |             container={Map.fetch!(@containers, container_id)} | ||||||
|           /> |           /> | ||||||
|         </div> |         </div> | ||||||
|       <% end %> |       <% end %> | ||||||
|   | |||||||
| @@ -21,7 +21,8 @@ | |||||||
|     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> |     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :name, |     <%= text_input(f, :name, | ||||||
|       class: "input input-primary col-span-2", |       class: "input input-primary col-span-2", | ||||||
|       placeholder: gettext("My cool ammo can") |       placeholder: gettext("My cool ammo can"), | ||||||
|  |       maxlength: 255 | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :name, "col-span-3 text-center") %> |     <%= error_tag(f, :name, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
| @@ -38,7 +39,8 @@ | |||||||
|     <%= label(f, :type, gettext("Type"), class: "title text-lg text-primary-600") %> |     <%= label(f, :type, gettext("Type"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :type, |     <%= text_input(f, :type, | ||||||
|       class: "input input-primary col-span-2", |       class: "input input-primary col-span-2", | ||||||
|       placeholder: gettext("Magazine, Clip, Ammo Box, etc") |       placeholder: gettext("Magazine, Clip, Ammo Box, etc"), | ||||||
|  |       maxlength: 255 | ||||||
|     ) %> |     ) %> | ||||||
|     <%= error_tag(f, :type, "col-span-3 text-center") %> |     <%= error_tag(f, :type, "col-span-3 text-center") %> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,17 +17,17 @@ | |||||||
|       <%= dgettext("actions", "New Container") %> |       <%= dgettext("actions", "New Container") %> | ||||||
|     </.link> |     </.link> | ||||||
|  |  | ||||||
|     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl"> |     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-2xl"> | ||||||
|       <.form |       <.form | ||||||
|         :let={f} |         :let={f} | ||||||
|         for={%{}} |         for={%{}} | ||||||
|         as={:search} |         as={:search} | ||||||
|         phx-change="search" |         phx-change="search" | ||||||
|         phx-submit="search" |         phx-submit="search" | ||||||
|         class="grow self-stretch flex flex-col items-stretch" |         class="grow flex items-center" | ||||||
|       > |       > | ||||||
|         <%= text_input(f, :search_term, |         <%= text_input(f, :search_term, | ||||||
|           class: "input input-primary", |           class: "grow input input-primary", | ||||||
|           value: @search, |           value: @search, | ||||||
|           role: "search", |           role: "search", | ||||||
|           phx_debounce: 300, |           phx_debounce: 300, | ||||||
| @@ -41,7 +41,6 @@ | |||||||
|         </span> |         </span> | ||||||
|       </.toggle_button> |       </.toggle_button> | ||||||
|     </div> |     </div> | ||||||
|   <% end %> |  | ||||||
|  |  | ||||||
|     <%= if @containers |> Enum.empty?() do %> |     <%= if @containers |> Enum.empty?() do %> | ||||||
|       <h2 class="title text-xl text-primary-600"> |       <h2 class="title text-xl text-primary-600"> | ||||||
| @@ -97,7 +96,9 @@ | |||||||
|               phx-click="delete" |               phx-click="delete" | ||||||
|               phx-value-id={container.id} |               phx-value-id={container.id} | ||||||
|               data-confirm={ |               data-confirm={ | ||||||
|               dgettext("prompts", "Are you sure you want to delete %{name}?", name: container.name) |                 dgettext("prompts", "Are you sure you want to delete %{name}?", | ||||||
|  |                   name: container.name | ||||||
|  |                 ) | ||||||
|               } |               } | ||||||
|               aria-label={ |               aria-label={ | ||||||
|                 dgettext("actions", "Delete %{container_name}", container_name: container.name) |                 dgettext("actions", "Delete %{container_name}", container_name: container.name) | ||||||
| @@ -153,7 +154,9 @@ | |||||||
|               phx-click="delete" |               phx-click="delete" | ||||||
|               phx-value-id={container.id} |               phx-value-id={container.id} | ||||||
|               data-confirm={ |               data-confirm={ | ||||||
|               dgettext("prompts", "Are you sure you want to delete %{name}?", name: container.name) |                 dgettext("prompts", "Are you sure you want to delete %{name}?", | ||||||
|  |                   name: container.name | ||||||
|  |                 ) | ||||||
|               } |               } | ||||||
|               aria-label={ |               aria-label={ | ||||||
|                 dgettext("actions", "Delete %{container_name}", container_name: container.name) |                 dgettext("actions", "Delete %{container_name}", container_name: container.name) | ||||||
| @@ -165,6 +168,7 @@ | |||||||
|         </div> |         </div> | ||||||
|       <% end %> |       <% end %> | ||||||
|     <% end %> |     <% end %> | ||||||
|  |   <% end %> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <%= case @live_action do %> | <%= case @live_action do %> | ||||||
|   | |||||||
| @@ -11,13 +11,13 @@ defmodule CanneryWeb.ContainerLive.Show do | |||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def mount(_params, _session, socket), |   def mount(_params, _session, socket), | ||||||
|     do: {:ok, socket |> assign(show_used: false, view_table: true)} |     do: {:ok, socket |> assign(class: :all, view_table: true)} | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def handle_params(%{"id" => id}, _session, %{assigns: %{current_user: current_user}} = socket) do |   def handle_params(%{"id" => id}, _session, %{assigns: %{current_user: current_user}} = socket) do | ||||||
|     socket = |     socket = | ||||||
|       socket |       socket | ||||||
|       |> assign(view_table: true) |       |> assign(:view_table, true) | ||||||
|       |> render_container(id, current_user) |       |> render_container(id, current_user) | ||||||
|  |  | ||||||
|     {:noreply, socket} |     {:noreply, socket} | ||||||
| @@ -82,29 +82,41 @@ defmodule CanneryWeb.ContainerLive.Show do | |||||||
|     {:noreply, socket} |     {:noreply, socket} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def handle_event("toggle_show_used", _params, %{assigns: %{show_used: show_used}} = socket) do |  | ||||||
|     {:noreply, socket |> assign(:show_used, !show_used) |> render_container()} |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   def handle_event("toggle_table", _params, %{assigns: %{view_table: view_table}} = socket) do |   def handle_event("toggle_table", _params, %{assigns: %{view_table: view_table}} = socket) do | ||||||
|     {:noreply, socket |> assign(:view_table, !view_table) |> render_container()} |     {:noreply, socket |> assign(:view_table, !view_table) |> render_container()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "rifle"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :rifle) |> render_container()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "shotgun"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :shotgun) |> render_container()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "pistol"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :pistol) |> render_container()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => _all}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :all) |> render_container()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|   @spec render_container(Socket.t(), Container.id(), User.t()) :: Socket.t() |   @spec render_container(Socket.t(), Container.id(), User.t()) :: Socket.t() | ||||||
|   defp render_container( |   defp render_container( | ||||||
|          %{assigns: %{live_action: live_action, show_used: show_used}} = socket, |          %{assigns: %{class: class, live_action: live_action}} = socket, | ||||||
|          id, |          id, | ||||||
|          current_user |          current_user | ||||||
|        ) do |        ) do | ||||||
|     %{name: container_name} = container = Containers.get_container!(id, current_user) |     %{name: container_name} = container = Containers.get_container!(id, current_user) | ||||||
|     ammo_groups = Ammo.list_ammo_groups_for_container(container, current_user, show_used) |     ammo_groups = Ammo.list_ammo_groups_for_container(container, class, current_user) | ||||||
|     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) |     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) | ||||||
|     cprs = ammo_groups |> Ammo.get_cprs(current_user) |     cprs = ammo_groups |> Ammo.get_cprs(current_user) | ||||||
|     last_used_dates = ammo_groups |> ActivityLog.get_last_used_dates(current_user) |     last_used_dates = ammo_groups |> ActivityLog.get_last_used_dates(current_user) | ||||||
|  |  | ||||||
|     page_title = |     page_title = | ||||||
|       case live_action do |       case live_action do | ||||||
|         action when action in [:show, :table] -> container_name |         :show -> container_name | ||||||
|         :edit -> gettext("Edit %{name}", name: container_name) |         :edit -> gettext("Edit %{name}", name: container_name) | ||||||
|         :edit_tags -> gettext("Edit %{name} tags", name: container_name) |         :edit_tags -> gettext("Edit %{name} tags", name: container_name) | ||||||
|       end |       end | ||||||
| @@ -113,6 +125,7 @@ defmodule CanneryWeb.ContainerLive.Show do | |||||||
|     |> assign( |     |> assign( | ||||||
|       container: container, |       container: container, | ||||||
|       round_count: Ammo.get_round_count_for_container!(container, current_user), |       round_count: Ammo.get_round_count_for_container!(container, current_user), | ||||||
|  |       ammo_groups_count: Ammo.get_ammo_groups_count_for_container!(container, current_user), | ||||||
|       ammo_groups: ammo_groups, |       ammo_groups: ammo_groups, | ||||||
|       original_counts: original_counts, |       original_counts: original_counts, | ||||||
|       cprs: cprs, |       cprs: cprs, | ||||||
|   | |||||||
| @@ -18,22 +18,15 @@ | |||||||
|     <%= @container.location %> |     <%= @container.location %> | ||||||
|   </span> |   </span> | ||||||
|  |  | ||||||
|   <%= unless @ammo_groups |> Enum.empty?() do %> |  | ||||||
|   <span class="rounded-lg title text-lg"> |   <span class="rounded-lg title text-lg"> | ||||||
|     <%= gettext("Packs:") %> |     <%= gettext("Packs:") %> | ||||||
|       <%= @ammo_groups |> Enum.reject(fn %{count: count} -> count in [0, nil] end) |> Enum.count() %> |     <%= @ammo_groups_count %> | ||||||
|     </span> |  | ||||||
|  |  | ||||||
|     <span :if={@show_used} class="rounded-lg title text-lg"> |  | ||||||
|       <%= gettext("Total packs:") %> |  | ||||||
|       <%= Enum.count(@ammo_groups) %> |  | ||||||
|   </span> |   </span> | ||||||
|  |  | ||||||
|   <span class="rounded-lg title text-lg"> |   <span class="rounded-lg title text-lg"> | ||||||
|     <%= gettext("Rounds:") %> |     <%= gettext("Rounds:") %> | ||||||
|     <%= @round_count %> |     <%= @round_count %> | ||||||
|   </span> |   </span> | ||||||
|   <% end %> |  | ||||||
|  |  | ||||||
|   <div class="flex space-x-4 justify-center items-center text-primary-600"> |   <div class="flex space-x-4 justify-center items-center text-primary-600"> | ||||||
|     <.link |     <.link | ||||||
| @@ -93,11 +86,29 @@ | |||||||
|   <hr class="mb-4 hr" /> |   <hr class="mb-4 hr" /> | ||||||
|  |  | ||||||
|   <div class="flex justify-center items-center space-x-4"> |   <div class="flex justify-center items-center space-x-4"> | ||||||
|     <.toggle_button action="toggle_show_used" value={@show_used}> |     <.form | ||||||
|       <span class="title text-lg text-primary-600"> |       :let={f} | ||||||
|         <%= gettext("Show used") %> |       for={%{}} | ||||||
|       </span> |       as={:ammo_type} | ||||||
|     </.toggle_button> |       phx-change="change_class" | ||||||
|  |       phx-submit="change_class" | ||||||
|  |       class="flex items-center" | ||||||
|  |     > | ||||||
|  |       <%= label(f, :class, gettext("Class"), class: "title text-primary-600 text-lg text-center") %> | ||||||
|  |  | ||||||
|  |       <%= select( | ||||||
|  |         f, | ||||||
|  |         :class, | ||||||
|  |         [ | ||||||
|  |           {gettext("All"), :all}, | ||||||
|  |           {gettext("Rifle"), :rifle}, | ||||||
|  |           {gettext("Shotgun"), :shotgun}, | ||||||
|  |           {gettext("Pistol"), :pistol} | ||||||
|  |         ], | ||||||
|  |         class: "mx-2 my-1 min-w-md input input-primary", | ||||||
|  |         value: @class | ||||||
|  |       ) %> | ||||||
|  |     </.form> | ||||||
|  |  | ||||||
|     <.toggle_button action="toggle_table" value={@view_table}> |     <.toggle_button action="toggle_table" value={@view_table}> | ||||||
|       <span class="title text-lg text-primary-600"> |       <span class="title text-lg text-primary-600"> | ||||||
| @@ -118,6 +129,7 @@ | |||||||
|           id="ammo-type-show-table" |           id="ammo-type-show-table" | ||||||
|           ammo_groups={@ammo_groups} |           ammo_groups={@ammo_groups} | ||||||
|           current_user={@current_user} |           current_user={@current_user} | ||||||
|  |           show_used={false} | ||||||
|         > |         > | ||||||
|           <:ammo_type :let={%{name: ammo_type_name} = ammo_type}> |           <:ammo_type :let={%{name: ammo_type_name} = ammo_type}> | ||||||
|             <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, ammo_type)} class="link"> |             <.link navigate={Routes.ammo_type_show_path(Endpoint, :show, ammo_type)} class="link"> | ||||||
|   | |||||||
| @@ -18,7 +18,10 @@ | |||||||
|       <%= changeset_errors(@changeset) %> |       <%= changeset_errors(@changeset) %> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> |     <%= label(f, :name, gettext("Name"), | ||||||
|  |       class: "title text-lg text-primary-600", | ||||||
|  |       maxlength: 255 | ||||||
|  |     ) %> | ||||||
|     <%= text_input(f, :name, class: "input input-primary col-span-2") %> |     <%= text_input(f, :name, class: "input input-primary col-span-2") %> | ||||||
|     <%= error_tag(f, :name, "col-span-3") %> |     <%= error_tag(f, :name, "col-span-3") %> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,6 +31,7 @@ | |||||||
|     <%= textarea(f, :notes, |     <%= textarea(f, :notes, | ||||||
|       id: "shot-group-form-notes", |       id: "shot-group-form-notes", | ||||||
|       class: "input input-primary col-span-2", |       class: "input input-primary col-span-2", | ||||||
|  |       maxlength: 255, | ||||||
|       placeholder: gettext("Really great weather"), |       placeholder: gettext("Really great weather"), | ||||||
|       phx_hook: "MaintainAttrs", |       phx_hook: "MaintainAttrs", | ||||||
|       phx_update: "ignore" |       phx_update: "ignore" | ||||||
|   | |||||||
| @@ -10,11 +10,11 @@ defmodule CanneryWeb.RangeLive.Index do | |||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
|   def mount(%{"search" => search}, _session, socket) do |   def mount(%{"search" => search}, _session, socket) do | ||||||
|     {:ok, socket |> assign(search: search) |> display_shot_groups()} |     {:ok, socket |> assign(class: :all, search: search) |> display_shot_groups()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def mount(_params, _session, socket) do |   def mount(_params, _session, socket) do | ||||||
|     {:ok, socket |> assign(search: nil) |> display_shot_groups()} |     {:ok, socket |> assign(class: :all, search: nil) |> display_shot_groups()} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   @impl true |   @impl true | ||||||
| @@ -102,9 +102,27 @@ defmodule CanneryWeb.RangeLive.Index do | |||||||
|     {:noreply, socket |> push_patch(to: Routes.range_index_path(Endpoint, :search, search_term))} |     {:noreply, socket |> push_patch(to: Routes.range_index_path(Endpoint, :search, search_term))} | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "rifle"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :rifle) |> display_shot_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "shotgun"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :shotgun) |> display_shot_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => "pistol"}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :pistol) |> display_shot_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def handle_event("change_class", %{"ammo_type" => %{"class" => _all}}, socket) do | ||||||
|  |     {:noreply, socket |> assign(:class, :all) |> display_shot_groups()} | ||||||
|  |   end | ||||||
|  |  | ||||||
|   @spec display_shot_groups(Socket.t()) :: Socket.t() |   @spec display_shot_groups(Socket.t()) :: Socket.t() | ||||||
|   defp display_shot_groups(%{assigns: %{search: search, current_user: current_user}} = socket) do |   defp display_shot_groups( | ||||||
|     shot_groups = ActivityLog.list_shot_groups(search, current_user) |          %{assigns: %{class: class, search: search, current_user: current_user}} = socket | ||||||
|  |        ) do | ||||||
|  |     shot_groups = ActivityLog.list_shot_groups(search, class, current_user) | ||||||
|     ammo_groups = Ammo.list_staged_ammo_groups(current_user) |     ammo_groups = Ammo.list_staged_ammo_groups(current_user) | ||||||
|     chart_data = shot_groups |> get_chart_data_for_shot_group() |     chart_data = shot_groups |> get_chart_data_for_shot_group() | ||||||
|     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) |     original_counts = ammo_groups |> Ammo.get_original_counts(current_user) | ||||||
|   | |||||||
| @@ -74,17 +74,41 @@ | |||||||
|       <%= dgettext("errors", "Your browser does not support the canvas element.") %> |       <%= dgettext("errors", "Your browser does not support the canvas element.") %> | ||||||
|     </canvas> |     </canvas> | ||||||
|  |  | ||||||
|     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl"> |     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-2xl"> | ||||||
|  |       <.form | ||||||
|  |         :let={f} | ||||||
|  |         for={%{}} | ||||||
|  |         as={:ammo_type} | ||||||
|  |         phx-change="change_class" | ||||||
|  |         phx-submit="change_class" | ||||||
|  |         class="flex items-center" | ||||||
|  |       > | ||||||
|  |         <%= label(f, :class, gettext("Class"), class: "title text-primary-600 text-lg text-center") %> | ||||||
|  |  | ||||||
|  |         <%= select( | ||||||
|  |           f, | ||||||
|  |           :class, | ||||||
|  |           [ | ||||||
|  |             {gettext("All"), :all}, | ||||||
|  |             {gettext("Rifle"), :rifle}, | ||||||
|  |             {gettext("Shotgun"), :shotgun}, | ||||||
|  |             {gettext("Pistol"), :pistol} | ||||||
|  |           ], | ||||||
|  |           class: "mx-2 my-1 min-w-md input input-primary", | ||||||
|  |           value: @class | ||||||
|  |         ) %> | ||||||
|  |       </.form> | ||||||
|  |  | ||||||
|       <.form |       <.form | ||||||
|         :let={f} |         :let={f} | ||||||
|         for={%{}} |         for={%{}} | ||||||
|         as={:search} |         as={:search} | ||||||
|         phx-change="search" |         phx-change="search" | ||||||
|         phx-submit="search" |         phx-submit="search" | ||||||
|         class="grow self-stretch flex flex-col items-stretch" |         class="grow flex items-center" | ||||||
|       > |       > | ||||||
|         <%= text_input(f, :search_term, |         <%= text_input(f, :search_term, | ||||||
|           class: "input input-primary", |           class: "grow input input-primary", | ||||||
|           value: @search, |           value: @search, | ||||||
|           role: "search", |           role: "search", | ||||||
|           phx_debounce: 300, |           phx_debounce: 300, | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> |     <%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-600") %> | ||||||
|     <%= text_input(f, :name, class: "input input-primary col-span-2") %> |     <%= text_input(f, :name, class: "input input-primary col-span-2", maxlength: 255) %> | ||||||
|     <%= error_tag(f, :name, "col-span-3") %> |     <%= error_tag(f, :name, "col-span-3") %> | ||||||
|  |  | ||||||
|     <%= label(f, :bg_color, gettext("Background color"), class: "title text-lg text-primary-600") %> |     <%= label(f, :bg_color, gettext("Background color"), class: "title text-lg text-primary-600") %> | ||||||
|   | |||||||
| @@ -18,19 +18,18 @@ | |||||||
|     <.link patch={Routes.tag_index_path(Endpoint, :new)} class="btn btn-primary"> |     <.link patch={Routes.tag_index_path(Endpoint, :new)} class="btn btn-primary"> | ||||||
|       <%= dgettext("actions", "New Tag") %> |       <%= dgettext("actions", "New Tag") %> | ||||||
|     </.link> |     </.link> | ||||||
|   <% end %> |  | ||||||
|  |  | ||||||
|   <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl"> |     <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-2xl"> | ||||||
|       <.form |       <.form | ||||||
|         :let={f} |         :let={f} | ||||||
|         for={%{}} |         for={%{}} | ||||||
|         as={:search} |         as={:search} | ||||||
|         phx-change="search" |         phx-change="search" | ||||||
|         phx-submit="search" |         phx-submit="search" | ||||||
|       class="grow self-stretch flex flex-col items-stretch" |         class="grow flex items-center" | ||||||
|       > |       > | ||||||
|         <%= text_input(f, :search_term, |         <%= text_input(f, :search_term, | ||||||
|         class: "input input-primary", |           class: "grow input input-primary", | ||||||
|           value: @search, |           value: @search, | ||||||
|           role: "search", |           role: "search", | ||||||
|           phx_debounce: 300, |           phx_debounce: 300, | ||||||
| @@ -70,6 +69,7 @@ | |||||||
|         </.tag_card> |         </.tag_card> | ||||||
|       </div> |       </div> | ||||||
|     <% end %> |     <% end %> | ||||||
|  |   <% end %> | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
| <.modal :if={@live_action in [:new, :edit]} return_to={Routes.tag_index_path(Endpoint, :index)}> | <.modal :if={@live_action in [:new, :edit]} return_to={Routes.tag_index_path(Endpoint, :index)}> | ||||||
|   | |||||||
| @@ -77,7 +77,6 @@ defmodule CanneryWeb.Router do | |||||||
|  |  | ||||||
|     live "/type/:id", AmmoTypeLive.Show, :show |     live "/type/:id", AmmoTypeLive.Show, :show | ||||||
|     live "/type/:id/edit", AmmoTypeLive.Show, :edit |     live "/type/:id/edit", AmmoTypeLive.Show, :edit | ||||||
|     live "/type/:id/table", AmmoTypeLive.Show, :table |  | ||||||
|  |  | ||||||
|     live "/containers", ContainerLive.Index, :index |     live "/containers", ContainerLive.Index, :index | ||||||
|     live "/containers/new", ContainerLive.Index, :new |     live "/containers/new", ContainerLive.Index, :new | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								mix.exs
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ defmodule Cannery.MixProject do | |||||||
|   def project do |   def project do | ||||||
|     [ |     [ | ||||||
|       app: :cannery, |       app: :cannery, | ||||||
|       version: "0.8.5", |       version: "0.9.0", | ||||||
|       elixir: "1.14.1", |       elixir: "1.14.1", | ||||||
|       elixirc_paths: elixirc_paths(Mix.env()), |       elixirc_paths: elixirc_paths(Mix.env()), | ||||||
|       compilers: Mix.compilers(), |       compilers: Mix.compilers(), | ||||||
|   | |||||||
| @@ -10,14 +10,14 @@ | |||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -120,12 +120,12 @@ msgstr "" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -136,7 +136,7 @@ msgstr "" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -156,7 +156,7 @@ msgstr "" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -178,7 +178,7 @@ msgstr "" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -203,13 +203,13 @@ msgstr "" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -237,13 +237,13 @@ msgstr "" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -253,20 +253,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -277,30 +277,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -316,44 +316,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -23,14 +23,14 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "Munition hinzufügen" | msgstr "Munition hinzufügen" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "Fügen Sie ihre erste Box hinzu!" | msgstr "Fügen Sie ihre erste Box hinzu!" | ||||||
| @@ -133,12 +133,12 @@ msgstr "Bestätigungsmail erneut senden" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "Passwort zurücksetzen" | msgstr "Passwort zurücksetzen" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -149,7 +149,7 @@ msgstr "Speichern" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "Anleitung zum Passwort zurücksetzen zusenden" | msgstr "Anleitung zum Passwort zurücksetzen zusenden" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "Warum fügen Sie keine hinzu?" | msgstr "Warum fügen Sie keine hinzu?" | ||||||
| @@ -169,7 +169,7 @@ msgstr "Munition markieren" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "Warum nicht einige für den Schießstand auswählen?" | msgstr "Warum nicht einige für den Schießstand auswählen?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -191,7 +191,7 @@ msgstr "Markieren" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "In die Zwischenablage kopieren" | msgstr "In die Zwischenablage kopieren" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "Zuerst einen Behälter hinzufügen" | msgstr "Zuerst einen Behälter hinzufügen" | ||||||
| @@ -216,13 +216,13 @@ msgstr "Sprache wechseln" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -250,13 +250,13 @@ msgstr "" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -266,20 +266,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -290,30 +290,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -329,44 +329,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "Munition markieren" | msgstr "Munition markieren" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -23,7 +23,7 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "Behälter muss vor dem Löschen leer sein" | msgstr "Behälter muss vor dem Löschen leer sein" | ||||||
| @@ -69,6 +69,7 @@ msgstr "Ungültige Mailadresse oder Passwort" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "Nicht gefunden" | msgstr "Nicht gefunden" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -117,22 +118,22 @@ msgstr "Nutzerkonto Bestätigungslink ist ungültig oder abgelaufen." | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "Sie sind nicht berechtigt, diese Seite aufzurufen." | msgstr "Sie sind nicht berechtigt, diese Seite aufzurufen." | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "hat sich nicht geändert" | msgstr "hat sich nicht geändert" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "Passwort stimmt nicht überein" | msgstr "Passwort stimmt nicht überein" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "ist nicht gültig" | msgstr "ist nicht gültig" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "Muss ein @ Zeichen und keine Leerzeichen haben" | msgstr "Muss ein @ Zeichen und keine Leerzeichen haben" | ||||||
| @@ -172,7 +173,7 @@ msgstr "" | |||||||
| "Ungültige Nummer an Kopien. Muss zwischen 1 and %{max} liegen. War " | "Ungültige Nummer an Kopien. Muss zwischen 1 and %{max} liegen. War " | ||||||
| "%{multiplier}" | "%{multiplier}" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -187,27 +188,27 @@ msgstr "" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "Anzahl muss weniger als %{count} betragen" | msgstr "Anzahl muss weniger als %{count} betragen" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "%{name} erfolgreich erstellt" | msgstr "%{name} erfolgreich erstellt" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -65,15 +65,15 @@ msgstr "" | |||||||
| "Sind Sie sicher, dass sie %{email} löschen möchten? Dies kann nicht " | "Sind Sie sicher, dass sie %{email} löschen möchten? Dies kann nicht " | ||||||
| "zurückgenommen werden!" | "zurückgenommen werden!" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "Sind Sie sicher, dass sie %{name} löschen möchten?" | msgstr "Sind Sie sicher, dass sie %{name} löschen möchten?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -128,12 +128,12 @@ msgstr "Passwort erfolgreich geändert." | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "Bitte überprüfen Sie ihre Mailbox und bestätigen Sie das Nutzerkonto" | msgstr "Bitte überprüfen Sie ihre Mailbox und bestätigen Sie das Nutzerkonto" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -177,7 +177,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?" | msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "Sind sie sicher, dass sie die Schießkladde löschen möchten?" | msgstr "Sind sie sicher, dass sie die Schießkladde löschen möchten?" | ||||||
| @@ -213,8 +213,8 @@ msgstr "Der Zwischenablage hinzugefügt" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "%{name} erfolgreich entfernt" | msgstr "%{name} erfolgreich entfernt" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "Sie müssen" | msgstr "Sie müssen" | ||||||
| @@ -234,7 +234,7 @@ msgstr "Möchten Sie die Sprache wechseln?" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "Spracheinstellung gespeichert." | msgstr "Spracheinstellung gespeichert." | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -257,7 +257,7 @@ msgid_plural "Ammo added successfully" | |||||||
| msgstr[0] "Munitionsgruppe erfolgreich aktualisiert" | msgstr[0] "Munitionsgruppe erfolgreich aktualisiert" | ||||||
| msgstr[1] "Munitionsgruppe erfolgreich aktualisiert" | msgstr[1] "Munitionsgruppe erfolgreich aktualisiert" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,14 +10,14 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Language: en\n" | "Language: en\n" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -120,12 +120,12 @@ msgstr "" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -136,7 +136,7 @@ msgstr "" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -156,7 +156,7 @@ msgstr "" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -178,7 +178,7 @@ msgstr "" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -203,13 +203,13 @@ msgstr "" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -237,13 +237,13 @@ msgstr "" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -253,20 +253,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -277,30 +277,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -316,44 +316,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,7 +10,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Language: en\n" | "Language: en\n" | ||||||
|  |  | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -56,6 +56,7 @@ msgstr "" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -103,23 +104,23 @@ msgstr "" | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| ## From Ecto.Changeset.put_change/3 | ## From Ecto.Changeset.put_change/3 | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -155,7 +156,7 @@ msgstr "" | |||||||
| msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -170,27 +171,27 @@ msgstr "" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -50,15 +50,15 @@ msgstr "" | |||||||
| msgid "Are you sure you want to delete %{email}? This action is permanent!" | msgid "Are you sure you want to delete %{email}? This action is permanent!" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -109,12 +109,12 @@ msgstr "" | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -156,7 +156,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -192,8 +192,8 @@ msgstr "" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -213,7 +213,7 @@ msgstr "" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -236,7 +236,7 @@ msgid_plural "Ammo added successfully" | |||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -56,6 +56,7 @@ msgstr "" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -103,22 +104,22 @@ msgstr "" | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -154,7 +155,7 @@ msgstr "" | |||||||
| msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -169,27 +170,27 @@ msgstr "" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -23,14 +23,14 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "Añadir Munición" | msgstr "Añadir Munición" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "¡Añade tu primera caja!" | msgstr "¡Añade tu primera caja!" | ||||||
| @@ -133,12 +133,12 @@ msgstr "Reenviar instrucciones de confirmación" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "Resetear contraseña" | msgstr "Resetear contraseña" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -149,7 +149,7 @@ msgstr "Guardar" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "Enviar instrucciones para reestablecer contraseña" | msgstr "Enviar instrucciones para reestablecer contraseña" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "¿Por qué no añadir una?" | msgstr "¿Por qué no añadir una?" | ||||||
| @@ -169,7 +169,7 @@ msgstr "Preparar munición" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "¿Por qué no preparar parte para disparar?" | msgstr "¿Por qué no preparar parte para disparar?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -191,7 +191,7 @@ msgstr "Seleccionar" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "Copiar al portapapeles" | msgstr "Copiar al portapapeles" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "añade primero un contenedor" | msgstr "añade primero un contenedor" | ||||||
| @@ -216,13 +216,13 @@ msgstr "Cambiar lenguaje" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "Ver en Catalogo" | msgstr "Ver en Catalogo" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "añade primero un tipo de munición" | msgstr "añade primero un tipo de munición" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -250,13 +250,13 @@ msgstr "Desmontar del campo de tiro" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "Exportar datos como JSON" | msgstr "Exportar datos como JSON" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -266,20 +266,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -290,30 +290,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -329,44 +329,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "Preparar munición" | msgstr "Preparar munición" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -23,7 +23,7 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "El contenedor debe estar vacío antes de ser borrado" | msgstr "El contenedor debe estar vacío antes de ser borrado" | ||||||
| @@ -69,6 +69,7 @@ msgstr "Correo o contraseña incorrecta" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "No se encontró" | msgstr "No se encontró" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -119,22 +120,22 @@ msgstr "El enlace de confirmación de usuario no es válido o ha caducado." | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "No está autorizado a ver esta página." | msgstr "No está autorizado a ver esta página." | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "no cambió" | msgstr "no cambió" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "no coincide con la contraseña" | msgstr "no coincide con la contraseña" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "no es válido" | msgstr "no es válido" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "debe tener el signo @ y no contener espacios" | msgstr "debe tener el signo @ y no contener espacios" | ||||||
| @@ -170,7 +171,7 @@ msgstr "No se ha podido procesar el número de copias" | |||||||
| msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | ||||||
| msgstr "Número inválido de copias, debe ser entre 1 y %{max}. Fue %{multiplier" | msgstr "Número inválido de copias, debe ser entre 1 y %{max}. Fue %{multiplier" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "Multiplicador inválido" | msgstr "Multiplicador inválido" | ||||||
| @@ -185,27 +186,27 @@ msgstr "Por favor escoja un tipo de munición y un contenedor" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "Su navegador no es compatible con el elemento lienzo." | msgstr "Su navegador no es compatible con el elemento lienzo." | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "Por favor escoja un usuario y tipo de munición valido" | msgstr "Por favor escoja un usuario y tipo de munición valido" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "El recuento debe ser menos de %{count}" | msgstr "El recuento debe ser menos de %{count}" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "%{name} creado exitosamente" | msgstr "%{name} creado exitosamente" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -65,15 +65,15 @@ msgstr "" | |||||||
| msgid "Are you sure you want to delete %{email}? This action is permanent!" | msgid "Are you sure you want to delete %{email}? This action is permanent!" | ||||||
| msgstr "Está seguro que desea eliminar %{email}? Esta acción es permanente!" | msgstr "Está seguro que desea eliminar %{email}? Esta acción es permanente!" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "Está seguro que desea eliminar %{name}?" | msgstr "Está seguro que desea eliminar %{name}?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -128,12 +128,12 @@ msgstr "Contraseña cambiada exitosamente." | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "Por favor chequea el correo para verificar tu cuenta" | msgstr "Por favor chequea el correo para verificar tu cuenta" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -176,7 +176,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "Está seguro que desea desmontar esta munición?" | msgstr "Está seguro que desea desmontar esta munición?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "¿Está segure que quiere borrar este récord de disparos?" | msgstr "¿Está segure que quiere borrar este récord de disparos?" | ||||||
| @@ -212,8 +212,8 @@ msgstr "Copiado al portapapeles" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "%{name} eliminado exitosamente" | msgstr "%{name} eliminado exitosamente" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "Necesitará hacerlo" | msgstr "Necesitará hacerlo" | ||||||
| @@ -233,7 +233,7 @@ msgstr "¿Está segure de que quiere cambiar el idioma?" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "Idioma cambiado exitosamente." | msgstr "Idioma cambiado exitosamente." | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -256,7 +256,7 @@ msgid_plural "Ammo added successfully" | |||||||
| msgstr[0] "Munición añadida exitosamente" | msgstr[0] "Munición añadida exitosamente" | ||||||
| msgstr[1] "Municiones añadidas exitosamente" | msgstr[1] "Municiones añadidas exitosamente" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
| @@ -23,14 +23,14 @@ msgstr "" | |||||||
| # # Run "mix gettext.extract" to bring this file up to | # # Run "mix gettext.extract" to bring this file up to | ||||||
| # # date. Leave "msgstr"s empty as changing them here has no | # # date. Leave "msgstr"s empty as changing them here has no | ||||||
| # # effect: edit them in PO (.po) files instead. | # # effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "ajouter munition" | msgstr "ajouter munition" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "Ajoutez votre première caisse !" | msgstr "Ajoutez votre première caisse !" | ||||||
| @@ -133,12 +133,12 @@ msgstr "Renvoyer les instructions de confirmation" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "Réinitialisé le mot de passe" | msgstr "Réinitialisé le mot de passe" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -149,7 +149,7 @@ msgstr "Sauvegarder" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "Envoyer les instructions pour réinitialiser le mot de passe" | msgstr "Envoyer les instructions pour réinitialiser le mot de passe" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "Pourquoi pas en ajouter un ?" | msgstr "Pourquoi pas en ajouter un ?" | ||||||
| @@ -169,7 +169,7 @@ msgstr "Munition préparée" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "Pourquoi pas en préparer pour tirer ?" | msgstr "Pourquoi pas en préparer pour tirer ?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -191,7 +191,7 @@ msgstr "Sélectionner" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "Copier dans le presse-papier" | msgstr "Copier dans le presse-papier" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "ajouter un conteneur en premier" | msgstr "ajouter un conteneur en premier" | ||||||
| @@ -216,13 +216,13 @@ msgstr "Changer la langue" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "Voir en catalogue" | msgstr "Voir en catalogue" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "Ajoutez d'abord un type de munitions" | msgstr "Ajoutez d'abord un type de munitions" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -250,13 +250,13 @@ msgstr "" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -266,20 +266,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -290,30 +290,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -329,44 +329,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "Munition préparée" | msgstr "Munition préparée" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -23,7 +23,7 @@ msgstr "" | |||||||
| # # Run "mix gettext.extract" to bring this file up to | # # Run "mix gettext.extract" to bring this file up to | ||||||
| # # date. Leave "msgstr"s empty as changing them here has no | # # date. Leave "msgstr"s empty as changing them here has no | ||||||
| # # effect: edit them in PO (.po) files instead. | # # effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "Le conteneur doit être vide pour être supprimé" | msgstr "Le conteneur doit être vide pour être supprimé" | ||||||
| @@ -69,6 +69,7 @@ msgstr "Mél ou mot de passe invalide" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "Pas trouvé" | msgstr "Pas trouvé" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -118,22 +119,22 @@ msgstr "Le lien de confirmation d’utilisateur·ice est invalide ou a expiré." | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "Vous n’êtes pas autorisé·e à voir cette page." | msgstr "Vous n’êtes pas autorisé·e à voir cette page." | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "est inchangé" | msgstr "est inchangé" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "le mot de passe ne correspond pas" | msgstr "le mot de passe ne correspond pas" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "n’est pas valide" | msgstr "n’est pas valide" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "doit contenir le symbole @ et aucune espace" | msgstr "doit contenir le symbole @ et aucune espace" | ||||||
| @@ -171,7 +172,7 @@ msgstr "Impossible d'analyser le nombre de copies" | |||||||
| msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | 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}" | msgstr "Nombre de copies invalide, doit être 1 et %{max}. Été %{multiplier}" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "Multiplicateur invalide" | msgstr "Multiplicateur invalide" | ||||||
| @@ -186,27 +187,27 @@ msgstr "Veuillez choisir un type de munitions et un conteneur" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "Veuillez choisir un utilisateur valide et un groupe de munitions" | msgstr "Veuillez choisir un utilisateur valide et un groupe de munitions" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "La quantité doit être inférieur à %{count}" | msgstr "La quantité doit être inférieur à %{count}" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "%{name} créé· avec succès" | msgstr "%{name} créé· avec succès" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -66,15 +66,15 @@ msgid "Are you sure you want to delete %{email}? This action is permanent!" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Êtes-vous certain·e de supprimer %{email} ? Cette action est définitive !" | "Êtes-vous certain·e de supprimer %{email} ? Cette action est définitive !" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "Êtes-vous certain·e de supprimer %{name} ?" | msgstr "Êtes-vous certain·e de supprimer %{name} ?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -129,12 +129,12 @@ msgstr "Mot de passe mis à jour avec succès." | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "Veuillez vérifier votre mél pour confirmer votre compte" | msgstr "Veuillez vérifier votre mél pour confirmer votre compte" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -178,7 +178,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?" | msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "Êtes-vous certain·e de vouloir supprimer cet enregistrement de tir ?" | msgstr "Êtes-vous certain·e de vouloir supprimer cet enregistrement de tir ?" | ||||||
| @@ -214,8 +214,8 @@ msgstr "Copié dans le presse-papier" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "%{name} retiré avec succès" | msgstr "%{name} retiré avec succès" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "Vous aurez besoin de" | msgstr "Vous aurez besoin de" | ||||||
| @@ -235,7 +235,7 @@ msgstr "Êtes-vous certain·e de vouloir changer votre langue ?" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "Langue mise à jour avec succès." | msgstr "Langue mise à jour avec succès." | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -258,7 +258,7 @@ msgid_plural "Ammo added successfully" | |||||||
| msgstr[0] "Groupe de munition mis à jour avec succès" | msgstr[0] "Groupe de munition mis à jour avec succès" | ||||||
| msgstr[1] "Groupe de munition mis à jour avec succès" | msgstr[1] "Groupe de munition mis à jour avec succès" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
| @@ -21,14 +21,14 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:54 | #: lib/cannery_web/live/ammo_group_live/index.ex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:62 | #: lib/cannery_web/live/ammo_group_live/index.ex:67 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:41 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:38 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add Ammo" | msgid "Add Ammo" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:37 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:34 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Add your first box!" | msgid "Add your first box!" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -131,12 +131,12 @@ msgstr "" | |||||||
| msgid "Reset password" | msgid "Reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:56 | #: lib/cannery_web/components/add_shot_group_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:84 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:159 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:350 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:55 | #: lib/cannery_web/live/container_live/form_component.html.heex:57 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:32 | #: lib/cannery_web/live/invite_live/form_component.html.heex:35 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:44 | #: lib/cannery_web/live/range_live/form_component.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | #: lib/cannery_web/live/tag_live/form_component.html.heex:37 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Save" | msgid "Save" | ||||||
| @@ -147,7 +147,7 @@ msgstr "" | |||||||
| msgid "Send instructions to reset password" | msgid "Send instructions to reset password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:75 | #: lib/cannery_web/live/container_live/show.html.heex:68 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Why not add one?" | msgid "Why not add one?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -167,7 +167,7 @@ msgstr "" | |||||||
| msgid "Why not get some ready to shoot?" | msgid "Why not get some ready to shoot?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:127 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:103 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:45 | #: lib/cannery_web/live/range_live/index.html.heex:45 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| @@ -189,7 +189,7 @@ msgstr "" | |||||||
| msgid "Copy to clipboard" | msgid "Copy to clipboard" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:22 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:14 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add a container first" | msgid "add a container first" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -214,13 +214,13 @@ msgstr "" | |||||||
| msgid "View in Catalog" | msgid "View in Catalog" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:32 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:24 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "add an ammo type first" | msgid "add an ammo type first" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/move_ammo_group_component.ex:80 | #: lib/cannery_web/components/move_ammo_group_component.ex:80 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:121 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:144 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:96 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Move ammo" | msgid "Move ammo" | ||||||
| @@ -248,13 +248,13 @@ msgstr "" | |||||||
| msgid "Export Data as JSON" | msgid "Export Data as JSON" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:85 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:110 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{ammo_type_name}" | msgid "Clone %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:88 | #: lib/cannery_web/live/container_live/index.html.heex:87 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:144 | #: lib/cannery_web/live/container_live/index.html.heex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Clone %{container_name}" | msgid "Clone %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -264,20 +264,20 @@ msgstr "" | |||||||
| msgid "Copy invite link for %{invite_name}" | msgid "Copy invite link for %{invite_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:104 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:129 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:36 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{ammo_type_name}" | msgid "Delete %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:103 | #: lib/cannery_web/live/container_live/index.html.heex:104 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:159 | #: lib/cannery_web/live/container_live/index.html.heex:162 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:55 | #: lib/cannery_web/live/container_live/show.html.heex:48 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{container_name}" | msgid "Delete %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:66 | #: lib/cannery_web/live/tag_live/index.html.heex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete %{tag_name}" | msgid "Delete %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -288,30 +288,30 @@ msgid "Delete invite for %{invite_name}" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:161 | #: lib/cannery_web/live/ammo_group_live/show.ex:161 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:131 | #: lib/cannery_web/live/range_live/index.html.heex:155 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Delete shot record of %{shot_group_count} shots" | msgid "Delete shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:75 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:100 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:19 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{ammo_type_name}" | msgid "Edit %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:78 | #: lib/cannery_web/live/container_live/index.html.heex:77 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:134 | #: lib/cannery_web/live/container_live/index.html.heex:135 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:42 | #: lib/cannery_web/live/container_live/show.html.heex:35 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{container_name}" | msgid "Edit %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:53 | #: lib/cannery_web/live/tag_live/index.html.heex:52 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit %{tag_name}" | msgid "Edit %{tag_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:143 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:166 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:62 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit ammo group of %{ammo_group_count} bullets" | msgid "Edit ammo group of %{ammo_group_count} bullets" | ||||||
| @@ -327,44 +327,45 @@ msgstr "" | |||||||
| msgid "Edit shot group of %{shot_group_count} shots" | msgid "Edit shot group of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:114 | #: lib/cannery_web/live/range_live/index.html.heex:138 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Edit shot record of %{shot_group_count} shots" | msgid "Edit shot record of %{shot_group_count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:120 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Stage" | msgid "Stage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:66 | #: lib/cannery_web/live/container_live/index.html.heex:65 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:123 | #: lib/cannery_web/live/container_live/index.html.heex:124 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Tag %{container_name}" | msgid "Tag %{container_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:96 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:119 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Unstage" | msgid "Unstage" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:65 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:90 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "View %{ammo_type_name}" | msgid "View %{ammo_type_name}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:155 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:178 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Clone ammo group of %{ammo_group_count} bullets" | msgid "Clone ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:170 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:193 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:76 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Delete ammo group of %{ammo_group_count} bullets" | msgid "Delete ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:131 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:154 | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/show.html.heex:206 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "View ammo group of %{ammo_group_count} bullets" | msgid "View ammo group of %{ammo_group_count} bullets" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -24,7 +24,7 @@ msgstr "" | |||||||
| ## Run "mix gettext.extract" to bring this file up to | ## Run "mix gettext.extract" to bring this file up to | ||||||
| ## date. Leave "msgstr"s empty as changing them here has no | ## date. Leave "msgstr"s empty as changing them here has no | ||||||
| ## effect: edit them in PO (.po) files instead. | ## effect: edit them in PO (.po) files instead. | ||||||
| #: lib/cannery/containers.ex:200 | #: lib/cannery/containers.ex:220 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Container must be empty before deleting" | msgid "Container must be empty before deleting" | ||||||
| msgstr "Caithfidh an coimeádán a bheidh follamh roimh scriosadh" | msgstr "Caithfidh an coimeádán a bheidh follamh roimh scriosadh" | ||||||
| @@ -70,6 +70,7 @@ msgstr "Seoladh email nó pasfhocal neamhbhailí" | |||||||
| msgid "Not found" | msgid "Not found" | ||||||
| msgstr "Ní feidir é a fáil" | msgstr "Ní feidir é a fáil" | ||||||
|  |  | ||||||
|  | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:18 | ||||||
| #: lib/cannery_web/templates/user_registration/new.html.heex:13 | #: lib/cannery_web/templates/user_registration/new.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | #: lib/cannery_web/templates/user_reset_password/edit.html.heex:13 | ||||||
| #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | #: lib/cannery_web/templates/user_settings/edit.html.heex:22 | ||||||
| @@ -119,22 +120,22 @@ msgstr "Tá nasc an úsáideoir a deimhnigh neamhbailí nó as dáta." | |||||||
| msgid "You are not authorized to view this page." | msgid "You are not authorized to view this page." | ||||||
| msgstr "Níl cead agaibh féachaint ar an leathanach seo." | msgstr "Níl cead agaibh féachaint ar an leathanach seo." | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:144 | #: lib/cannery/accounts/user.ex:145 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "did not change" | msgid "did not change" | ||||||
| msgstr "Níor athraigh sé" | msgstr "Níor athraigh sé" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:165 | #: lib/cannery/accounts/user.ex:166 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "does not match password" | msgid "does not match password" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:202 | #: lib/cannery/accounts/user.ex:203 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "is not valid" | msgid "is not valid" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/accounts/user.ex:99 | #: lib/cannery/accounts/user.ex:100 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "must have the @ sign and no spaces" | msgid "must have the @ sign and no spaces" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -170,7 +171,7 @@ msgstr "" | |||||||
| msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/ammo.ex:1015 | #: lib/cannery/ammo.ex:1123 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Invalid multiplier" | msgid "Invalid multiplier" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -185,27 +186,27 @@ msgstr "" | |||||||
| msgid "Your browser does not support the canvas element." | msgid "Your browser does not support the canvas element." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:72 | #: lib/cannery/activity_log/shot_group.ex:74 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Please select a valid user and ammo pack" | msgid "Please select a valid user and ammo pack" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:86 | #: lib/cannery/activity_log/shot_group.ex:88 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left can be at most %{count} rounds" | msgid "Ammo left can be at most %{count} rounds" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:82 | #: lib/cannery/activity_log/shot_group.ex:84 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo left must be at least 0" | msgid "Ammo left must be at least 0" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:119 | #: lib/cannery/activity_log/shot_group.ex:122 | ||||||
| #, elixir-autogen, elixir-format, fuzzy | #, elixir-autogen, elixir-format, fuzzy | ||||||
| msgid "Count can be at most %{count} shots" | msgid "Count can be at most %{count} shots" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery/activity_log/shot_group.ex:78 | #: lib/cannery/activity_log/shot_group.ex:80 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "can't be blank" | msgid "can't be blank" | ||||||
| msgstr "" | msgstr "" | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -61,15 +61,15 @@ msgstr "" | |||||||
| msgid "Are you sure you want to delete %{email}? This action is permanent!" | msgid "Are you sure you want to delete %{email}? This action is permanent!" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -120,12 +120,12 @@ msgstr "" | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -167,7 +167,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -203,8 +203,8 @@ msgstr "" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -224,7 +224,7 @@ msgstr "" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -250,7 +250,7 @@ msgstr[2] "" | |||||||
| msgstr[3] "" | msgstr[3] "" | ||||||
| msgstr[4] "" | msgstr[4] "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ msgid "%{name} created successfully" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.ex:72 | #: lib/cannery_web/live/ammo_type_live/index.ex:72 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.ex:54 | #: lib/cannery_web/live/ammo_type_live/show.ex:27 | ||||||
| #: lib/cannery_web/live/tag_live/index.ex:65 | #: lib/cannery_web/live/tag_live/index.ex:65 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "%{name} deleted succesfully" | msgid "%{name} deleted succesfully" | ||||||
| @@ -50,15 +50,15 @@ msgstr "" | |||||||
| msgid "Are you sure you want to delete %{email}? This action is permanent!" | msgid "Are you sure you want to delete %{email}? This action is permanent!" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:100 | #: lib/cannery_web/live/container_live/index.html.heex:99 | ||||||
| #: lib/cannery_web/live/container_live/index.html.heex:156 | #: lib/cannery_web/live/container_live/index.html.heex:157 | ||||||
| #: lib/cannery_web/live/container_live/show.html.heex:52 | #: lib/cannery_web/live/container_live/show.html.heex:45 | ||||||
| #: lib/cannery_web/live/tag_live/index.html.heex:64 | #: lib/cannery_web/live/tag_live/index.html.heex:63 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}?" | msgid "Are you sure you want to delete %{name}?" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:168 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:191 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | #: lib/cannery_web/live/ammo_group_live/show.html.heex:74 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this ammo?" | msgid "Are you sure you want to delete this ammo?" | ||||||
| @@ -109,12 +109,12 @@ msgstr "" | |||||||
| msgid "Please check your email to verify your account" | msgid "Please check your email to verify your account" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/components/add_shot_group_component.html.heex:58 | #: lib/cannery_web/components/add_shot_group_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | #: lib/cannery_web/live/ammo_group_live/form_component.html.heex:85 | ||||||
| #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:160 | #: lib/cannery_web/live/ammo_type_live/form_component.html.heex:351 | ||||||
| #: lib/cannery_web/live/container_live/form_component.html.heex:57 | #: lib/cannery_web/live/container_live/form_component.html.heex:59 | ||||||
| #: lib/cannery_web/live/invite_live/form_component.html.heex:34 | #: lib/cannery_web/live/invite_live/form_component.html.heex:37 | ||||||
| #: lib/cannery_web/live/range_live/form_component.html.heex:46 | #: lib/cannery_web/live/range_live/form_component.html.heex:47 | ||||||
| #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | #: lib/cannery_web/live/tag_live/form_component.html.heex:39 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Saving..." | msgid "Saving..." | ||||||
| @@ -156,7 +156,7 @@ msgid "Are you sure you want to unstage this ammo?" | |||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:159 | #: lib/cannery_web/live/ammo_group_live/show.ex:159 | ||||||
| #: lib/cannery_web/live/range_live/index.html.heex:128 | #: lib/cannery_web/live/range_live/index.html.heex:152 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete this shot record?" | msgid "Are you sure you want to delete this shot record?" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -192,8 +192,8 @@ msgstr "" | |||||||
| msgid "%{name} removed successfully" | msgid "%{name} removed successfully" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:18 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:10 | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.html.heex:28 | #: lib/cannery_web/live/ammo_group_live/index.html.heex:20 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "You'll need to" | msgid "You'll need to" | ||||||
| msgstr "" | msgstr "" | ||||||
| @@ -213,7 +213,7 @@ msgstr "" | |||||||
| msgid "Language updated successfully." | msgid "Language updated successfully." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_group_live/index.ex:89 | #: lib/cannery_web/live/ammo_group_live/index.ex:94 | ||||||
| #: lib/cannery_web/live/ammo_group_live/show.ex:55 | #: lib/cannery_web/live/ammo_group_live/show.ex:55 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Ammo deleted succesfully" | msgid "Ammo deleted succesfully" | ||||||
| @@ -236,7 +236,7 @@ msgid_plural "Ammo added successfully" | |||||||
| msgstr[0] "" | msgstr[0] "" | ||||||
| msgstr[1] "" | msgstr[1] "" | ||||||
|  |  | ||||||
| #: lib/cannery_web/live/ammo_type_live/index.html.heex:97 | #: lib/cannery_web/live/ammo_type_live/index.html.heex:122 | ||||||
| #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | #: lib/cannery_web/live/ammo_type_live/show.html.heex:29 | ||||||
| #, elixir-autogen, elixir-format | #, elixir-autogen, elixir-format | ||||||
| msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | msgid "Are you sure you want to delete %{name}? This will delete all %{name} type ammo as well!" | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ defmodule Cannery.Repo.Migrations.AddLocaleSetting do | |||||||
|   use Ecto.Migration |   use Ecto.Migration | ||||||
|  |  | ||||||
|   def change do |   def change do | ||||||
|     alter table("users") do |     alter table(:users) do | ||||||
|       add :locale, :string |       add :locale, :string | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -0,0 +1,98 @@ | |||||||
|  | defmodule Cannery.Repo.Migrations.AddAmmoTypeTypesAndShotgunFields do | ||||||
|  |   use Ecto.Migration | ||||||
|  |  | ||||||
|  |   def change do | ||||||
|  |     alter table(:ammo_types) do | ||||||
|  |       # rifle/shotgun/pistol | ||||||
|  |       add :type, :string, default: "rifle" | ||||||
|  |  | ||||||
|  |       add :wadding, :string | ||||||
|  |       # target/bird/buck/slug/special | ||||||
|  |       add :shot_type, :string | ||||||
|  |       add :shot_material, :string | ||||||
|  |       add :shot_size, :string | ||||||
|  |       add :unfired_length, :string | ||||||
|  |       add :brass_height, :string | ||||||
|  |       add :chamber_size, :string | ||||||
|  |       add :load_grains, :integer | ||||||
|  |       add :shot_charge_weight, :string | ||||||
|  |       add :dram_equivalent, :string | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     create index(:ammo_types, [:type]) | ||||||
|  |  | ||||||
|  |     execute(&add_fields_to_search/0, &remove_fields_from_search/0) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   defp add_fields_to_search() do | ||||||
|  |     execute """ | ||||||
|  |     ALTER TABLE ammo_types | ||||||
|  |       ALTER COLUMN search tsvector | ||||||
|  |       GENERATED ALWAYS AS ( | ||||||
|  |         setweight(to_tsvector('english', coalesce("name", '')), 'A') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("desc", '')), 'B') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("type", '')), 'B') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("manufacturer", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("upc", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("bullet_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("bullet_core", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("cartridge", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("caliber", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("case_material", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("jacket_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("muzzle_velocity", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("powder_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("powder_grains_per_charge", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("grains", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("pressure", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("primer_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("firing_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("wadding", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("shot_type", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("shot_material", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("shot_size", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("unfired_length", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("brass_height", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("chamber_size", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("load_grains", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("shot_charge_weight,", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("dram_equivalent", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("tracer", 'tracer', '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("incendiary", 'incendiary', '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("blank", 'blank', '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("corrosive", 'corrosive', '')), 'D') | ||||||
|  |         setwe | ||||||
|  |       ) STORED | ||||||
|  |     """ | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   defp remove_fields_from_search() do | ||||||
|  |     execute """ | ||||||
|  |     ALTER TABLE ammo_types | ||||||
|  |       ALTER COLUMN search tsvector | ||||||
|  |       GENERATED ALWAYS AS ( | ||||||
|  |         setweight(to_tsvector('english', coalesce("name", '')), 'A') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("desc", '')), 'B') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("bullet_type", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("bullet_core", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("cartridge", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("caliber", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("case_material", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("jacket_type", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("muzzle_velocity", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("powder_type", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("powder_grains_per_charge", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', immutable_to_string("grains", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("pressure", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("primer_type", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("firing_type", '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("tracer", 'tracer', '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("incendiary", 'incendiary', '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("blank", 'blank', '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', boolean_to_string("corrosive", 'corrosive', '')), 'C') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("manufacturer", '')), 'D') || | ||||||
|  |         setweight(to_tsvector('english', coalesce("upc", '')), 'D') | ||||||
|  |       ) STORED | ||||||
|  |     """ | ||||||
|  |   end | ||||||
|  | end | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | defmodule Cannery.Repo.Migrations.RenameTypeToClass do | ||||||
|  |   use Ecto.Migration | ||||||
|  |  | ||||||
|  |   def change do | ||||||
|  |     rename table(:ammo_types), :type, to: :class | ||||||
|  |   end | ||||||
|  | end | ||||||
| @@ -11,11 +11,11 @@ defmodule Cannery.InvitesTest do | |||||||
|   @moduletag :invites_test |   @moduletag :invites_test | ||||||
|  |  | ||||||
|   @valid_attrs %{ |   @valid_attrs %{ | ||||||
|     "name" => "some name" |     name: "some name" | ||||||
|   } |   } | ||||||
|   @invalid_attrs %{ |   @invalid_attrs %{ | ||||||
|     "name" => nil, |     name: nil, | ||||||
|     "token" => nil |     token: nil | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   describe "invites" do |   describe "invites" do | ||||||
| @@ -57,7 +57,7 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|       assert {:ok, _user} = |       assert {:ok, _user} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  token |                  token | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -65,7 +65,7 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|       assert {:ok, _user} = |       assert {:ok, _user} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  token |                  token | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -81,13 +81,13 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|       assert {:ok, _user} = |       assert {:ok, _user} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  token |                  token | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
|       assert {:ok, _user} = |       assert {:ok, _user} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  another_token |                  another_token | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -97,7 +97,7 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|       assert {:ok, _user} = |       assert {:ok, _user} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  token |                  token | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -138,21 +138,14 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|     test "create_invite/1 with valid data creates an unlimited invite", |     test "create_invite/1 with valid data creates an unlimited invite", | ||||||
|          %{current_user: current_user} do |          %{current_user: current_user} do | ||||||
|       assert {:ok, %Invite{} = invite} = |       assert {:ok, %Invite{} = invite} = Invites.create_invite(current_user, %{name: "some name"}) | ||||||
|                Invites.create_invite(current_user, %{ |  | ||||||
|                  "name" => "some name" |  | ||||||
|                }) |  | ||||||
|  |  | ||||||
|       assert invite.name == "some name" |       assert invite.name == "some name" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_invite/1 with valid data creates a limited invite", |     test "create_invite/1 with valid data creates a limited invite", | ||||||
|          %{current_user: current_user} do |          %{current_user: current_user} do | ||||||
|       assert {:ok, %Invite{} = invite} = |       assert {:ok, %Invite{} = invite} = | ||||||
|                Invites.create_invite(current_user, %{ |                Invites.create_invite(current_user, %{name: "some name", uses_left: 10}) | ||||||
|                  "name" => "some name", |  | ||||||
|                  "uses_left" => 10 |  | ||||||
|                }) |  | ||||||
|  |  | ||||||
|       assert invite.name == "some name" |       assert invite.name == "some name" | ||||||
|       assert invite.uses_left == 10 |       assert invite.uses_left == 10 | ||||||
| @@ -168,7 +161,7 @@ defmodule Cannery.InvitesTest do | |||||||
|       assert {:ok, %Invite{} = new_invite} = |       assert {:ok, %Invite{} = new_invite} = | ||||||
|                Invites.update_invite( |                Invites.update_invite( | ||||||
|                  invite, |                  invite, | ||||||
|                  %{"name" => "some updated name", "uses_left" => 5}, |                  %{name: "some updated name", uses_left: 5}, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -178,12 +171,12 @@ defmodule Cannery.InvitesTest do | |||||||
|  |  | ||||||
|     test "update_invite/2 can set an invite to be unlimited", |     test "update_invite/2 can set an invite to be unlimited", | ||||||
|          %{invite: invite, current_user: current_user} do |          %{invite: invite, current_user: current_user} do | ||||||
|       {:ok, invite} = Invites.update_invite(invite, %{"uses_left" => 5}, current_user) |       {:ok, invite} = Invites.update_invite(invite, %{uses_left: 5}, current_user) | ||||||
|  |  | ||||||
|       assert {:ok, %Invite{} = new_invite} = |       assert {:ok, %Invite{} = new_invite} = | ||||||
|                Invites.update_invite( |                Invites.update_invite( | ||||||
|                  invite, |                  invite, | ||||||
|                  %{"name" => "some updated name", "uses_left" => nil}, |                  %{name: "some updated name", uses_left: nil}, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -63,8 +63,7 @@ defmodule Cannery.AccountsTest do | |||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "validates email and password when given" do |     test "validates email and password when given" do | ||||||
|       {:error, changeset} = |       {:error, changeset} = Accounts.register_user(%{email: "not valid", password: "not valid"}) | ||||||
|         Accounts.register_user(%{"email" => "not valid", "password" => "not valid"}) |  | ||||||
|  |  | ||||||
|       assert %{ |       assert %{ | ||||||
|                email: ["must have the @ sign and no spaces"], |                email: ["must have the @ sign and no spaces"], | ||||||
| @@ -74,26 +73,25 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|     test "validates maximum values for email and password for security" do |     test "validates maximum values for email and password for security" do | ||||||
|       too_long = String.duplicate("db", 100) |       too_long = String.duplicate("db", 100) | ||||||
|       {:error, changeset} = Accounts.register_user(%{"email" => too_long, "password" => too_long}) |       {:error, changeset} = Accounts.register_user(%{email: too_long, password: too_long}) | ||||||
|       assert "should be at most 160 character(s)" in errors_on(changeset).email |       assert "should be at most 160 character(s)" in errors_on(changeset).email | ||||||
|       assert "should be at most 80 character(s)" in errors_on(changeset).password |       assert "should be at most 80 character(s)" in errors_on(changeset).password | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "validates email uniqueness" do |     test "validates email uniqueness" do | ||||||
|       %{email: email} = user_fixture() |       %{email: email} = user_fixture() | ||||||
|       {:error, changeset} = Accounts.register_user(%{"email" => email}) |       {:error, changeset} = Accounts.register_user(%{email: email}) | ||||||
|       assert "has already been taken" in errors_on(changeset).email |       assert "has already been taken" in errors_on(changeset).email | ||||||
|  |  | ||||||
|       # Now try with the upper cased email too, to check that email case is ignored. |       # Now try with the upper cased email too, to check that email case is ignored. | ||||||
|       {:error, changeset} = Accounts.register_user(%{"email" => String.upcase(email)}) |       {:error, changeset} = Accounts.register_user(%{email: String.upcase(email)}) | ||||||
|       assert "has already been taken" in errors_on(changeset).email |       assert "has already been taken" in errors_on(changeset).email | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "registers users with a hashed password" do |     test "registers users with a hashed password" do | ||||||
|       email = unique_user_email() |       email = unique_user_email() | ||||||
|  |  | ||||||
|       {:ok, user} = |       {:ok, user} = Accounts.register_user(%{email: email, password: valid_user_password()}) | ||||||
|         Accounts.register_user(%{"email" => email, "password" => valid_user_password()}) |  | ||||||
|  |  | ||||||
|       assert user.email == email |       assert user.email == email | ||||||
|       assert is_binary(user.hashed_password) |       assert is_binary(user.hashed_password) | ||||||
| @@ -103,11 +101,11 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|     test "records used invite during registration" do |     test "records used invite during registration" do | ||||||
|       {:ok, %{id: invite_id, token: token}} = |       {:ok, %{id: invite_id, token: token}} = | ||||||
|         admin_fixture() |> Invites.create_invite(%{"name" => "my invite"}) |         admin_fixture() |> Invites.create_invite(%{name: "my invite"}) | ||||||
|  |  | ||||||
|       assert {:ok, %{invite_id: ^invite_id}} = |       assert {:ok, %{invite_id: ^invite_id}} = | ||||||
|                Accounts.register_user( |                Accounts.register_user( | ||||||
|                  %{"email" => unique_user_email(), "password" => valid_user_password()}, |                  %{email: unique_user_email(), password: valid_user_password()}, | ||||||
|                  token |                  token | ||||||
|                ) |                ) | ||||||
|     end |     end | ||||||
| @@ -123,7 +121,7 @@ defmodule Cannery.AccountsTest do | |||||||
|       email = unique_user_email() |       email = unique_user_email() | ||||||
|       password = valid_user_password() |       password = valid_user_password() | ||||||
|  |  | ||||||
|       changeset = Accounts.change_user_registration(%{"email" => email, "password" => password}) |       changeset = Accounts.change_user_registration(%{email: email, password: password}) | ||||||
|  |  | ||||||
|       assert changeset.valid? |       assert changeset.valid? | ||||||
|       assert get_change(changeset, :email) == email |       assert get_change(changeset, :email) == email | ||||||
| @@ -151,7 +149,7 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|     test "validates email", %{user: user} do |     test "validates email", %{user: user} do | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.apply_user_email(user, valid_user_password(), %{"email" => "not valid"}) |         Accounts.apply_user_email(user, valid_user_password(), %{email: "not valid"}) | ||||||
|  |  | ||||||
|       assert %{email: ["must have the @ sign and no spaces"]} = errors_on(changeset) |       assert %{email: ["must have the @ sign and no spaces"]} = errors_on(changeset) | ||||||
|     end |     end | ||||||
| @@ -160,7 +158,7 @@ defmodule Cannery.AccountsTest do | |||||||
|       too_long = String.duplicate("db", 100) |       too_long = String.duplicate("db", 100) | ||||||
|  |  | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.apply_user_email(user, valid_user_password(), %{"email" => too_long}) |         Accounts.apply_user_email(user, valid_user_password(), %{email: too_long}) | ||||||
|  |  | ||||||
|       assert "should be at most 160 character(s)" in errors_on(changeset).email |       assert "should be at most 160 character(s)" in errors_on(changeset).email | ||||||
|     end |     end | ||||||
| @@ -169,21 +167,21 @@ defmodule Cannery.AccountsTest do | |||||||
|       %{email: email} = user_fixture() |       %{email: email} = user_fixture() | ||||||
|  |  | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.apply_user_email(user, valid_user_password(), %{"email" => email}) |         Accounts.apply_user_email(user, valid_user_password(), %{email: email}) | ||||||
|  |  | ||||||
|       assert "has already been taken" in errors_on(changeset).email |       assert "has already been taken" in errors_on(changeset).email | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "validates current password", %{user: user} do |     test "validates current password", %{user: user} do | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.apply_user_email(user, "invalid", %{"email" => unique_user_email()}) |         Accounts.apply_user_email(user, "invalid", %{email: unique_user_email()}) | ||||||
|  |  | ||||||
|       assert %{current_password: ["is not valid"]} = errors_on(changeset) |       assert %{current_password: ["is not valid"]} = errors_on(changeset) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "applies the email without persisting it", %{user: user} do |     test "applies the email without persisting it", %{user: user} do | ||||||
|       email = unique_user_email() |       email = unique_user_email() | ||||||
|       {:ok, user} = Accounts.apply_user_email(user, valid_user_password(), %{"email" => email}) |       {:ok, user} = Accounts.apply_user_email(user, valid_user_password(), %{email: email}) | ||||||
|       assert user.email == email |       assert user.email == email | ||||||
|       assert Accounts.get_user!(user.id).email != email |       assert Accounts.get_user!(user.id).email != email | ||||||
|     end |     end | ||||||
| @@ -258,11 +256,7 @@ defmodule Cannery.AccountsTest do | |||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "allows fields to be set" do |     test "allows fields to be set" do | ||||||
|       changeset = |       changeset = Accounts.change_user_password(%User{}, %{password: "new valid password"}) | ||||||
|         Accounts.change_user_password(%User{}, %{ |  | ||||||
|           "password" => "new valid password" |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|       assert changeset.valid? |       assert changeset.valid? | ||||||
|       assert get_change(changeset, :password) == "new valid password" |       assert get_change(changeset, :password) == "new valid password" | ||||||
|       assert is_nil(get_change(changeset, :hashed_password)) |       assert is_nil(get_change(changeset, :hashed_password)) | ||||||
| @@ -277,8 +271,8 @@ defmodule Cannery.AccountsTest do | |||||||
|     test "validates password", %{user: user} do |     test "validates password", %{user: user} do | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.update_user_password(user, valid_user_password(), %{ |         Accounts.update_user_password(user, valid_user_password(), %{ | ||||||
|           "password" => "not valid", |           password: "not valid", | ||||||
|           "password_confirmation" => "another" |           password_confirmation: "another" | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert %{ |       assert %{ | ||||||
| @@ -291,14 +285,14 @@ defmodule Cannery.AccountsTest do | |||||||
|       too_long = String.duplicate("db", 100) |       too_long = String.duplicate("db", 100) | ||||||
|  |  | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.update_user_password(user, valid_user_password(), %{"password" => too_long}) |         Accounts.update_user_password(user, valid_user_password(), %{password: too_long}) | ||||||
|  |  | ||||||
|       assert "should be at most 80 character(s)" in errors_on(changeset).password |       assert "should be at most 80 character(s)" in errors_on(changeset).password | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "validates current password", %{user: user} do |     test "validates current password", %{user: user} do | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.update_user_password(user, "invalid", %{"password" => valid_user_password()}) |         Accounts.update_user_password(user, "invalid", %{password: valid_user_password()}) | ||||||
|  |  | ||||||
|       assert %{current_password: ["is not valid"]} = errors_on(changeset) |       assert %{current_password: ["is not valid"]} = errors_on(changeset) | ||||||
|     end |     end | ||||||
| @@ -306,7 +300,7 @@ defmodule Cannery.AccountsTest do | |||||||
|     test "updates the password", %{user: user} do |     test "updates the password", %{user: user} do | ||||||
|       {:ok, user} = |       {:ok, user} = | ||||||
|         Accounts.update_user_password(user, valid_user_password(), %{ |         Accounts.update_user_password(user, valid_user_password(), %{ | ||||||
|           "password" => "new valid password" |           password: "new valid password" | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert is_nil(user.password) |       assert is_nil(user.password) | ||||||
| @@ -318,7 +312,7 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|       {:ok, _} = |       {:ok, _} = | ||||||
|         Accounts.update_user_password(user, valid_user_password(), %{ |         Accounts.update_user_password(user, valid_user_password(), %{ | ||||||
|           "password" => "new valid password" |           password: "new valid password" | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       refute Repo.get_by(UserToken, user_id: user.id) |       refute Repo.get_by(UserToken, user_id: user.id) | ||||||
| @@ -486,8 +480,8 @@ defmodule Cannery.AccountsTest do | |||||||
|     test "validates password", %{user: user} do |     test "validates password", %{user: user} do | ||||||
|       {:error, changeset} = |       {:error, changeset} = | ||||||
|         Accounts.reset_user_password(user, %{ |         Accounts.reset_user_password(user, %{ | ||||||
|           "password" => "not valid", |           password: "not valid", | ||||||
|           "password_confirmation" => "another" |           password_confirmation: "another" | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert %{ |       assert %{ | ||||||
| @@ -498,13 +492,12 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|     test "validates maximum values for password for security", %{user: user} do |     test "validates maximum values for password for security", %{user: user} do | ||||||
|       too_long = String.duplicate("db", 100) |       too_long = String.duplicate("db", 100) | ||||||
|       {:error, changeset} = Accounts.reset_user_password(user, %{"password" => too_long}) |       {:error, changeset} = Accounts.reset_user_password(user, %{password: too_long}) | ||||||
|       assert "should be at most 80 character(s)" in errors_on(changeset).password |       assert "should be at most 80 character(s)" in errors_on(changeset).password | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "updates the password", %{user: user} do |     test "updates the password", %{user: user} do | ||||||
|       {:ok, updated_user} = |       {:ok, updated_user} = Accounts.reset_user_password(user, %{password: "new valid password"}) | ||||||
|         Accounts.reset_user_password(user, %{"password" => "new valid password"}) |  | ||||||
|  |  | ||||||
|       assert is_nil(updated_user.password) |       assert is_nil(updated_user.password) | ||||||
|       assert Accounts.get_user_by_email_and_password(user.email, "new valid password") |       assert Accounts.get_user_by_email_and_password(user.email, "new valid password") | ||||||
| @@ -512,7 +505,7 @@ defmodule Cannery.AccountsTest do | |||||||
|  |  | ||||||
|     test "deletes all tokens for the given user", %{user: user} do |     test "deletes all tokens for the given user", %{user: user} do | ||||||
|       _session_token = Accounts.generate_user_session_token(user) |       _session_token = Accounts.generate_user_session_token(user) | ||||||
|       {:ok, _user} = Accounts.reset_user_password(user, %{"password" => "new valid password"}) |       {:ok, _user} = Accounts.reset_user_password(user, %{password: "new valid password"}) | ||||||
|       refute Repo.get_by(UserToken, user_id: user.id) |       refute Repo.get_by(UserToken, user_id: user.id) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -5,12 +5,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|  |  | ||||||
|   use Cannery.DataCase |   use Cannery.DataCase | ||||||
|   import Cannery.Fixtures |   import Cannery.Fixtures | ||||||
|  |   alias Cannery.{ActivityLog, ActivityLog.ShotGroup, Ammo} | ||||||
|   alias Cannery.{ |  | ||||||
|     ActivityLog, |  | ||||||
|     ActivityLog.ShotGroup, |  | ||||||
|     Ammo |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @moduletag :activity_log_test |   @moduletag :activity_log_test | ||||||
|  |  | ||||||
| @@ -21,10 +16,10 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       ammo_type = ammo_type_fixture(current_user) |       ammo_type = ammo_type_fixture(current_user) | ||||||
|  |  | ||||||
|       {1, [%{id: ammo_group_id} = ammo_group]} = |       {1, [%{id: ammo_group_id} = ammo_group]} = | ||||||
|         ammo_group_fixture(%{"count" => 25}, ammo_type, container, current_user) |         ammo_group_fixture(%{count: 25}, ammo_type, container, current_user) | ||||||
|  |  | ||||||
|       shot_group = |       shot_group = | ||||||
|         %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"} |         %{count: 5, date: ~N[2022-02-13 03:17:00], notes: "some notes"} | ||||||
|         |> shot_group_fixture(current_user, ammo_group) |         |> shot_group_fixture(current_user, ammo_group) | ||||||
|  |  | ||||||
|       ammo_group = ammo_group_id |> Ammo.get_ammo_group!(current_user) |       ammo_group = ammo_group_id |> Ammo.get_ammo_group!(current_user) | ||||||
| @@ -38,50 +33,6 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       ] |       ] | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "list_shot_groups/1 returns all shot_groups", |  | ||||||
|          %{shot_group: shot_group, current_user: current_user} do |  | ||||||
|       assert ActivityLog.list_shot_groups(current_user) == [shot_group] |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     test "list_shot_groups/2 returns relevant shot_groups for a user", %{ |  | ||||||
|       ammo_type: ammo_type, |  | ||||||
|       ammo_group: ammo_group, |  | ||||||
|       container: container, |  | ||||||
|       current_user: current_user |  | ||||||
|     } do |  | ||||||
|       shot_group_a = shot_group_fixture(%{"notes" => "amazing"}, current_user, ammo_group) |  | ||||||
|  |  | ||||||
|       {1, [another_ammo_group]} = |  | ||||||
|         ammo_group_fixture(%{"notes" => "stupendous"}, ammo_type, container, current_user) |  | ||||||
|  |  | ||||||
|       shot_group_b = shot_group_fixture(current_user, another_ammo_group) |  | ||||||
|  |  | ||||||
|       another_ammo_type = ammo_type_fixture(%{"name" => "fabulous ammo"}, current_user) |  | ||||||
|  |  | ||||||
|       {1, [yet_another_ammo_group]} = |  | ||||||
|         ammo_group_fixture(another_ammo_type, container, current_user) |  | ||||||
|  |  | ||||||
|       shot_group_c = shot_group_fixture(current_user, yet_another_ammo_group) |  | ||||||
|  |  | ||||||
|       random_user = user_fixture() |  | ||||||
|       random_container = container_fixture(random_user) |  | ||||||
|       random_ammo_type = ammo_type_fixture(random_user) |  | ||||||
|  |  | ||||||
|       {1, [random_ammo_group]} = |  | ||||||
|         ammo_group_fixture(random_ammo_type, random_container, random_user) |  | ||||||
|  |  | ||||||
|       _shouldnt_return = shot_group_fixture(random_user, random_ammo_group) |  | ||||||
|  |  | ||||||
|       # notes |  | ||||||
|       assert ActivityLog.list_shot_groups("amazing", current_user) == [shot_group_a] |  | ||||||
|  |  | ||||||
|       # ammo group attributes |  | ||||||
|       assert ActivityLog.list_shot_groups("stupendous", current_user) == [shot_group_b] |  | ||||||
|  |  | ||||||
|       # ammo type attributes |  | ||||||
|       assert ActivityLog.list_shot_groups("fabulous", current_user) == [shot_group_c] |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     test "get_shot_group!/2 returns the shot_group with given id", |     test "get_shot_group!/2 returns the shot_group with given id", | ||||||
|          %{shot_group: shot_group, current_user: current_user} do |          %{shot_group: shot_group, current_user: current_user} do | ||||||
|       assert ActivityLog.get_shot_group!(shot_group.id, current_user) == shot_group |       assert ActivityLog.get_shot_group!(shot_group.id, current_user) == shot_group | ||||||
| @@ -98,7 +49,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|  |  | ||||||
|     test "create_shot_group/3 with valid data creates a shot_group", |     test "create_shot_group/3 with valid data creates a shot_group", | ||||||
|          %{current_user: current_user, ammo_group: ammo_group} do |          %{current_user: current_user, ammo_group: ammo_group} do | ||||||
|       valid_attrs = %{"count" => 10, "date" => ~D[2022-02-13], "notes" => "some notes"} |       valid_attrs = %{count: 10, date: ~D[2022-02-13], notes: "some notes"} | ||||||
|  |  | ||||||
|       assert {:ok, %ShotGroup{} = shot_group} = |       assert {:ok, %ShotGroup{} = shot_group} = | ||||||
|                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) |                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) | ||||||
| @@ -113,7 +64,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|            current_user: current_user, |            current_user: current_user, | ||||||
|            ammo_group: %{id: ammo_group_id, count: org_count} = ammo_group |            ammo_group: %{id: ammo_group_id, count: org_count} = ammo_group | ||||||
|          } do |          } do | ||||||
|       valid_attrs = %{"count" => 10, "date" => ~D[2022-02-13], "notes" => "some notes"} |       valid_attrs = %{count: 10, date: ~D[2022-02-13], notes: "some notes"} | ||||||
|  |  | ||||||
|       assert {:ok, %ShotGroup{} = shot_group} = |       assert {:ok, %ShotGroup{} = shot_group} = | ||||||
|                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) |                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) | ||||||
| @@ -126,7 +77,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|  |  | ||||||
|     test "create_shot_group/3 does not remove more than ammo group amount", |     test "create_shot_group/3 does not remove more than ammo group amount", | ||||||
|          %{current_user: current_user, ammo_group: %{id: ammo_group_id} = ammo_group} do |          %{current_user: current_user, ammo_group: %{id: ammo_group_id} = ammo_group} do | ||||||
|       valid_attrs = %{"count" => 20, "date" => ~D[2022-02-13], "notes" => "some notes"} |       valid_attrs = %{count: 20, date: ~D[2022-02-13], notes: "some notes"} | ||||||
|  |  | ||||||
|       assert {:ok, %ShotGroup{}} = |       assert {:ok, %ShotGroup{}} = | ||||||
|                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) |                ActivityLog.create_shot_group(valid_attrs, current_user, ammo_group) | ||||||
| @@ -136,12 +87,12 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert ammo_group.count == 0 |       assert ammo_group.count == 0 | ||||||
|  |  | ||||||
|       assert {:error, %Ecto.Changeset{}} = |       assert {:error, %Ecto.Changeset{}} = | ||||||
|                ActivityLog.create_shot_group(%{"count" => 1}, current_user, ammo_group) |                ActivityLog.create_shot_group(%{count: 1}, current_user, ammo_group) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_shot_group/3 with invalid data returns error changeset", |     test "create_shot_group/3 with invalid data returns error changeset", | ||||||
|          %{current_user: current_user, ammo_group: ammo_group} do |          %{current_user: current_user, ammo_group: ammo_group} do | ||||||
|       invalid_params = %{"count" => nil, "date" => nil, "notes" => nil} |       invalid_params = %{count: nil, date: nil, notes: nil} | ||||||
|  |  | ||||||
|       assert {:error, %Ecto.Changeset{}} = |       assert {:error, %Ecto.Changeset{}} = | ||||||
|                ActivityLog.create_shot_group(invalid_params, current_user, ammo_group) |                ActivityLog.create_shot_group(invalid_params, current_user, ammo_group) | ||||||
| @@ -157,9 +108,9 @@ defmodule Cannery.ActivityLogTest do | |||||||
|                ActivityLog.update_shot_group( |                ActivityLog.update_shot_group( | ||||||
|                  shot_group, |                  shot_group, | ||||||
|                  %{ |                  %{ | ||||||
|                    "count" => 10, |                    count: 10, | ||||||
|                    "date" => ~D[2022-02-13], |                    date: ~D[2022-02-13], | ||||||
|                    "notes" => "some updated notes" |                    notes: "some updated notes" | ||||||
|                  }, |                  }, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
| @@ -175,9 +126,9 @@ defmodule Cannery.ActivityLogTest do | |||||||
|                ActivityLog.update_shot_group( |                ActivityLog.update_shot_group( | ||||||
|                  shot_group, |                  shot_group, | ||||||
|                  %{ |                  %{ | ||||||
|                    "count" => 25, |                    count: 25, | ||||||
|                    "date" => ~D[2022-02-13], |                    date: ~D[2022-02-13], | ||||||
|                    "notes" => "some updated notes" |                    notes: "some updated notes" | ||||||
|                  }, |                  }, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
| @@ -193,14 +144,14 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert {:error, %Ecto.Changeset{}} = |       assert {:error, %Ecto.Changeset{}} = | ||||||
|                ActivityLog.update_shot_group( |                ActivityLog.update_shot_group( | ||||||
|                  shot_group, |                  shot_group, | ||||||
|                  %{"count" => 26, "date" => nil, "notes" => nil}, |                  %{count: 26, date: nil, notes: nil}, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
|       assert {:error, %Ecto.Changeset{}} = |       assert {:error, %Ecto.Changeset{}} = | ||||||
|                ActivityLog.update_shot_group( |                ActivityLog.update_shot_group( | ||||||
|                  shot_group, |                  shot_group, | ||||||
|                  %{"count" => -1, "date" => nil, "notes" => nil}, |                  %{count: -1, date: nil, notes: nil}, | ||||||
|                  current_user |                  current_user | ||||||
|                ) |                ) | ||||||
|  |  | ||||||
| @@ -228,10 +179,10 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert 0 = another_ammo_group |> ActivityLog.get_used_count(current_user) |       assert 0 = another_ammo_group |> ActivityLog.get_used_count(current_user) | ||||||
|       assert 5 = ammo_group |> ActivityLog.get_used_count(current_user) |       assert 5 = ammo_group |> ActivityLog.get_used_count(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 15}, current_user, ammo_group) |       shot_group_fixture(%{count: 15}, current_user, ammo_group) | ||||||
|       assert 20 = ammo_group |> ActivityLog.get_used_count(current_user) |       assert 20 = ammo_group |> ActivityLog.get_used_count(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 10}, current_user, ammo_group) |       shot_group_fixture(%{count: 10}, current_user, ammo_group) | ||||||
|       assert 30 = ammo_group |> ActivityLog.get_used_count(current_user) |       assert 30 = ammo_group |> ActivityLog.get_used_count(current_user) | ||||||
|  |  | ||||||
|       {1, [another_ammo_group]} = ammo_group_fixture(ammo_type, container, current_user) |       {1, [another_ammo_group]} = ammo_group_fixture(ammo_type, container, current_user) | ||||||
| @@ -250,17 +201,17 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{ammo_group_id => 5} == |       assert %{ammo_group_id => 5} == | ||||||
|                [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) |                [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 5}, current_user, another_ammo_group) |       shot_group_fixture(%{count: 5}, current_user, another_ammo_group) | ||||||
|       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) |       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) | ||||||
|       assert %{^ammo_group_id => 5} = used_counts |       assert %{^ammo_group_id => 5} = used_counts | ||||||
|       assert %{^another_ammo_group_id => 5} = used_counts |       assert %{^another_ammo_group_id => 5} = used_counts | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 15}, current_user, ammo_group) |       shot_group_fixture(%{count: 15}, current_user, ammo_group) | ||||||
|       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) |       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) | ||||||
|       assert %{^ammo_group_id => 20} = used_counts |       assert %{^ammo_group_id => 20} = used_counts | ||||||
|       assert %{^another_ammo_group_id => 5} = used_counts |       assert %{^another_ammo_group_id => 5} = used_counts | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 10}, current_user, ammo_group) |       shot_group_fixture(%{count: 10}, current_user, ammo_group) | ||||||
|       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) |       used_counts = [ammo_group, another_ammo_group] |> ActivityLog.get_used_counts(current_user) | ||||||
|       assert %{^ammo_group_id => 30} = used_counts |       assert %{^ammo_group_id => 30} = used_counts | ||||||
|       assert %{^another_ammo_group_id => 5} = used_counts |       assert %{^another_ammo_group_id => 5} = used_counts | ||||||
| @@ -277,10 +228,10 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert another_ammo_group |> ActivityLog.get_last_used_date(current_user) |> is_nil() |       assert another_ammo_group |> ActivityLog.get_last_used_date(current_user) |> is_nil() | ||||||
|       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) |       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) | ||||||
|  |  | ||||||
|       %{date: date} = shot_group_fixture(%{"date" => ~D[2022-11-10]}, current_user, ammo_group) |       %{date: date} = shot_group_fixture(%{date: ~D[2022-11-10]}, current_user, ammo_group) | ||||||
|       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) |       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) | ||||||
|  |  | ||||||
|       %{date: date} = shot_group_fixture(%{"date" => ~D[2022-11-11]}, current_user, ammo_group) |       %{date: date} = shot_group_fixture(%{date: ~D[2022-11-11]}, current_user, ammo_group) | ||||||
|       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) |       assert ^date = ammo_group |> ActivityLog.get_last_used_date(current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -298,7 +249,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{ammo_group_id => date} == |       assert %{ammo_group_id => date} == | ||||||
|                [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) |                [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"date" => ~D[2022-11-09]}, current_user, another_ammo_group) |       shot_group_fixture(%{date: ~D[2022-11-09]}, current_user, another_ammo_group) | ||||||
|  |  | ||||||
|       # setting initial date |       # setting initial date | ||||||
|       last_used_shot_groups = |       last_used_shot_groups = | ||||||
| @@ -308,7 +259,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{^another_ammo_group_id => ~D[2022-11-09]} = last_used_shot_groups |       assert %{^another_ammo_group_id => ~D[2022-11-09]} = last_used_shot_groups | ||||||
|  |  | ||||||
|       # setting another date |       # setting another date | ||||||
|       shot_group_fixture(%{"date" => ~D[2022-11-10]}, current_user, ammo_group) |       shot_group_fixture(%{date: ~D[2022-11-10]}, current_user, ammo_group) | ||||||
|  |  | ||||||
|       last_used_shot_groups = |       last_used_shot_groups = | ||||||
|         [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) |         [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) | ||||||
| @@ -317,7 +268,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{^another_ammo_group_id => ~D[2022-11-09]} = last_used_shot_groups |       assert %{^another_ammo_group_id => ~D[2022-11-09]} = last_used_shot_groups | ||||||
|  |  | ||||||
|       # setting yet another date |       # setting yet another date | ||||||
|       shot_group_fixture(%{"date" => ~D[2022-11-11]}, current_user, ammo_group) |       shot_group_fixture(%{date: ~D[2022-11-11]}, current_user, ammo_group) | ||||||
|  |  | ||||||
|       last_used_shot_groups = |       last_used_shot_groups = | ||||||
|         [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) |         [ammo_group, another_ammo_group] |> ActivityLog.get_last_used_dates(current_user) | ||||||
| @@ -332,10 +283,10 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert 0 = another_ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) |       assert 0 = another_ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) | ||||||
|       assert 5 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) |       assert 5 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 5}, current_user, ammo_group) |       shot_group_fixture(%{count: 5}, current_user, ammo_group) | ||||||
|       assert 10 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) |       assert 10 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 1}, current_user, ammo_group) |       shot_group_fixture(%{count: 1}, current_user, ammo_group) | ||||||
|       assert 11 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) |       assert 11 = ammo_type |> ActivityLog.get_used_count_for_ammo_type(current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -353,7 +304,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|                |> ActivityLog.get_used_count_for_ammo_types(current_user) |                |> ActivityLog.get_used_count_for_ammo_types(current_user) | ||||||
|  |  | ||||||
|       # use generated ammo group |       # use generated ammo group | ||||||
|       shot_group_fixture(%{"count" => 5}, current_user, ammo_group) |       shot_group_fixture(%{count: 5}, current_user, ammo_group) | ||||||
|  |  | ||||||
|       used_counts = |       used_counts = | ||||||
|         [ammo_type, another_ammo_type] |> ActivityLog.get_used_count_for_ammo_types(current_user) |         [ammo_type, another_ammo_type] |> ActivityLog.get_used_count_for_ammo_types(current_user) | ||||||
| @@ -362,7 +313,7 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{^another_ammo_type_id => 5} = used_counts |       assert %{^another_ammo_type_id => 5} = used_counts | ||||||
|  |  | ||||||
|       # use generated ammo group again |       # use generated ammo group again | ||||||
|       shot_group_fixture(%{"count" => 1}, current_user, ammo_group) |       shot_group_fixture(%{count: 1}, current_user, ammo_group) | ||||||
|  |  | ||||||
|       used_counts = |       used_counts = | ||||||
|         [ammo_type, another_ammo_type] |> ActivityLog.get_used_count_for_ammo_types(current_user) |         [ammo_type, another_ammo_type] |> ActivityLog.get_used_count_for_ammo_types(current_user) | ||||||
| @@ -371,4 +322,99 @@ defmodule Cannery.ActivityLogTest do | |||||||
|       assert %{^another_ammo_type_id => 6} = used_counts |       assert %{^another_ammo_type_id => 6} = used_counts | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   describe "list_shot_groups/3" do | ||||||
|  |     setup do | ||||||
|  |       current_user = user_fixture() | ||||||
|  |       container = container_fixture(current_user) | ||||||
|  |       ammo_type = ammo_type_fixture(current_user) | ||||||
|  |       {1, [ammo_group]} = ammo_group_fixture(ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       [ | ||||||
|  |         current_user: current_user, | ||||||
|  |         container: container, | ||||||
|  |         ammo_type: ammo_type, | ||||||
|  |         ammo_group: ammo_group | ||||||
|  |       ] | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     test "list_shot_groups/3 returns relevant shot_groups for a type", | ||||||
|  |          %{current_user: current_user, container: container} do | ||||||
|  |       other_user = user_fixture() | ||||||
|  |       other_container = container_fixture(other_user) | ||||||
|  |  | ||||||
|  |       for class <- ["rifle", "shotgun", "pistol"] do | ||||||
|  |         other_ammo_type = ammo_type_fixture(%{class: class}, other_user) | ||||||
|  |         {1, [other_ammo_group]} = ammo_group_fixture(other_ammo_type, other_container, other_user) | ||||||
|  |         shot_group_fixture(other_user, other_ammo_group) | ||||||
|  |       end | ||||||
|  |  | ||||||
|  |       rifle_ammo_type = ammo_type_fixture(%{class: :rifle}, current_user) | ||||||
|  |       {1, [rifle_ammo_group]} = ammo_group_fixture(rifle_ammo_type, container, current_user) | ||||||
|  |       rifle_shot_group = shot_group_fixture(current_user, rifle_ammo_group) | ||||||
|  |  | ||||||
|  |       shotgun_ammo_type = ammo_type_fixture(%{class: :shotgun}, current_user) | ||||||
|  |       {1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_ammo_type, container, current_user) | ||||||
|  |       shotgun_shot_group = shot_group_fixture(current_user, shotgun_ammo_group) | ||||||
|  |  | ||||||
|  |       pistol_ammo_type = ammo_type_fixture(%{class: :pistol}, current_user) | ||||||
|  |       {1, [pistol_ammo_group]} = ammo_group_fixture(pistol_ammo_type, container, current_user) | ||||||
|  |       pistol_shot_group = shot_group_fixture(current_user, pistol_ammo_group) | ||||||
|  |  | ||||||
|  |       assert [^rifle_shot_group] = ActivityLog.list_shot_groups(:rifle, current_user) | ||||||
|  |       assert [^shotgun_shot_group] = ActivityLog.list_shot_groups(:shotgun, current_user) | ||||||
|  |       assert [^pistol_shot_group] = ActivityLog.list_shot_groups(:pistol, current_user) | ||||||
|  |  | ||||||
|  |       shot_groups = ActivityLog.list_shot_groups(:all, current_user) | ||||||
|  |       assert Enum.count(shot_groups) == 3 | ||||||
|  |       assert rifle_shot_group in shot_groups | ||||||
|  |       assert shotgun_shot_group in shot_groups | ||||||
|  |       assert pistol_shot_group in shot_groups | ||||||
|  |  | ||||||
|  |       shot_groups = ActivityLog.list_shot_groups(nil, current_user) | ||||||
|  |       assert Enum.count(shot_groups) == 3 | ||||||
|  |       assert rifle_shot_group in shot_groups | ||||||
|  |       assert shotgun_shot_group in shot_groups | ||||||
|  |       assert pistol_shot_group in shot_groups | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     test "list_shot_groups/3 returns relevant shot_groups for a search", %{ | ||||||
|  |       ammo_type: ammo_type, | ||||||
|  |       ammo_group: ammo_group, | ||||||
|  |       container: container, | ||||||
|  |       current_user: current_user | ||||||
|  |     } do | ||||||
|  |       shot_group_a = shot_group_fixture(%{notes: "amazing"}, current_user, ammo_group) | ||||||
|  |  | ||||||
|  |       {1, [another_ammo_group]} = | ||||||
|  |         ammo_group_fixture(%{notes: "stupendous"}, ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       shot_group_b = shot_group_fixture(current_user, another_ammo_group) | ||||||
|  |  | ||||||
|  |       another_ammo_type = ammo_type_fixture(%{name: "fabulous ammo"}, current_user) | ||||||
|  |  | ||||||
|  |       {1, [yet_another_ammo_group]} = | ||||||
|  |         ammo_group_fixture(another_ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       shot_group_c = shot_group_fixture(current_user, yet_another_ammo_group) | ||||||
|  |  | ||||||
|  |       another_user = user_fixture() | ||||||
|  |       another_container = container_fixture(another_user) | ||||||
|  |       another_ammo_type = ammo_type_fixture(another_user) | ||||||
|  |  | ||||||
|  |       {1, [another_ammo_group]} = | ||||||
|  |         ammo_group_fixture(another_ammo_type, another_container, another_user) | ||||||
|  |  | ||||||
|  |       _shouldnt_return = shot_group_fixture(another_user, another_ammo_group) | ||||||
|  |  | ||||||
|  |       # notes | ||||||
|  |       assert ActivityLog.list_shot_groups("amazing", :all, current_user) == [shot_group_a] | ||||||
|  |  | ||||||
|  |       # ammo group attributes | ||||||
|  |       assert ActivityLog.list_shot_groups("stupendous", :all, current_user) == [shot_group_b] | ||||||
|  |  | ||||||
|  |       # ammo type attributes | ||||||
|  |       assert ActivityLog.list_shot_groups("fabulous", :all, current_user) == [shot_group_c] | ||||||
|  |     end | ||||||
|  |   end | ||||||
| end | end | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,37 +10,37 @@ defmodule Cannery.ContainersTest do | |||||||
|   @moduletag :containers_test |   @moduletag :containers_test | ||||||
|  |  | ||||||
|   @valid_attrs %{ |   @valid_attrs %{ | ||||||
|     "desc" => "some desc", |     desc: "some desc", | ||||||
|     "location" => "some location", |     location: "some location", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "type" => "some type" |     type: "some type" | ||||||
|   } |   } | ||||||
|   @update_attrs %{ |   @update_attrs %{ | ||||||
|     "desc" => "some updated desc", |     desc: "some updated desc", | ||||||
|     "location" => "some updated location", |     location: "some updated location", | ||||||
|     "name" => "some updated name", |     name: "some updated name", | ||||||
|     "type" => "some updated type" |     type: "some updated type" | ||||||
|   } |   } | ||||||
|   @invalid_attrs %{ |   @invalid_attrs %{ | ||||||
|     "desc" => nil, |     desc: nil, | ||||||
|     "location" => nil, |     location: nil, | ||||||
|     "name" => nil, |     name: nil, | ||||||
|     "type" => nil |     type: nil | ||||||
|   } |   } | ||||||
|   @valid_tag_attrs %{ |   @valid_tag_attrs %{ | ||||||
|     "bg_color" => "some bg-color", |     bg_color: "#100000", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "text_color" => "some text-color" |     text_color: "#000000" | ||||||
|   } |   } | ||||||
|   @update_tag_attrs %{ |   @update_tag_attrs %{ | ||||||
|     "bg_color" => "some updated bg-color", |     bg_color: "#100001", | ||||||
|     "name" => "some updated name", |     name: "some updated name", | ||||||
|     "text_color" => "some updated text-color" |     text_color: "#000001" | ||||||
|   } |   } | ||||||
|   @invalid_tag_attrs %{ |   @invalid_tag_attrs %{ | ||||||
|     "bg_color" => nil, |     bg_color: nil, | ||||||
|     "name" => nil, |     name: nil, | ||||||
|     "text_color" => nil |     text_color: nil | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   describe "containers" do |   describe "containers" do | ||||||
| @@ -57,25 +57,24 @@ defmodule Cannery.ContainersTest do | |||||||
|  |  | ||||||
|     test "list_containers/2 returns relevant containers for a user", |     test "list_containers/2 returns relevant containers for a user", | ||||||
|          %{current_user: current_user} do |          %{current_user: current_user} do | ||||||
|       container_a = container_fixture(%{"name" => "my cool container"}, current_user) |       container_a = container_fixture(%{name: "my cool container"}, current_user) | ||||||
|       container_b = container_fixture(%{"desc" => "a fascinating description"}, current_user) |       container_b = container_fixture(%{desc: "a fascinating description"}, current_user) | ||||||
|  |  | ||||||
|       %{id: container_c_id} = |       %{id: container_c_id} = | ||||||
|         container_c = container_fixture(%{"location" => "a secret place"}, current_user) |         container_c = container_fixture(%{location: "a secret place"}, current_user) | ||||||
|  |  | ||||||
|       tag = tag_fixture(%{"name" => "stupendous tag"}, current_user) |       tag = tag_fixture(%{name: "stupendous tag"}, current_user) | ||||||
|       Containers.add_tag!(container_c, tag, current_user) |       Containers.add_tag!(container_c, tag, current_user) | ||||||
|       container_c = container_c_id |> Containers.get_container!(current_user) |       container_c = container_c_id |> Containers.get_container!(current_user) | ||||||
|  |  | ||||||
|       %{id: container_d_id} = |       %{id: container_d_id} = | ||||||
|         container_d = container_fixture(%{"type" => "musty old box"}, current_user) |         container_d = container_fixture(%{type: "musty old box"}, current_user) | ||||||
|  |  | ||||||
|       tag = tag_fixture(%{"name" => "amazing tag"}, current_user) |       tag = tag_fixture(%{name: "amazing tag"}, current_user) | ||||||
|       Containers.add_tag!(container_d, tag, current_user) |       Containers.add_tag!(container_d, tag, current_user) | ||||||
|       container_d = container_d_id |> Containers.get_container!(current_user) |       container_d = container_d_id |> Containers.get_container!(current_user) | ||||||
|  |  | ||||||
|       _shouldnt_return = |       _shouldnt_return = container_fixture(%{name: "another person's container"}, user_fixture()) | ||||||
|         container_fixture(%{"name" => "another person's container"}, user_fixture()) |  | ||||||
|  |  | ||||||
|       # attributes |       # attributes | ||||||
|       assert Containers.list_containers("cool", current_user) == [container_a] |       assert Containers.list_containers("cool", current_user) == [container_a] | ||||||
| @@ -90,14 +89,26 @@ defmodule Cannery.ContainersTest do | |||||||
|       assert Containers.list_containers("asajslkdflskdf", current_user) == [] |       assert Containers.list_containers("asajslkdflskdf", current_user) == [] | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "get_container!/1 returns the container with given id", |     test "get_container!/2 returns the container with given id", | ||||||
|          %{current_user: current_user, container: container} do |          %{current_user: current_user, container: container} do | ||||||
|       assert Containers.get_container!(container.id, current_user) == container |       assert Containers.get_container!(container.id, current_user) == container | ||||||
|  |       assert_raise KeyError, fn -> Containers.get_container!(current_user.id, current_user) end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_container/1 with valid data creates a container", %{current_user: current_user} do |     test "get_containers/2 returns the container with given id", | ||||||
|  |          %{current_user: current_user, container: %{id: container_id} = container} do | ||||||
|  |       assert %{container_id => container} == | ||||||
|  |                Containers.get_containers([container_id], current_user) | ||||||
|  |  | ||||||
|  |       %{id: another_container_id} = another_container = container_fixture(current_user) | ||||||
|  |       containers = [container_id, another_container_id] |> Containers.get_containers(current_user) | ||||||
|  |       assert %{^container_id => ^container} = containers | ||||||
|  |       assert %{^another_container_id => ^another_container} = containers | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     test "create_container/2 with valid data creates a container", %{current_user: current_user} do | ||||||
|       assert {:ok, %Container{} = container} = |       assert {:ok, %Container{} = container} = | ||||||
|                @valid_attrs |> Containers.create_container(current_user) |                Containers.create_container(@valid_attrs, current_user) | ||||||
|  |  | ||||||
|       assert container.desc == "some desc" |       assert container.desc == "some desc" | ||||||
|       assert container.location == "some location" |       assert container.location == "some location" | ||||||
| @@ -106,12 +117,12 @@ defmodule Cannery.ContainersTest do | |||||||
|       assert container.user_id == current_user.id |       assert container.user_id == current_user.id | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_container/1 with invalid data returns error changeset", |     test "create_container/2 with invalid data returns error changeset", | ||||||
|          %{current_user: current_user} do |          %{current_user: current_user} do | ||||||
|       assert {:error, %Changeset{}} = @invalid_attrs |> Containers.create_container(current_user) |       assert {:error, %Changeset{}} = Containers.create_container(@invalid_attrs, current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "update_container/2 with valid data updates the container", |     test "update_container/3 with valid data updates the container", | ||||||
|          %{current_user: current_user, container: container} do |          %{current_user: current_user, container: container} do | ||||||
|       assert {:ok, %Container{} = container} = |       assert {:ok, %Container{} = container} = | ||||||
|                Containers.update_container(container, current_user, @update_attrs) |                Containers.update_container(container, current_user, @update_attrs) | ||||||
| @@ -122,7 +133,7 @@ defmodule Cannery.ContainersTest do | |||||||
|       assert container.type == "some updated type" |       assert container.type == "some updated type" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "update_container/2 with invalid data returns error changeset", |     test "update_container/3 with invalid data returns error changeset", | ||||||
|          %{current_user: current_user, container: container} do |          %{current_user: current_user, container: container} do | ||||||
|       assert {:error, %Changeset{}} = |       assert {:error, %Changeset{}} = | ||||||
|                Containers.update_container(container, current_user, @invalid_attrs) |                Containers.update_container(container, current_user, @invalid_attrs) | ||||||
| @@ -130,11 +141,11 @@ defmodule Cannery.ContainersTest do | |||||||
|       assert container == Containers.get_container!(container.id, current_user) |       assert container == Containers.get_container!(container.id, current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "delete_container/1 deletes the container", |     test "delete_container/2 deletes the container", | ||||||
|          %{current_user: current_user, container: container} do |          %{current_user: current_user, container: container} do | ||||||
|       assert {:ok, %Container{}} = Containers.delete_container(container, current_user) |       assert {:ok, %Container{}} = Containers.delete_container(container, current_user) | ||||||
|  |  | ||||||
|       assert_raise Ecto.NoResultsError, fn -> |       assert_raise KeyError, fn -> | ||||||
|         Containers.get_container!(container.id, current_user) |         Containers.get_container!(container.id, current_user) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| @@ -151,15 +162,10 @@ defmodule Cannery.ContainersTest do | |||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "list_tags/2 returns relevant tags for a user", %{current_user: current_user} do |     test "list_tags/2 returns relevant tags for a user", %{current_user: current_user} do | ||||||
|       tag_a = tag_fixture(%{"name" => "bullets"}, current_user) |       tag_a = tag_fixture(%{name: "bullets"}, current_user) | ||||||
|       tag_b = tag_fixture(%{"name" => "hollows"}, current_user) |       tag_b = tag_fixture(%{name: "hollows"}, current_user) | ||||||
|  |  | ||||||
|       _shouldnt_return = |       tag_fixture(%{name: "bullet", desc: "pews brass shell"}, user_fixture()) | ||||||
|         %{ |  | ||||||
|           "name" => "bullet", |  | ||||||
|           "desc" => "pews brass shell" |  | ||||||
|         } |  | ||||||
|         |> tag_fixture(user_fixture()) |  | ||||||
|  |  | ||||||
|       # name |       # name | ||||||
|       assert Containers.list_tags("bullet", current_user) == [tag_a] |       assert Containers.list_tags("bullet", current_user) == [tag_a] | ||||||
| @@ -168,36 +174,36 @@ defmodule Cannery.ContainersTest do | |||||||
|       assert Containers.list_tags("hollows", current_user) == [tag_b] |       assert Containers.list_tags("hollows", current_user) == [tag_b] | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "get_tag!/1 returns the tag with given id", %{tag: tag, current_user: current_user} do |     test "get_tag!/2 returns the tag with given id", %{tag: tag, current_user: current_user} do | ||||||
|       assert Containers.get_tag!(tag.id, current_user) == tag |       assert Containers.get_tag!(tag.id, current_user) == tag | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_tag/1 with valid data creates a tag", %{current_user: current_user} do |     test "create_tag/2 with valid data creates a tag", %{current_user: current_user} do | ||||||
|       assert {:ok, %Tag{} = tag} = Containers.create_tag(@valid_tag_attrs, current_user) |       assert {:ok, %Tag{} = tag} = Containers.create_tag(@valid_tag_attrs, current_user) | ||||||
|       assert tag.bg_color == "some bg-color" |       assert tag.bg_color == "#100000" | ||||||
|       assert tag.name == "some name" |       assert tag.name == "some name" | ||||||
|       assert tag.text_color == "some text-color" |       assert tag.text_color == "#000000" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "create_tag/1 with invalid data returns error changeset", |     test "create_tag/2 with invalid data returns error changeset", | ||||||
|          %{current_user: current_user} do |          %{current_user: current_user} do | ||||||
|       assert {:error, %Changeset{}} = Containers.create_tag(@invalid_tag_attrs, current_user) |       assert {:error, %Changeset{}} = Containers.create_tag(@invalid_tag_attrs, current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "update_tag/2 with valid data updates the tag", %{tag: tag, current_user: current_user} do |     test "update_tag/3 with valid data updates the tag", %{tag: tag, current_user: current_user} do | ||||||
|       assert {:ok, %Tag{} = tag} = Containers.update_tag(tag, @update_tag_attrs, current_user) |       assert {:ok, %Tag{} = tag} = Containers.update_tag(tag, @update_tag_attrs, current_user) | ||||||
|       assert tag.bg_color == "some updated bg-color" |       assert tag.bg_color == "#100001" | ||||||
|       assert tag.name == "some updated name" |       assert tag.name == "some updated name" | ||||||
|       assert tag.text_color == "some updated text-color" |       assert tag.text_color == "#000001" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "update_tag/2 with invalid data returns error changeset", |     test "update_tag/3 with invalid data returns error changeset", | ||||||
|          %{tag: tag, current_user: current_user} do |          %{tag: tag, current_user: current_user} do | ||||||
|       assert {:error, %Changeset{}} = Containers.update_tag(tag, @invalid_tag_attrs, current_user) |       assert {:error, %Changeset{}} = Containers.update_tag(tag, @invalid_tag_attrs, current_user) | ||||||
|       assert tag == Containers.get_tag!(tag.id, current_user) |       assert tag == Containers.get_tag!(tag.id, current_user) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "delete_tag/1 deletes the tag", %{tag: tag, current_user: current_user} do |     test "delete_tag/2 deletes the tag", %{tag: tag, current_user: current_user} do | ||||||
|       assert {:ok, %Tag{}} = Containers.delete_tag(tag, current_user) |       assert {:ok, %Tag{}} = Containers.delete_tag(tag, current_user) | ||||||
|       assert_raise Ecto.NoResultsError, fn -> Containers.get_tag!(tag.id, current_user) end |       assert_raise Ecto.NoResultsError, fn -> Containers.get_tag!(tag.id, current_user) end | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserAuthTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.Accounts |   alias Cannery.Accounts | ||||||
|   alias CanneryWeb.UserAuth |   alias CanneryWeb.UserAuth | ||||||
|  |  | ||||||
| @@ -148,7 +147,7 @@ defmodule CanneryWeb.UserAuthTest do | |||||||
|       assert redirected_to(conn) == Routes.user_session_path(conn, :new) |       assert redirected_to(conn) == Routes.user_session_path(conn, :new) | ||||||
|  |  | ||||||
|       assert get_flash(conn, :error) == |       assert get_flash(conn, :error) == | ||||||
|                dgettext("errors", "You must confirm your account and log in to access this page.") |                "You must confirm your account and log in to access this page." | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "stores the path to redirect to on GET", %{conn: conn} do |     test "stores the path to redirect to on GET", %{conn: conn} do | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.{Accounts, Repo} |   alias Cannery.{Accounts, Repo} | ||||||
|  |  | ||||||
|   @moduletag :user_confirmation_controller_test |   @moduletag :user_confirmation_controller_test | ||||||
| @@ -17,7 +16,7 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|     test "renders the confirmation page", %{conn: conn} do |     test "renders the confirmation page", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_confirmation_path(conn, :new)) |       conn = get(conn, Routes.user_confirmation_path(conn, :new)) | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ dgettext("actions", "Resend confirmation instructions") |       assert response =~ "Resend confirmation instructions" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -25,18 +24,12 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|     @tag :capture_log |     @tag :capture_log | ||||||
|     test "sends a new confirmation token", %{conn: conn, user: user} do |     test "sends a new confirmation token", %{conn: conn, user: user} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_confirmation_path(conn, :create), %{ |         post(conn, Routes.user_confirmation_path(conn, :create), %{user: %{email: user.email}}) | ||||||
|           "user" => %{"email" => user.email} |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |                "If your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." | ||||||
|                  "prompts", |  | ||||||
|                  "If your email is in our system and it has not been confirmed yet, " <> |  | ||||||
|                    "you will receive an email with instructions shortly." |  | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert Repo.get_by!(Accounts.UserToken, user_id: user.id).context == "confirm" |       assert Repo.get_by!(Accounts.UserToken, user_id: user.id).context == "confirm" | ||||||
|     end |     end | ||||||
| @@ -45,34 +38,24 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|       Repo.update!(Accounts.User.confirm_changeset(user)) |       Repo.update!(Accounts.User.confirm_changeset(user)) | ||||||
|  |  | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_confirmation_path(conn, :create), %{ |         post(conn, Routes.user_confirmation_path(conn, :create), %{user: %{email: user.email}}) | ||||||
|           "user" => %{"email" => user.email} |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |                "If your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." | ||||||
|                  "prompts", |  | ||||||
|                  "If your email is in our system and it has not been confirmed yet, " <> |  | ||||||
|                    "you will receive an email with instructions shortly." |  | ||||||
|                ) |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not send confirmation token if email is invalid", %{conn: conn} do |     test "does not send confirmation token if email is invalid", %{conn: conn} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_confirmation_path(conn, :create), %{ |         post(conn, Routes.user_confirmation_path(conn, :create), %{ | ||||||
|           "user" => %{"email" => "unknown@example.com"} |           user: %{email: "unknown@example.com"} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |                "If your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." | ||||||
|                  "prompts", |  | ||||||
|                  "If your email is in our system and it has not been confirmed yet, " <> |  | ||||||
|                    "you will receive an email with instructions shortly." |  | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert Repo.all(Accounts.UserToken) == [] |       assert Repo.all(Accounts.UserToken) == [] | ||||||
|     end |     end | ||||||
| @@ -87,10 +70,7 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|  |  | ||||||
|       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, token)) |       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, token)) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |       assert get_flash(conn, :info) =~ "#{user.email} confirmed successfully" | ||||||
|       assert get_flash(conn, :info) =~ |  | ||||||
|                dgettext("prompts", "%{email} confirmed successfully", email: user.email) |  | ||||||
|  |  | ||||||
|       assert Accounts.get_user!(user.id).confirmed_at |       assert Accounts.get_user!(user.id).confirmed_at | ||||||
|       refute get_session(conn, :user_token) |       refute get_session(conn, :user_token) | ||||||
|       assert Repo.all(Accounts.UserToken) == [] |       assert Repo.all(Accounts.UserToken) == [] | ||||||
| @@ -99,8 +79,7 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, token)) |       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, token)) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :error) =~ |       assert get_flash(conn, :error) =~ "User confirmation link is invalid or it has expired" | ||||||
|                dgettext("errors", "User confirmation link is invalid or it has expired") |  | ||||||
|  |  | ||||||
|       # When logged in |       # When logged in | ||||||
|       conn = |       conn = | ||||||
| @@ -115,10 +94,7 @@ defmodule CanneryWeb.UserConfirmationControllerTest do | |||||||
|     test "does not confirm email with invalid token", %{conn: conn, user: user} do |     test "does not confirm email with invalid token", %{conn: conn, user: user} do | ||||||
|       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, "oops")) |       conn = get(conn, Routes.user_confirmation_path(conn, :confirm, "oops")) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |       assert get_flash(conn, :error) =~ "User confirmation link is invalid or it has expired" | ||||||
|       assert get_flash(conn, :error) =~ |  | ||||||
|                dgettext("errors", "User confirmation link is invalid or it has expired") |  | ||||||
|  |  | ||||||
|       refute Accounts.get_user!(user.id).confirmed_at |       refute Accounts.get_user!(user.id).confirmed_at | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserRegistrationControllerTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|  |  | ||||||
|   @moduletag :user_registration_controller_test |   @moduletag :user_registration_controller_test | ||||||
|  |  | ||||||
| @@ -12,8 +11,8 @@ defmodule CanneryWeb.UserRegistrationControllerTest do | |||||||
|     test "renders registration page", %{conn: conn} do |     test "renders registration page", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_registration_path(conn, :new)) |       conn = get(conn, Routes.user_registration_path(conn, :new)) | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ dgettext("actions", "Register") |       assert response =~ "Register" | ||||||
|       assert response =~ dgettext("actions", "Log in") |       assert response =~ "Log in" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "redirects if already logged in", %{conn: conn} do |     test "redirects if already logged in", %{conn: conn} do | ||||||
| @@ -29,11 +28,11 @@ defmodule CanneryWeb.UserRegistrationControllerTest do | |||||||
|  |  | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_registration_path(conn, :create), %{ |         post(conn, Routes.user_registration_path(conn, :create), %{ | ||||||
|           "user" => valid_user_attributes(email: email) |           user: valid_user_attributes(email: email) | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert get_session(conn, :phoenix_flash) == %{ |       assert get_session(conn, :phoenix_flash) == %{ | ||||||
|                "info" => dgettext("prompts", "Please check your email to verify your account") |                "info" => "Please check your email to verify your account" | ||||||
|              } |              } | ||||||
|  |  | ||||||
|       assert redirected_to(conn) =~ "/" |       assert redirected_to(conn) =~ "/" | ||||||
| @@ -48,11 +47,11 @@ defmodule CanneryWeb.UserRegistrationControllerTest do | |||||||
|     test "render errors for invalid data", %{conn: conn} do |     test "render errors for invalid data", %{conn: conn} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_registration_path(conn, :create), %{ |         post(conn, Routes.user_registration_path(conn, :create), %{ | ||||||
|           "user" => %{"email" => "with spaces", "password" => "too short"} |           user: %{email: "with spaces", password: "too short"} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ gettext("Register") |       assert response =~ "Register" | ||||||
|       assert response =~ "must have the @ sign and no spaces" |       assert response =~ "must have the @ sign and no spaces" | ||||||
|       assert response =~ "should be at least 12 character" |       assert response =~ "should be at least 12 character" | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.{Accounts, Repo} |   alias Cannery.{Accounts, Repo} | ||||||
|  |  | ||||||
|   @moduletag :user_reset_password_controller_test |   @moduletag :user_reset_password_controller_test | ||||||
| @@ -17,7 +16,7 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|     test "renders the reset password page", %{conn: conn} do |     test "renders the reset password page", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_reset_password_path(conn, :new)) |       conn = get(conn, Routes.user_reset_password_path(conn, :new)) | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ dgettext("actions", "Forgot your password?") |       assert response =~ "Forgot your password?" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -25,17 +24,12 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|     @tag :capture_log |     @tag :capture_log | ||||||
|     test "sends a new reset password token", %{conn: conn, user: user} do |     test "sends a new reset password token", %{conn: conn, user: user} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_reset_password_path(conn, :create), %{ |         post(conn, Routes.user_reset_password_path(conn, :create), %{user: %{email: user.email}}) | ||||||
|           "user" => %{"email" => user.email} |  | ||||||
|         }) |  | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |  | ||||||
|                  "prompts", |  | ||||||
|                "If your email is in our system, you will receive instructions to reset your password shortly." |                "If your email is in our system, you will receive instructions to reset your password shortly." | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert Repo.get_by!(Accounts.UserToken, user_id: user.id).context == "reset_password" |       assert Repo.get_by!(Accounts.UserToken, user_id: user.id).context == "reset_password" | ||||||
|     end |     end | ||||||
| @@ -43,16 +37,13 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|     test "does not send reset password token if email is invalid", %{conn: conn} do |     test "does not send reset password token if email is invalid", %{conn: conn} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_reset_password_path(conn, :create), %{ |         post(conn, Routes.user_reset_password_path(conn, :create), %{ | ||||||
|           "user" => %{"email" => "unknown@example.com"} |           user: %{email: "unknown@example.com"} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |  | ||||||
|                  "prompts", |  | ||||||
|                "If your email is in our system, you will receive instructions to reset your password shortly." |                "If your email is in our system, you will receive instructions to reset your password shortly." | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert Repo.all(Accounts.UserToken) == [] |       assert Repo.all(Accounts.UserToken) == [] | ||||||
|     end |     end | ||||||
| @@ -70,15 +61,13 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|  |  | ||||||
|     test "renders reset password", %{conn: conn, token: token} do |     test "renders reset password", %{conn: conn, token: token} do | ||||||
|       conn = get(conn, Routes.user_reset_password_path(conn, :edit, token)) |       conn = get(conn, Routes.user_reset_password_path(conn, :edit, token)) | ||||||
|       assert html_response(conn, 200) =~ dgettext("actions", "Reset password") |       assert html_response(conn, 200) =~ "Reset password" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not render reset password with invalid token", %{conn: conn} do |     test "does not render reset password with invalid token", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_reset_password_path(conn, :edit, "oops")) |       conn = get(conn, Routes.user_reset_password_path(conn, :edit, "oops")) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |       assert get_flash(conn, :error) =~ "Reset password link is invalid or it has expired" | ||||||
|       assert get_flash(conn, :error) =~ |  | ||||||
|                dgettext("errors", "Reset password link is invalid or it has expired") |  | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -95,39 +84,37 @@ defmodule CanneryWeb.UserResetPasswordControllerTest do | |||||||
|     test "resets password once", %{conn: conn, user: user, token: token} do |     test "resets password once", %{conn: conn, user: user, token: token} do | ||||||
|       conn = |       conn = | ||||||
|         put(conn, Routes.user_reset_password_path(conn, :update, token), %{ |         put(conn, Routes.user_reset_password_path(conn, :update, token), %{ | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "password" => "new valid password", |             password: "new valid password", | ||||||
|             "password_confirmation" => "new valid password" |             password_confirmation: "new valid password" | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == Routes.user_session_path(conn, :new) |       assert redirected_to(conn) == Routes.user_session_path(conn, :new) | ||||||
|       refute get_session(conn, :user_token) |       refute get_session(conn, :user_token) | ||||||
|       assert get_flash(conn, :info) =~ dgettext("prompts", "Password reset successfully") |       assert get_flash(conn, :info) =~ "Password reset successfully" | ||||||
|       assert Accounts.get_user_by_email_and_password(user.email, "new valid password") |       assert Accounts.get_user_by_email_and_password(user.email, "new valid password") | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not reset password on invalid data", %{conn: conn, token: token} do |     test "does not reset password on invalid data", %{conn: conn, token: token} do | ||||||
|       conn = |       conn = | ||||||
|         put(conn, Routes.user_reset_password_path(conn, :update, token), %{ |         put(conn, Routes.user_reset_password_path(conn, :update, token), %{ | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "password" => "too short", |             password: "too short", | ||||||
|             "password_confirmation" => "does not match" |             password_confirmation: "does not match" | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ gettext("Reset password") |       assert response =~ "Reset password" | ||||||
|       assert response =~ dgettext("errors", "should be at least 12 character(s)") |       assert response =~ "should be at least 12 character(s)" | ||||||
|       assert response =~ dgettext("errors", "does not match password") |       assert response =~ "does not match password" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not reset password with invalid token", %{conn: conn} do |     test "does not reset password with invalid token", %{conn: conn} do | ||||||
|       conn = put(conn, Routes.user_reset_password_path(conn, :update, "oops")) |       conn = put(conn, Routes.user_reset_password_path(conn, :update, "oops")) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|  |       assert get_flash(conn, :error) =~ "Reset password link is invalid or it has expired" | ||||||
|       assert get_flash(conn, :error) =~ |  | ||||||
|                dgettext("errors", "Reset password link is invalid or it has expired") |  | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|  |  | ||||||
|   @moduletag :user_session_controller_test |   @moduletag :user_session_controller_test | ||||||
|  |  | ||||||
| @@ -16,7 +15,7 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|     test "renders log in page", %{conn: conn} do |     test "renders log in page", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_session_path(conn, :new)) |       conn = get(conn, Routes.user_session_path(conn, :new)) | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ dgettext("actions", "Log in") |       assert response =~ "Log in" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "redirects if already logged in", %{conn: conn, current_user: current_user} do |     test "redirects if already logged in", %{conn: conn, current_user: current_user} do | ||||||
| @@ -29,7 +28,7 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|     test "logs the user in", %{conn: conn, current_user: current_user} do |     test "logs the user in", %{conn: conn, current_user: current_user} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_session_path(conn, :create), %{ |         post(conn, Routes.user_session_path(conn, :create), %{ | ||||||
|           "user" => %{"email" => current_user.email, "password" => valid_user_password()} |           user: %{email: current_user.email, password: valid_user_password()} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert get_session(conn, :user_token) |       assert get_session(conn, :user_token) | ||||||
| @@ -39,16 +38,16 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|       conn = get(conn, "/") |       conn = get(conn, "/") | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ current_user.email |       assert response =~ current_user.email | ||||||
|       assert response =~ dgettext("prompts", "Are you sure you want to log out?") |       assert response =~ "Are you sure you want to log out?" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "logs the user in with remember me", %{conn: conn, current_user: current_user} do |     test "logs the user in with remember me", %{conn: conn, current_user: current_user} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_session_path(conn, :create), %{ |         post(conn, Routes.user_session_path(conn, :create), %{ | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "email" => current_user.email, |             email: current_user.email, | ||||||
|             "password" => valid_user_password(), |             password: valid_user_password(), | ||||||
|             "remember_me" => "true" |             remember_me: "true" | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
| @@ -61,9 +60,9 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|         conn |         conn | ||||||
|         |> init_test_session(user_return_to: "/foo/bar") |         |> init_test_session(user_return_to: "/foo/bar") | ||||||
|         |> post(Routes.user_session_path(conn, :create), %{ |         |> post(Routes.user_session_path(conn, :create), %{ | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "email" => current_user.email, |             email: current_user.email, | ||||||
|             "password" => valid_user_password() |             password: valid_user_password() | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
| @@ -74,12 +73,12 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|          %{conn: conn, current_user: current_user} do |          %{conn: conn, current_user: current_user} do | ||||||
|       conn = |       conn = | ||||||
|         post(conn, Routes.user_session_path(conn, :create), %{ |         post(conn, Routes.user_session_path(conn, :create), %{ | ||||||
|           "user" => %{"email" => current_user.email, "password" => "bad"} |           user: %{email: current_user.email, password: "bad"} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ dgettext("actions", "Log in") |       assert response =~ "Log in" | ||||||
|       assert response =~ dgettext("errors", "Invalid email or password") |       assert response =~ "Invalid email or password" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -88,14 +87,14 @@ defmodule CanneryWeb.UserSessionControllerTest do | |||||||
|       conn = conn |> log_in_user(current_user) |> delete(Routes.user_session_path(conn, :delete)) |       conn = conn |> log_in_user(current_user) |> delete(Routes.user_session_path(conn, :delete)) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|       refute get_session(conn, :user_token) |       refute get_session(conn, :user_token) | ||||||
|       assert get_flash(conn, :info) =~ gettext("Logged out successfully") |       assert get_flash(conn, :info) =~ "Logged out successfully" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "succeeds even if the user is not logged in", %{conn: conn} do |     test "succeeds even if the user is not logged in", %{conn: conn} do | ||||||
|       conn = delete(conn, Routes.user_session_path(conn, :delete)) |       conn = delete(conn, Routes.user_session_path(conn, :delete)) | ||||||
|       assert redirected_to(conn) == "/" |       assert redirected_to(conn) == "/" | ||||||
|       refute get_session(conn, :user_token) |       refute get_session(conn, :user_token) | ||||||
|       assert get_flash(conn, :info) =~ gettext("Logged out successfully") |       assert get_flash(conn, :info) =~ "Logged out successfully" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.Accounts |   alias Cannery.Accounts | ||||||
|  |  | ||||||
|   @moduletag :user_settings_controller_test |   @moduletag :user_settings_controller_test | ||||||
| @@ -15,7 +14,7 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|     test "renders settings page", %{conn: conn} do |     test "renders settings page", %{conn: conn} do | ||||||
|       conn = get(conn, Routes.user_settings_path(conn, :edit)) |       conn = get(conn, Routes.user_settings_path(conn, :edit)) | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ gettext("Settings") |       assert response =~ "Settings" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "redirects if user is not logged in" do |     test "redirects if user is not logged in" do | ||||||
| @@ -30,40 +29,36 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|          %{conn: conn, current_user: current_user} do |          %{conn: conn, current_user: current_user} do | ||||||
|       new_password_conn = |       new_password_conn = | ||||||
|         put(conn, Routes.user_settings_path(conn, :update), %{ |         put(conn, Routes.user_settings_path(conn, :update), %{ | ||||||
|           "action" => "update_password", |           action: "update_password", | ||||||
|           "current_password" => valid_user_password(), |           current_password: valid_user_password(), | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "password" => "new valid password", |             password: "new valid password", | ||||||
|             "password_confirmation" => "new valid password" |             password_confirmation: "new valid password" | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert redirected_to(new_password_conn) == Routes.user_settings_path(conn, :edit) |       assert redirected_to(new_password_conn) == Routes.user_settings_path(conn, :edit) | ||||||
|       assert get_session(new_password_conn, :user_token) != get_session(conn, :user_token) |       assert get_session(new_password_conn, :user_token) != get_session(conn, :user_token) | ||||||
|  |       assert get_flash(new_password_conn, :info) =~ "Password updated successfully" | ||||||
|       assert get_flash(new_password_conn, :info) =~ |  | ||||||
|                dgettext("actions", "Password updated successfully") |  | ||||||
|  |  | ||||||
|       assert Accounts.get_user_by_email_and_password(current_user.email, "new valid password") |       assert Accounts.get_user_by_email_and_password(current_user.email, "new valid password") | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not update password on invalid data", %{conn: conn} do |     test "does not update password on invalid data", %{conn: conn} do | ||||||
|       old_password_conn = |       old_password_conn = | ||||||
|         put(conn, Routes.user_settings_path(conn, :update), %{ |         put(conn, Routes.user_settings_path(conn, :update), %{ | ||||||
|           "action" => "update_password", |           action: "update_password", | ||||||
|           "current_password" => "invalid", |           current_password: "invalid", | ||||||
|           "user" => %{ |           user: %{ | ||||||
|             "password" => "too short", |             password: "too short", | ||||||
|             "password_confirmation" => "does not match" |             password_confirmation: "does not match" | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       response = html_response(old_password_conn, 200) |       response = html_response(old_password_conn, 200) | ||||||
|       assert response =~ gettext("Settings") |       assert response =~ "Settings" | ||||||
|       assert response =~ dgettext("errors", "should be at least 12 character(s)") |       assert response =~ "should be at least 12 character(s)" | ||||||
|       assert response =~ dgettext("errors", "does not match password") |       assert response =~ "does not match password" | ||||||
|       assert response =~ dgettext("errors", "is not valid") |       assert response =~ "is not valid" | ||||||
|  |  | ||||||
|       assert get_session(old_password_conn, :user_token) == get_session(conn, :user_token) |       assert get_session(old_password_conn, :user_token) == get_session(conn, :user_token) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| @@ -73,18 +68,15 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|     test "updates the user email", %{conn: conn, current_user: current_user} do |     test "updates the user email", %{conn: conn, current_user: current_user} do | ||||||
|       conn = |       conn = | ||||||
|         put(conn, Routes.user_settings_path(conn, :update), %{ |         put(conn, Routes.user_settings_path(conn, :update), %{ | ||||||
|           "action" => "update_email", |           action: "update_email", | ||||||
|           "current_password" => valid_user_password(), |           current_password: valid_user_password(), | ||||||
|           "user" => %{"email" => unique_user_email()} |           user: %{email: unique_user_email()} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) |       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) | ||||||
|  |  | ||||||
|       assert get_flash(conn, :info) =~ |       assert get_flash(conn, :info) =~ | ||||||
|                dgettext( |  | ||||||
|                  "prompts", |  | ||||||
|                "A link to confirm your email change has been sent to the new address." |                "A link to confirm your email change has been sent to the new address." | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert Accounts.get_user_by_email(current_user.email) |       assert Accounts.get_user_by_email(current_user.email) | ||||||
|     end |     end | ||||||
| @@ -92,15 +84,15 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|     test "does not update email on invalid data", %{conn: conn} do |     test "does not update email on invalid data", %{conn: conn} do | ||||||
|       conn = |       conn = | ||||||
|         put(conn, Routes.user_settings_path(conn, :update), %{ |         put(conn, Routes.user_settings_path(conn, :update), %{ | ||||||
|           "action" => "update_email", |           action: "update_email", | ||||||
|           "current_password" => "invalid", |           current_password: "invalid", | ||||||
|           "user" => %{"email" => "with spaces"} |           user: %{email: "with spaces"} | ||||||
|         }) |         }) | ||||||
|  |  | ||||||
|       response = html_response(conn, 200) |       response = html_response(conn, 200) | ||||||
|       assert response =~ gettext("Settings") |       assert response =~ "Settings" | ||||||
|       assert response =~ dgettext("errors", "must have the @ sign and no spaces") |       assert response =~ "must have the @ sign and no spaces" | ||||||
|       assert response =~ dgettext("errors", "is not valid") |       assert response =~ "is not valid" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -124,24 +116,19 @@ defmodule CanneryWeb.UserSettingsControllerTest do | |||||||
|          %{conn: conn, current_user: current_user, token: token, email: email} do |          %{conn: conn, current_user: current_user, token: token, email: email} do | ||||||
|       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) |       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) | ||||||
|       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) |       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) | ||||||
|       assert get_flash(conn, :info) =~ dgettext("prompts", "Email changed successfully") |       assert get_flash(conn, :info) =~ "Email changed successfully" | ||||||
|       refute Accounts.get_user_by_email(current_user.email) |       refute Accounts.get_user_by_email(current_user.email) | ||||||
|       assert Accounts.get_user_by_email(email) |       assert Accounts.get_user_by_email(email) | ||||||
|  |  | ||||||
|       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) |       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) | ||||||
|       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) |       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) | ||||||
|  |       assert get_flash(conn, :error) =~ "Email change link is invalid or it has expired" | ||||||
|       assert get_flash(conn, :error) =~ |  | ||||||
|                dgettext("errors", "Email change link is invalid or it has expired") |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not update email with invalid token", %{conn: conn, current_user: current_user} do |     test "does not update email with invalid token", %{conn: conn, current_user: current_user} do | ||||||
|       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, "oops")) |       conn = get(conn, Routes.user_settings_path(conn, :confirm_email, "oops")) | ||||||
|       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) |       assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) | ||||||
|  |       assert get_flash(conn, :error) =~ "Email change link is invalid or it has expired" | ||||||
|       assert get_flash(conn, :error) =~ |  | ||||||
|                dgettext("errors", "Email change link is invalid or it has expired") |  | ||||||
|  |  | ||||||
|       assert Accounts.get_user_by_email(current_user.email) |       assert Accounts.get_user_by_email(current_user.email) | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,43 +5,40 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.{Ammo, Repo} |   alias Cannery.{Ammo, Repo} | ||||||
|  |  | ||||||
|   @moduletag :ammo_group_live_test |   @moduletag :ammo_group_live_test | ||||||
|   @shot_group_create_attrs %{"ammo_left" => 5, "notes" => "some notes"} |   @create_attrs %{count: 42, notes: "some notes", price_paid: 120.5} | ||||||
|   @shot_group_update_attrs %{ |   @update_attrs %{count: 43, notes: "some updated notes", price_paid: 456.7} | ||||||
|     "count" => 5, |   @invalid_attrs %{count: nil, notes: nil, price_paid: nil} | ||||||
|     "date" => ~N[2022-02-13 03:17:00], |  | ||||||
|     "notes" => "some updated notes" |  | ||||||
|   } |  | ||||||
|   @create_attrs %{"count" => 42, "notes" => "some notes", "price_paid" => 120.5} |  | ||||||
|   @update_attrs %{"count" => 43, "notes" => "some updated notes", "price_paid" => 456.7} |  | ||||||
|   @ammo_group_create_limit 10_000 |   @ammo_group_create_limit 10_000 | ||||||
|  |   @shot_group_create_attrs %{ammo_left: 5, notes: "some notes"} | ||||||
|  |   @shot_group_update_attrs %{ | ||||||
|  |     count: 5, | ||||||
|  |     date: ~N[2022-02-13 03:17:00], | ||||||
|  |     notes: "some updated notes" | ||||||
|  |   } | ||||||
|  |   @shot_group_invalid_attrs %{ammo_left: nil, count: nil, notes: nil} | ||||||
|   @empty_attrs %{ |   @empty_attrs %{ | ||||||
|     "price_paid" => 50, |     price_paid: 50, | ||||||
|     "count" => 20 |     count: 20 | ||||||
|   } |   } | ||||||
|   @shot_group_attrs %{ |   @shot_group_attrs %{ | ||||||
|     "price_paid" => 50, |     price_paid: 50, | ||||||
|     "count" => 20 |     count: 20 | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   # @invalid_attrs %{count: -1, notes: nil, price_paid: nil} |  | ||||||
|  |  | ||||||
|   defp create_ammo_group(%{current_user: current_user}) do |   defp create_ammo_group(%{current_user: current_user}) do | ||||||
|     ammo_type = ammo_type_fixture(current_user) |     ammo_type = ammo_type_fixture(current_user) | ||||||
|     container = container_fixture(current_user) |     container = container_fixture(current_user) | ||||||
|     {1, [ammo_group]} = ammo_group_fixture(@create_attrs, ammo_type, container, current_user) |     {1, [ammo_group]} = ammo_group_fixture(@create_attrs, ammo_type, container, current_user) | ||||||
|  |     [ammo_type: ammo_type, ammo_group: ammo_group, container: container] | ||||||
|     %{ammo_type: ammo_type, ammo_group: ammo_group, container: container} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp create_shot_group(%{current_user: current_user, ammo_group: ammo_group}) do |   defp create_shot_group(%{current_user: current_user, ammo_group: ammo_group}) do | ||||||
|     shot_group = shot_group_fixture(@shot_group_update_attrs, current_user, ammo_group) |     shot_group = shot_group_fixture(@shot_group_update_attrs, current_user, ammo_group) | ||||||
|     ammo_group = ammo_group |> Repo.reload!() |     ammo_group = ammo_group |> Repo.reload!() | ||||||
|  |     [ammo_group: ammo_group, shot_group: shot_group] | ||||||
|     %{ammo_group: ammo_group, shot_group: shot_group} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp create_empty_ammo_group(%{ |   defp create_empty_ammo_group(%{ | ||||||
| @@ -52,7 +49,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|     {1, [ammo_group]} = ammo_group_fixture(@empty_attrs, ammo_type, container, current_user) |     {1, [ammo_group]} = ammo_group_fixture(@empty_attrs, ammo_type, container, current_user) | ||||||
|     shot_group = shot_group_fixture(@shot_group_attrs, current_user, ammo_group) |     shot_group = shot_group_fixture(@shot_group_attrs, current_user, ammo_group) | ||||||
|     ammo_group = ammo_group |> Repo.reload!() |     ammo_group = ammo_group |> Repo.reload!() | ||||||
|     %{empty_ammo_group: ammo_group, shot_group: shot_group} |     [empty_ammo_group: ammo_group, shot_group: shot_group] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "Index of ammo group" do |   describe "Index of ammo group" do | ||||||
| @@ -60,12 +57,65 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|     test "lists all ammo_groups", %{conn: conn, ammo_group: ammo_group} do |     test "lists all ammo_groups", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       ammo_group = ammo_group |> Repo.preload(:ammo_type) |       ammo_group = ammo_group |> Repo.preload(:ammo_type) | ||||||
|       assert html =~ gettext("Ammo") |       assert html =~ "Ammo" | ||||||
|       assert html =~ ammo_group.ammo_type.name |       assert html =~ ammo_group.ammo_type.name | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     test "can sort by type", | ||||||
|  |          %{conn: conn, container: container, current_user: current_user} do | ||||||
|  |       rifle_type = ammo_type_fixture(%{class: :rifle}, current_user) | ||||||
|  |       {1, [rifle_ammo_group]} = ammo_group_fixture(rifle_type, container, current_user) | ||||||
|  |       shotgun_type = ammo_type_fixture(%{class: :shotgun}, current_user) | ||||||
|  |       {1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_type, container, current_user) | ||||||
|  |       pistol_type = ammo_type_fixture(%{class: :pistol}, current_user) | ||||||
|  |       {1, [pistol_ammo_group]} = ammo_group_fixture(pistol_type, container, current_user) | ||||||
|  |  | ||||||
|  |       {:ok, index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|  |       assert html =~ "All" | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :rifle}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :shotgun}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :pistol}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :all}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |     end | ||||||
|  |  | ||||||
|     test "can search for ammo_groups", %{conn: conn, ammo_group: ammo_group} do |     test "can search for ammo_groups", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
| @@ -74,10 +124,9 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|       assert html =~ ammo_group.ammo_type.name |       assert html =~ ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, |              |> form(~s/form[phx-change="search"]/) | ||||||
|                search: %{search_term: ammo_group.ammo_type.name} |              |> render_change(search: %{search_term: ammo_group.ammo_type.name}) =~ | ||||||
|              ) |                ammo_group.ammo_type.name | ||||||
|              |> render_change() =~ ammo_group.ammo_type.name |  | ||||||
|  |  | ||||||
|       assert_patch( |       assert_patch( | ||||||
|         index_live, |         index_live, | ||||||
| @@ -85,14 +134,15 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|       ) |       ) | ||||||
|  |  | ||||||
|       refute index_live |       refute index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: "something_else"}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ ammo_group.ammo_type.name |              |> render_change(search: %{search_term: "something_else"}) =~ | ||||||
|  |                ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :search, "something_else")) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :search, "something_else")) | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: ""}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ ammo_group.ammo_type.name |              |> render_change(search: %{search_term: ""}) =~ ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :index)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :index)) | ||||||
|     end |     end | ||||||
| @@ -100,85 +150,65 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|     test "saves a single new ammo_group", %{conn: conn} do |     test "saves a single new ammo_group", %{conn: conn} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ |       assert index_live |> element("a", "Add Ammo") |> render_click() =~ "Add Ammo" | ||||||
|                dgettext("actions", "Add Ammo") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_group-form", ammo_group: @create_attrs) |         |> form("#ammo_group-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_group: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo added successfully") |       assert html =~ "Ammo added successfully" | ||||||
|       assert html =~ "42" |       assert html =~ "\n42\n" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "saves multiple new ammo_groups", %{conn: conn, current_user: current_user} do |     test "saves multiple new ammo_groups", %{conn: conn, current_user: current_user} do | ||||||
|       multiplier = 25 |       multiplier = 25 | ||||||
|  |  | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ |       assert index_live |> element("a", "Add Ammo") |> render_click() =~ "Add Ammo" | ||||||
|                dgettext("actions", "Add Ammo") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_group-form", |         |> form("#ammo_group-form") | ||||||
|           ammo_group: @create_attrs |> Map.put("multiplier", to_string(multiplier)) |         |> render_submit(ammo_group: @create_attrs |> Map.put(:multiplier, multiplier)) | ||||||
|         ) |  | ||||||
|         |> render_submit() |  | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo added successfully") |       assert html =~ "Ammo added successfully" | ||||||
|       assert Ammo.list_ammo_groups(nil, false, current_user) |> Enum.count() == multiplier + 1 |       assert Ammo.list_ammo_groups(nil, :all, current_user) |> Enum.count() == multiplier + 1 | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "does not save invalid number of new ammo_groups", %{conn: conn} do |     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)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Add Ammo")) |> render_click() =~ |       assert index_live |> element("a", "Add Ammo") |> render_click() =~ "Add Ammo" | ||||||
|                dgettext("actions", "Add Ammo") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form("#ammo_group-form", ammo_group: @create_attrs |> Map.put("multiplier", "0")) |              |> form("#ammo_group-form") | ||||||
|              |> render_submit() =~ |              |> render_submit(ammo_group: @create_attrs |> Map.put(:multiplier, "0")) =~ | ||||||
|                dgettext( |                "Invalid number of copies, must be between 1 and #{@ammo_group_create_limit}. Was 0" | ||||||
|                  "errors", |  | ||||||
|                  "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}", |  | ||||||
|                  multiplier: 0, |  | ||||||
|                  max: @ammo_group_create_limit |  | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form("#ammo_group-form", |              |> form("#ammo_group-form") | ||||||
|                ammo_group: |              |> render_submit( | ||||||
|                  @create_attrs |> Map.put("multiplier", to_string(@ammo_group_create_limit + 1)) |                ammo_group: @create_attrs |> Map.put(:multiplier, @ammo_group_create_limit + 1) | ||||||
|              ) |              ) =~ | ||||||
|              |> render_submit() =~ |                "Invalid number of copies, must be between 1 and #{@ammo_group_create_limit}. Was #{@ammo_group_create_limit + 1}" | ||||||
|                dgettext( |  | ||||||
|                  "errors", |  | ||||||
|                  "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}", |  | ||||||
|                  multiplier: @ammo_group_create_limit + 1, |  | ||||||
|                  max: @ammo_group_create_limit |  | ||||||
|                ) |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "updates ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do |     test "updates ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do | ||||||
| @@ -186,23 +216,22 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> element(~s/a[aria-label="Edit ammo group of #{ammo_group.count} bullets"]/) |              |> element(~s/a[aria-label="Edit ammo group of #{ammo_group.count} bullets"]/) | ||||||
|              |> render_click() =~ |              |> render_click() =~ "Edit ammo" | ||||||
|                gettext("Edit ammo") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :edit, ammo_group)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :edit, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_group-form", ammo_group: @update_attrs) |         |> form("#ammo_group-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_group: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo updated successfully") |       assert html =~ "Ammo updated successfully" | ||||||
|       assert html =~ "43" |       assert html =~ "\n43\n" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "clones ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do |     test "clones ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do | ||||||
| @@ -213,24 +242,38 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|         |> element(~s/a[aria-label="Clone ammo group of #{ammo_group.count} bullets"]/) |         |> element(~s/a[aria-label="Clone ammo group of #{ammo_group.count} bullets"]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Add Ammo") |       assert html =~ "Add Ammo" | ||||||
|       assert html =~ gettext("$%{amount}", amount: display_currency(120.5)) |       assert html =~ "$#{display_currency(120.5)}" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :clone, ammo_group)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :clone, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       {:ok, _index_live, html} = | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |  | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |  | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |  | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_group-form") |         |> form("#ammo_group-form") | ||||||
|         |> render_submit() |         |> render_submit() | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo added successfully") |       assert html =~ "Ammo added successfully" | ||||||
|       assert html =~ "42" |       assert html =~ "\n42\n" | ||||||
|       assert html =~ gettext("$%{amount}", amount: display_currency(120.5)) |       assert html =~ "$#{display_currency(120.5)}" | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     test "checks validity when cloning", %{conn: conn, ammo_group: ammo_group} do | ||||||
|  |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> element(~s/a[aria-label="Clone ammo group of #{ammo_group.count} bullets"]/) | ||||||
|  |         |> render_click() | ||||||
|  |  | ||||||
|  |       assert html =~ "Add Ammo" | ||||||
|  |       assert html =~ "$#{display_currency(120.5)}" | ||||||
|  |  | ||||||
|  |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :clone, ammo_group)) | ||||||
|  |  | ||||||
|  |       assert index_live | ||||||
|  |              |> form("#ammo_group-form") | ||||||
|  |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "clones ammo_group in listing with updates", %{conn: conn, ammo_group: ammo_group} do |     test "clones ammo_group in listing with updates", %{conn: conn, ammo_group: ammo_group} do | ||||||
| @@ -241,24 +284,23 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|         |> element(~s/a[aria-label="Clone ammo group of #{ammo_group.count} bullets"]/) |         |> element(~s/a[aria-label="Clone ammo group of #{ammo_group.count} bullets"]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Add Ammo") |       assert html =~ "Add Ammo" | ||||||
|       assert html =~ gettext("$%{amount}", amount: display_currency(120.5)) |       assert html =~ "$#{display_currency(120.5)}" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :clone, ammo_group)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :clone, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_group-form", ammo_group: Map.merge(@create_attrs, %{"count" => 43})) |         |> form("#ammo_group-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_group: @create_attrs |> Map.put(:count, 43)) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo added successfully") |       assert html =~ "Ammo added successfully" | ||||||
|       assert html =~ "43" |       assert html =~ "\n43\n" | ||||||
|       assert html =~ gettext("$%{amount}", amount: display_currency(120.5)) |       assert html =~ "$#{display_currency(120.5)}" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "deletes ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do |     test "deletes ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do | ||||||
| @@ -274,22 +316,20 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do |     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Record shots")) |> render_click() =~ |       assert index_live |> element("a", "Record shots") |> render_click() =~ "Record shots" | ||||||
|                gettext("Record shots") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_index_path(conn, :add_shot_group, ammo_group)) |       assert_patch(index_live, Routes.ammo_group_index_path(conn, :add_shot_group, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#shot_group-form", shot_group: @invalid_attrs) |              |> form("#shot-group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "is invalid") |              |> render_change(shot_group: @shot_group_invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#shot-group-form", shot_group: @shot_group_create_attrs) |         |> form("#shot-group-form") | ||||||
|         |> render_submit() |         |> render_submit(shot_group: @shot_group_create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Shots recorded successfully") |       assert html =~ "Shots recorded successfully" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     @spec display_currency(float()) :: String.t() |     @spec display_currency(float()) :: String.t() | ||||||
| @@ -306,29 +346,20 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|     } do |     } do | ||||||
|       {:ok, show_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) |       {:ok, show_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Show used") |       assert html =~ "Show used" | ||||||
|       refute html =~ gettext("$%{amount}", amount: display_currency(50.00)) |       refute html =~ "$#{display_currency(50.00)}" | ||||||
|  |  | ||||||
|       refute html =~ |       percentage = ammo_group |> Ammo.get_percentage_remaining(current_user) | ||||||
|                "\n" <> |       refute html =~ "\n#{"#{percentage}%"}\n" | ||||||
|                  gettext("%{percentage}%", |  | ||||||
|                    percentage: ammo_group |> Ammo.get_percentage_remaining(current_user) |  | ||||||
|                  ) <> |  | ||||||
|                  "\n" |  | ||||||
|  |  | ||||||
|       html = |       html = | ||||||
|         show_live |         show_live | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ gettext("$%{amount}", amount: display_currency(50.00)) |       assert html =~ "$#{display_currency(50.00)}" | ||||||
|  |       percentage = ammo_group |> Ammo.get_percentage_remaining(current_user) | ||||||
|       assert html =~ |       assert html =~ "\n#{"#{percentage}%"}\n" | ||||||
|                "\n" <> |  | ||||||
|                  gettext("%{percentage}%", |  | ||||||
|                    percentage: ammo_group |> Ammo.get_percentage_remaining(current_user) |  | ||||||
|                  ) <> |  | ||||||
|                  "\n" |  | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -337,9 +368,8 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|     test "displays ammo_group", %{conn: conn, ammo_group: ammo_group} do |     test "displays ammo_group", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, _show_live, html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) |       {:ok, _show_live, html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) | ||||||
|  |  | ||||||
|       ammo_group = ammo_group |> Repo.preload(:ammo_type) |       ammo_group = ammo_group |> Repo.preload(:ammo_type) | ||||||
|       assert html =~ gettext("Show Ammo") |       assert html =~ "Show Ammo" | ||||||
|       assert html =~ ammo_group.ammo_type.name |       assert html =~ ammo_group.ammo_type.name | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -348,44 +378,41 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|       assert show_live |       assert show_live | ||||||
|              |> element(~s/a[aria-label="Edit ammo group of #{ammo_group.count} bullets"]/) |              |> element(~s/a[aria-label="Edit ammo group of #{ammo_group.count} bullets"]/) | ||||||
|              |> render_click() =~ |              |> render_click() =~ "Edit Ammo" | ||||||
|                gettext("Edit Ammo") |  | ||||||
|  |  | ||||||
|       assert_patch(show_live, Routes.ammo_group_show_path(conn, :edit, ammo_group)) |       assert_patch(show_live, Routes.ammo_group_show_path(conn, :edit, ammo_group)) | ||||||
|  |  | ||||||
|       # assert show_live |       assert show_live | ||||||
|       #        |> form("#ammo_group-form", ammo_group: @invalid_attrs) |              |> form("#ammo_group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         show_live |         show_live | ||||||
|         |> form("#ammo_group-form", ammo_group: @update_attrs) |         |> form("#ammo_group-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_group: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) |         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Ammo updated successfully") |       assert html =~ "Ammo updated successfully" | ||||||
|       assert html =~ "some updated notes" |       assert html =~ "some updated notes" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do |     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Record shots")) |> render_click() =~ |       assert index_live |> element("a", "Record shots") |> render_click() =~ "Record shots" | ||||||
|                gettext("Record shots") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_group_show_path(conn, :add_shot_group, ammo_group)) |       assert_patch(index_live, Routes.ammo_group_show_path(conn, :add_shot_group, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#shot_group-form", shot_group: @invalid_attrs) |              |> form("#shot-group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "is invalid") |              |> render_change(shot_group: @shot_group_invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#shot-group-form", shot_group: @shot_group_create_attrs) |         |> form("#shot-group-form") | ||||||
|         |> render_submit() |         |> render_submit(shot_group: @shot_group_create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) |         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Shots recorded successfully") |       assert html =~ "Shots recorded successfully" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -398,25 +425,24 @@ defmodule CanneryWeb.AmmoGroupLiveTest do | |||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> element(~s/a[aria-label="Edit shot group of #{shot_group.count} shots"]/) |              |> element(~s/a[aria-label="Edit shot group of #{shot_group.count} shots"]/) | ||||||
|              |> render_click() =~ |              |> render_click() =~ "Edit Shot Records" | ||||||
|                gettext("Edit Shot Records") |  | ||||||
|  |  | ||||||
|       assert_patch( |       assert_patch( | ||||||
|         index_live, |         index_live, | ||||||
|         Routes.ammo_group_show_path(conn, :edit_shot_group, ammo_group, shot_group) |         Routes.ammo_group_show_path(conn, :edit_shot_group, ammo_group, shot_group) | ||||||
|       ) |       ) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#shot_group-form", shot_group: @invalid_attrs) |              |> form("#shot-group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "is invalid") |              |> render_change(shot_group: @shot_group_invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#shot-group-form", shot_group: @shot_group_update_attrs) |         |> form("#shot-group-form") | ||||||
|         |> render_submit() |         |> render_submit(shot_group: @shot_group_update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) |         |> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Shot records updated successfully") |       assert html =~ "Shot records updated successfully" | ||||||
|       assert html =~ "some updated notes" |       assert html =~ "some updated notes" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,54 +5,51 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.{Ammo, Repo} |   alias Cannery.{Ammo, Repo} | ||||||
|  |  | ||||||
|   @moduletag :ammo_type_live_test |   @moduletag :ammo_type_live_test | ||||||
|  |  | ||||||
|   @create_attrs %{ |   @create_attrs %{ | ||||||
|     "bullet_type" => "some bullet_type", |     bullet_type: "some bullet_type", | ||||||
|     "case_material" => "some case_material", |     case_material: "some case_material", | ||||||
|     "desc" => "some desc", |     desc: "some desc", | ||||||
|     "manufacturer" => "some manufacturer", |     manufacturer: "some manufacturer", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "grains" => 120 |     grains: 120 | ||||||
|   } |   } | ||||||
|   @update_attrs %{ |   @update_attrs %{ | ||||||
|     "bullet_type" => "some updated bullet_type", |     bullet_type: "some updated bullet_type", | ||||||
|     "case_material" => "some updated case_material", |     case_material: "some updated case_material", | ||||||
|     "desc" => "some updated desc", |     desc: "some updated desc", | ||||||
|     "manufacturer" => "some updated manufacturer", |     manufacturer: "some updated manufacturer", | ||||||
|     "name" => "some updated name", |     name: "some updated name", | ||||||
|     "grains" => 456 |     grains: 456 | ||||||
|  |   } | ||||||
|  |   @invalid_attrs %{ | ||||||
|  |     bullet_type: nil, | ||||||
|  |     case_material: nil, | ||||||
|  |     desc: nil, | ||||||
|  |     manufacturer: nil, | ||||||
|  |     name: nil, | ||||||
|  |     grains: nil | ||||||
|   } |   } | ||||||
|   @ammo_group_attrs %{ |   @ammo_group_attrs %{ | ||||||
|     "notes" => "some ammo group", |     notes: "some ammo group", | ||||||
|     "count" => 20 |     count: 20 | ||||||
|   } |   } | ||||||
|   @shot_group_attrs %{ |   @shot_group_attrs %{ | ||||||
|     "notes" => "some shot group", |     notes: "some shot group", | ||||||
|     "count" => 20 |     count: 20 | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   # @invalid_attrs %{ |  | ||||||
|   #   "bullet_type" => nil, |  | ||||||
|   #   "case_material" => nil, |  | ||||||
|   #   "desc" => nil, |  | ||||||
|   #   "manufacturer" => nil, |  | ||||||
|   #   "name" => nil, |  | ||||||
|   #   "grains" => nil |  | ||||||
|   # } |  | ||||||
|  |  | ||||||
|   defp create_ammo_type(%{current_user: current_user}) do |   defp create_ammo_type(%{current_user: current_user}) do | ||||||
|     %{ammo_type: ammo_type_fixture(@create_attrs, current_user)} |     [ammo_type: ammo_type_fixture(@create_attrs, current_user)] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp create_ammo_group(%{ammo_type: ammo_type, current_user: current_user}) do |   defp create_ammo_group(%{ammo_type: ammo_type, current_user: current_user}) do | ||||||
|     container = container_fixture(current_user) |     container = container_fixture(current_user) | ||||||
|     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) |     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) | ||||||
|  |     [ammo_group: ammo_group, container: container] | ||||||
|     %{ammo_group: ammo_group, container: container} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp create_empty_ammo_group(%{ammo_type: ammo_type, current_user: current_user}) do |   defp create_empty_ammo_group(%{ammo_type: ammo_type, current_user: current_user}) do | ||||||
| @@ -60,8 +57,7 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) |     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) | ||||||
|     shot_group = shot_group_fixture(@shot_group_attrs, current_user, ammo_group) |     shot_group = shot_group_fixture(@shot_group_attrs, current_user, ammo_group) | ||||||
|     ammo_group = ammo_group |> Repo.reload!() |     ammo_group = ammo_group |> Repo.reload!() | ||||||
|  |     [ammo_group: ammo_group, container: container, shot_group: shot_group] | ||||||
|     %{ammo_group: ammo_group, container: container, shot_group: shot_group} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "Index" do |   describe "Index" do | ||||||
| @@ -69,33 +65,81 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|  |  | ||||||
|     test "lists all ammo_types", %{conn: conn, ammo_type: ammo_type} do |     test "lists all ammo_types", %{conn: conn, ammo_type: ammo_type} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |       assert html =~ "Catalog" | ||||||
|       assert html =~ gettext("Catalog") |  | ||||||
|       assert html =~ ammo_type.bullet_type |       assert html =~ ammo_type.bullet_type | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     test "can sort by class", %{conn: conn, current_user: current_user} do | ||||||
|  |       rifle_type = ammo_type_fixture(%{class: :rifle}, current_user) | ||||||
|  |       shotgun_type = ammo_type_fixture(%{class: :shotgun}, current_user) | ||||||
|  |       pistol_type = ammo_type_fixture(%{class: :pistol}, current_user) | ||||||
|  |  | ||||||
|  |       {:ok, index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|  |       assert html =~ "All" | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_type.name | ||||||
|  |       assert html =~ shotgun_type.name | ||||||
|  |       assert html =~ pistol_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :rifle}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_type.name | ||||||
|  |       refute html =~ shotgun_type.name | ||||||
|  |       refute html =~ pistol_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :shotgun}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_type.name | ||||||
|  |       assert html =~ shotgun_type.name | ||||||
|  |       refute html =~ pistol_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :pistol}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_type.name | ||||||
|  |       refute html =~ shotgun_type.name | ||||||
|  |       assert html =~ pistol_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :all}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_type.name | ||||||
|  |       assert html =~ shotgun_type.name | ||||||
|  |       assert html =~ pistol_type.name | ||||||
|  |     end | ||||||
|  |  | ||||||
|     test "can search for ammo_type", %{conn: conn, ammo_type: ammo_type} do |     test "can search for ammo_type", %{conn: conn, ammo_type: ammo_type} do | ||||||
|       {:ok, index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ ammo_type.bullet_type |       assert html =~ ammo_type.bullet_type | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, |              |> form(~s/form[phx-change="search"]/) | ||||||
|                search: %{search_term: ammo_type.bullet_type} |              |> render_change(search: %{search_term: ammo_type.bullet_type}) =~ | ||||||
|              ) |                ammo_type.bullet_type | ||||||
|              |> render_change() =~ ammo_type.bullet_type |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :search, ammo_type.bullet_type)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :search, ammo_type.bullet_type)) | ||||||
|  |  | ||||||
|       refute index_live |       refute index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: "something_else"}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ ammo_type.bullet_type |              |> render_change(search: %{search_term: "something_else"}) =~ ammo_type.bullet_type | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :search, "something_else")) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :search, "something_else")) | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: ""}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ ammo_type.bullet_type |              |> render_change(search: %{search_term: ""}) =~ ammo_type.bullet_type | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :index)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :index)) | ||||||
|     end |     end | ||||||
| @@ -103,23 +147,21 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|     test "saves new ammo_type", %{conn: conn, current_user: current_user, ammo_type: ammo_type} do |     test "saves new ammo_type", %{conn: conn, current_user: current_user, ammo_type: ammo_type} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "New Ammo type")) |> render_click() =~ |       assert index_live |> element("a", "New Ammo type") |> render_click() =~ "New Ammo type" | ||||||
|                gettext("New Ammo type") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :new)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_type-form", ammo_type: @invalid_attrs) |              |> form("#ammo_type-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_type: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_type-form", ammo_type: @create_attrs) |         |> form("#ammo_type-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_type: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) |       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: ammo_type.name) |       assert html =~ "#{ammo_type.name} created successfully" | ||||||
|       assert html =~ "some bullet_type" |       assert html =~ "some bullet_type" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -128,22 +170,22 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Edit #{ammo_type.name}"]/) |> render_click() =~ |       assert index_live |> element(~s/a[aria-label="Edit #{ammo_type.name}"]/) |> render_click() =~ | ||||||
|                gettext("Edit %{ammo_type_name}", ammo_type_name: ammo_type.name) |                "Edit #{ammo_type.name}" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :edit, ammo_type)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :edit, ammo_type)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_type-form", ammo_type: @invalid_attrs) |              |> form("#ammo_type-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_type: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_type-form", ammo_type: @update_attrs) |         |> form("#ammo_type-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_type: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) |       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} updated successfully", name: ammo_type.name) |       assert html =~ "#{ammo_type.name} updated successfully" | ||||||
|       assert html =~ "some updated bullet_type" |       assert html =~ "some updated bullet_type" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -152,23 +194,23 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       html = index_live |> element(~s/a[aria-label="Clone #{ammo_type.name}"]/) |> render_click() |       html = index_live |> element(~s/a[aria-label="Clone #{ammo_type.name}"]/) |> render_click() | ||||||
|       assert html =~ gettext("New Ammo type") |       assert html =~ "New Ammo type" | ||||||
|       assert html =~ "some bullet_type" |       assert html =~ "some bullet_type" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :clone, ammo_type)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :clone, ammo_type)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_type-form", ammo_type: @invalid_attrs) |              |> form("#ammo_type-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_type: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_type-form", ammo_type: @create_attrs) |         |> form("#ammo_type-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_type: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) |       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: ammo_type.name) |       assert html =~ "#{ammo_type.name} created successfully" | ||||||
|       assert html =~ "some bullet_type" |       assert html =~ "some bullet_type" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -177,31 +219,30 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       html = index_live |> element(~s/a[aria-label="Clone #{ammo_type.name}"]/) |> render_click() |       html = index_live |> element(~s/a[aria-label="Clone #{ammo_type.name}"]/) |> render_click() | ||||||
|       assert html =~ gettext("New Ammo type") |       assert html =~ "New Ammo type" | ||||||
|       assert html =~ "some bullet_type" |       assert html =~ "some bullet_type" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.ammo_type_index_path(conn, :clone, ammo_type)) |       assert_patch(index_live, Routes.ammo_type_index_path(conn, :clone, ammo_type)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#ammo_type-form", ammo_type: @invalid_attrs) |              |> form("#ammo_type-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_type: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#ammo_type-form", |         |> form("#ammo_type-form") | ||||||
|           ammo_type: Map.merge(@create_attrs, %{"bullet_type" => "some updated bullet_type"}) |         |> render_submit( | ||||||
|  |           ammo_type: Map.merge(@create_attrs, %{bullet_type: "some updated bullet_type"}) | ||||||
|         ) |         ) | ||||||
|         |> render_submit() |  | ||||||
|         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) |       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: ammo_type.name) |       assert html =~ "#{ammo_type.name} created successfully" | ||||||
|       assert html =~ "some updated bullet_type" |       assert html =~ "some updated bullet_type" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "deletes ammo_type in listing", %{conn: conn, ammo_type: ammo_type} do |     test "deletes ammo_type in listing", %{conn: conn, ammo_type: ammo_type} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Delete #{ammo_type.name}"]/) |> render_click() |       assert index_live |> element(~s/a[aria-label="Delete #{ammo_type.name}"]/) |> render_click() | ||||||
|       refute has_element?(index_live, "#ammo_type-#{ammo_type.id}") |       refute has_element?(index_live, "#ammo_type-#{ammo_type.id}") | ||||||
|     end |     end | ||||||
| @@ -214,27 +255,27 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|          %{conn: conn, ammo_group: ammo_group, current_user: current_user} do |          %{conn: conn, ammo_group: ammo_group, current_user: current_user} do | ||||||
|       {:ok, index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Show used") |       assert html =~ "Show used" | ||||||
|       refute html =~ gettext("Used rounds") |       refute html =~ "Used rounds" | ||||||
|       refute html =~ gettext("Total ever rounds") |       refute html =~ "Total ever rounds" | ||||||
|       refute html =~ gettext("Used packs") |       refute html =~ "Used packs" | ||||||
|       refute html =~ gettext("Total ever packs") |       refute html =~ "Total ever packs" | ||||||
|  |  | ||||||
|       html = |       html = | ||||||
|         index_live |         index_live | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ gettext("Used rounds") |       assert html =~ "Used rounds" | ||||||
|       assert html =~ gettext("Total ever rounds") |       assert html =~ "Total ever rounds" | ||||||
|       assert html =~ gettext("Used packs") |       assert html =~ "Used packs" | ||||||
|       assert html =~ gettext("Total ever packs") |       assert html =~ "Total ever packs" | ||||||
|  |  | ||||||
|       assert html =~ "20" |       assert html =~ "\n20\n" | ||||||
|       assert html =~ "0" |       assert html =~ "\n0\n" | ||||||
|       assert html =~ "1" |       assert html =~ "\n1\n" | ||||||
|  |  | ||||||
|       shot_group_fixture(%{"count" => 5}, current_user, ammo_group) |       shot_group_fixture(%{count: 5}, current_user, ammo_group) | ||||||
|  |  | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index)) | ||||||
|  |  | ||||||
| @@ -243,8 +284,8 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ "15" |       assert html =~ "\n15\n" | ||||||
|       assert html =~ "5" |       assert html =~ "\n5\n" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -266,22 +307,22 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|       {:ok, show_live, _html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) |       {:ok, show_live, _html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) | ||||||
|  |  | ||||||
|       assert show_live |> element(~s/a[aria-label="Edit #{ammo_type.name}"]/) |> render_click() =~ |       assert show_live |> element(~s/a[aria-label="Edit #{ammo_type.name}"]/) |> render_click() =~ | ||||||
|                gettext("Edit %{ammo_type_name}", ammo_type_name: name) |                "Edit #{name}" | ||||||
|  |  | ||||||
|       assert_patch(show_live, Routes.ammo_type_show_path(conn, :edit, ammo_type)) |       assert_patch(show_live, Routes.ammo_type_show_path(conn, :edit, ammo_type)) | ||||||
|  |  | ||||||
|       # assert show_live |       assert show_live | ||||||
|       #        |> form("#ammo_type-form", ammo_type: @invalid_attrs) |              |> form("#ammo_type-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(ammo_type: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         show_live |         show_live | ||||||
|         |> form("#ammo_type-form", ammo_type: @update_attrs) |         |> form("#ammo_type-form") | ||||||
|         |> render_submit() |         |> render_submit(ammo_type: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) |         |> follow_redirect(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) | ||||||
|  |  | ||||||
|       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) |       ammo_type = ammo_type.id |> Ammo.get_ammo_type!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} updated successfully", name: ammo_type.name) |       assert html =~ "#{ammo_type.name} updated successfully" | ||||||
|       assert html =~ "some updated bullet_type" |       assert html =~ "some updated bullet_type" | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| @@ -297,7 +338,7 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|       {:ok, _show_live, html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) |       {:ok, _show_live, html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) | ||||||
|  |  | ||||||
|       assert html =~ ammo_type_name |       assert html =~ ammo_type_name | ||||||
|       assert html =~ "some ammo group" |       assert html =~ "\n20\n" | ||||||
|       assert html =~ container_name |       assert html =~ container_name | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -310,9 +351,7 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert_patch(show_live, Routes.ammo_type_show_path(conn, :table, ammo_type)) |       assert html =~ "\n20\n" | ||||||
|  |  | ||||||
|       assert html =~ "some ammo group" |  | ||||||
|       assert html =~ container_name |       assert html =~ container_name | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| @@ -323,16 +362,15 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|     test "displays empty ammo groups on toggle", |     test "displays empty ammo groups on toggle", | ||||||
|          %{conn: conn, ammo_type: ammo_type, container: %{name: container_name}} do |          %{conn: conn, ammo_type: ammo_type, container: %{name: container_name}} do | ||||||
|       {:ok, show_live, html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) |       {:ok, show_live, html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type)) | ||||||
|  |       assert html =~ "Show used" | ||||||
|       assert html =~ dgettext("actions", "Show used") |       refute html =~ "\n20\n" | ||||||
|       refute html =~ "some ammo group" |  | ||||||
|  |  | ||||||
|       html = |       html = | ||||||
|         show_live |         show_live | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ "some ammo group" |       assert html =~ "\n20\n" | ||||||
|       assert html =~ "Empty" |       assert html =~ "Empty" | ||||||
|       assert html =~ container_name |       assert html =~ container_name | ||||||
|     end |     end | ||||||
| @@ -346,17 +384,15 @@ defmodule CanneryWeb.AmmoTypeLiveTest do | |||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert_patch(show_live, Routes.ammo_type_show_path(conn, :table, ammo_type)) |       assert html =~ "Show used" | ||||||
|  |       refute html =~ "\n20\n" | ||||||
|       assert html =~ dgettext("actions", "Show used") |  | ||||||
|       refute html =~ "some ammo group" |  | ||||||
|  |  | ||||||
|       html = |       html = | ||||||
|         show_live |         show_live | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ "some ammo group" |       assert html =~ "\n20\n" | ||||||
|       assert html =~ "Empty" |       assert html =~ "Empty" | ||||||
|       assert html =~ container_name |       assert html =~ container_name | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -5,61 +5,46 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |   alias Cannery.Containers | ||||||
|   alias Cannery.{Containers, Repo} |  | ||||||
|  |  | ||||||
|   @moduletag :container_live_test |   @moduletag :container_live_test | ||||||
|  |  | ||||||
|   @create_attrs %{ |   @create_attrs %{ | ||||||
|     "desc" => "some desc", |     desc: "some desc", | ||||||
|     "location" => "some location", |     location: "some location", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "type" => "some type" |     type: "some type" | ||||||
|   } |   } | ||||||
|   @update_attrs %{ |   @update_attrs %{ | ||||||
|     "desc" => "some updated desc", |     desc: "some updated desc", | ||||||
|     "location" => "some updated location", |     location: "some updated location", | ||||||
|     "name" => "some updated name", |     name: "some updated name", | ||||||
|     "type" => "some updated type" |     type: "some updated type" | ||||||
|   } |   } | ||||||
|  |   @invalid_attrs %{desc: nil, location: nil, name: nil, type: nil} | ||||||
|   @ammo_type_attrs %{ |   @ammo_type_attrs %{ | ||||||
|     "bullet_type" => "some bullet_type", |     bullet_type: "some bullet_type", | ||||||
|     "case_material" => "some case_material", |     case_material: "some case_material", | ||||||
|     "desc" => "some desc", |     desc: "some desc", | ||||||
|     "manufacturer" => "some manufacturer", |     manufacturer: "some manufacturer", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "grains" => 120 |     grains: 120 | ||||||
|   } |   } | ||||||
|   @ammo_group_attrs %{ |   @ammo_group_attrs %{ | ||||||
|     "notes" => "some ammo group", |     notes: "some ammo group", | ||||||
|     "count" => 20 |     count: 20 | ||||||
|   } |   } | ||||||
|   @shot_group_attrs %{ |  | ||||||
|     "notes" => "some shot group", |  | ||||||
|     "count" => 20 |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   # @invalid_attrs %{desc: nil, location: nil, name: nil, type: nil} |  | ||||||
|  |  | ||||||
|   defp create_container(%{current_user: current_user}) do |   defp create_container(%{current_user: current_user}) do | ||||||
|     container = container_fixture(@create_attrs, current_user) |     container = container_fixture(@create_attrs, current_user) | ||||||
|     %{container: container} |     [container: container] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   defp create_ammo_group(%{container: container, current_user: current_user}) do |   defp create_ammo_group(%{container: container, current_user: current_user}) do | ||||||
|     ammo_type = ammo_type_fixture(@ammo_type_attrs, current_user) |     ammo_type = ammo_type_fixture(@ammo_type_attrs, current_user) | ||||||
|     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) |     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) | ||||||
|  |  | ||||||
|     %{ammo_type: ammo_type, ammo_group: ammo_group} |     [ammo_type: ammo_type, ammo_group: ammo_group] | ||||||
|   end |  | ||||||
|  |  | ||||||
|   defp create_empty_ammo_group(%{container: container, current_user: current_user}) do |  | ||||||
|     ammo_type = ammo_type_fixture(@ammo_type_attrs, current_user) |  | ||||||
|     {1, [ammo_group]} = ammo_group_fixture(@ammo_group_attrs, ammo_type, container, current_user) |  | ||||||
|     shot_group = shot_group_fixture(@shot_group_attrs, current_user, ammo_group) |  | ||||||
|     ammo_group = ammo_group |> Repo.reload!() |  | ||||||
|  |  | ||||||
|     %{ammo_type: ammo_type, ammo_group: ammo_group, shot_group: shot_group} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "Index" do |   describe "Index" do | ||||||
| @@ -68,7 +53,7 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|     test "lists all containers", %{conn: conn, container: container} do |     test "lists all containers", %{conn: conn, container: container} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ gettext("Containers") |       assert html =~ "Containers" | ||||||
|       assert html =~ container.location |       assert html =~ container.location | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -80,7 +65,7 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) |         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) | ||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ gettext("Containers") |       assert html =~ "Containers" | ||||||
|       assert html =~ container.location |       assert html =~ container.location | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -90,22 +75,20 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       assert html =~ container.location |       assert html =~ container.location | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, |              |> form(~s/form[phx-change="search"]/) | ||||||
|                search: %{search_term: container.location} |              |> render_change(search: %{search_term: container.location}) =~ container.location | ||||||
|              ) |  | ||||||
|              |> render_change() =~ container.location |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :search, container.location)) |       assert_patch(index_live, Routes.container_index_path(conn, :search, container.location)) | ||||||
|  |  | ||||||
|       refute index_live |       refute index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: "something_else"}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ container.location |              |> render_change(search: %{search_term: "something_else"}) =~ container.location | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :search, "something_else")) |       assert_patch(index_live, Routes.container_index_path(conn, :search, "something_else")) | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: ""}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ container.location |              |> render_change(search: %{search_term: ""}) =~ container.location | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :index)) |       assert_patch(index_live, Routes.container_index_path(conn, :index)) | ||||||
|     end |     end | ||||||
| @@ -113,22 +96,20 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|     test "saves new container", %{conn: conn, container: container} do |     test "saves new container", %{conn: conn, container: container} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "New Container")) |> render_click() =~ |       assert index_live |> element("a", "New Container") |> render_click() =~ "New Container" | ||||||
|                gettext("New Container") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :new)) |       assert_patch(index_live, Routes.container_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#container-form", container: @invalid_attrs) |              |> form("#container-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(container: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#container-form", container: @create_attrs) |         |> form("#container-form") | ||||||
|         |> render_submit() |         |> render_submit(container: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: container.name) |       assert html =~ "#{container.name} created successfully" | ||||||
|       assert html =~ "some location" |       assert html =~ "some location" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -140,22 +121,22 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Edit #{container.name}"]/) |> render_click() =~ |       assert index_live |> element(~s/a[aria-label="Edit #{container.name}"]/) |> render_click() =~ | ||||||
|                gettext("Edit %{name}", name: container.name) |                "Edit #{container.name}" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :edit, container)) |       assert_patch(index_live, Routes.container_index_path(conn, :edit, container)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#container-form", container: @invalid_attrs) |              |> form("#container-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(container: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#container-form", container: @update_attrs) |         |> form("#container-form") | ||||||
|         |> render_submit() |         |> render_submit(container: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       container = container.id |> Containers.get_container!(current_user) |       container = container.id |> Containers.get_container!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} updated successfully", name: container.name) |       assert html =~ "#{container.name} updated successfully" | ||||||
|       assert html =~ "some updated location" |       assert html =~ "some updated location" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -167,23 +148,23 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       html = index_live |> element(~s/a[aria-label="Clone #{container.name}"]/) |> render_click() |       html = index_live |> element(~s/a[aria-label="Clone #{container.name}"]/) |> render_click() | ||||||
|       assert html =~ gettext("New Container") |       assert html =~ "New Container" | ||||||
|       assert html =~ "some location" |       assert html =~ "some location" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :clone, container)) |       assert_patch(index_live, Routes.container_index_path(conn, :clone, container)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#container-form", container: @invalid_attrs) |              |> form("#container-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(container: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#container-form", container: @create_attrs) |         |> form("#container-form") | ||||||
|         |> render_submit() |         |> render_submit(container: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       container = container.id |> Containers.get_container!(current_user) |       container = container.id |> Containers.get_container!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: container.name) |       assert html =~ "#{container.name} created successfully" | ||||||
|       assert html =~ "some location" |       assert html =~ "some location" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -195,30 +176,29 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Clone #{container.name}"]/) |> render_click() =~ |       assert index_live |> element(~s/a[aria-label="Clone #{container.name}"]/) |> render_click() =~ | ||||||
|                gettext("New Container") |                "New Container" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.container_index_path(conn, :clone, container)) |       assert_patch(index_live, Routes.container_index_path(conn, :clone, container)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#container-form", container: @invalid_attrs) |              |> form("#container-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(container: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#container-form", |         |> form("#container-form") | ||||||
|  |         |> render_submit( | ||||||
|           container: Map.merge(@create_attrs, %{location: "some updated location"}) |           container: Map.merge(@create_attrs, %{location: "some updated location"}) | ||||||
|         ) |         ) | ||||||
|         |> render_submit() |  | ||||||
|         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       container = container.id |> Containers.get_container!(current_user) |       container = container.id |> Containers.get_container!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} created successfully", name: container.name) |       assert html =~ "#{container.name} created successfully" | ||||||
|       assert html =~ "some updated location" |       assert html =~ "some updated location" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "deletes container in listing", %{conn: conn, container: container} do |     test "deletes container in listing", %{conn: conn, container: container} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Delete #{container.name}"]/) |> render_click() |       assert index_live |> element(~s/a[aria-label="Delete #{container.name}"]/) |> render_click() | ||||||
|       refute has_element?(index_live, "#container-#{container.id}") |       refute has_element?(index_live, "#container-#{container.id}") | ||||||
|     end |     end | ||||||
| @@ -232,7 +212,6 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       container: %{name: name, location: location} = container |       container: %{name: name, location: location} = container | ||||||
|     } do |     } do | ||||||
|       {:ok, _show_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) |       {:ok, _show_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) | ||||||
|  |  | ||||||
|       assert html =~ name |       assert html =~ name | ||||||
|       assert html =~ location |       assert html =~ location | ||||||
|     end |     end | ||||||
| @@ -245,24 +224,78 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       {:ok, show_live, _html} = live(conn, Routes.container_show_path(conn, :show, container)) |       {:ok, show_live, _html} = live(conn, Routes.container_show_path(conn, :show, container)) | ||||||
|  |  | ||||||
|       assert show_live |> element(~s/a[aria-label="Edit #{container.name}"]/) |> render_click() =~ |       assert show_live |> element(~s/a[aria-label="Edit #{container.name}"]/) |> render_click() =~ | ||||||
|                gettext("Edit %{name}", name: container.name) |                "Edit #{container.name}" | ||||||
|  |  | ||||||
|       assert_patch(show_live, Routes.container_show_path(conn, :edit, container)) |       assert_patch(show_live, Routes.container_show_path(conn, :edit, container)) | ||||||
|  |  | ||||||
|       # assert show_live |       assert show_live | ||||||
|       #        |> form("#container-form", container: @invalid_attrs) |              |> form("#container-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(container: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         show_live |         show_live | ||||||
|         |> form("#container-form", container: @update_attrs) |         |> form("#container-form") | ||||||
|         |> render_submit() |         |> render_submit(container: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.container_show_path(conn, :show, container)) |         |> follow_redirect(conn, Routes.container_show_path(conn, :show, container)) | ||||||
|  |  | ||||||
|       container = container.id |> Containers.get_container!(current_user) |       container = container.id |> Containers.get_container!(current_user) | ||||||
|       assert html =~ dgettext("prompts", "%{name} updated successfully", name: container.name) |       assert html =~ "#{container.name} updated successfully" | ||||||
|       assert html =~ "some updated location" |       assert html =~ "some updated location" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     test "can sort by type", | ||||||
|  |          %{conn: conn, container: container, current_user: current_user} do | ||||||
|  |       rifle_type = ammo_type_fixture(%{class: :rifle}, current_user) | ||||||
|  |       {1, [rifle_ammo_group]} = ammo_group_fixture(rifle_type, container, current_user) | ||||||
|  |       shotgun_type = ammo_type_fixture(%{class: :shotgun}, current_user) | ||||||
|  |       {1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_type, container, current_user) | ||||||
|  |       pistol_type = ammo_type_fixture(%{class: :pistol}, current_user) | ||||||
|  |       {1, [pistol_ammo_group]} = ammo_group_fixture(pistol_type, container, current_user) | ||||||
|  |  | ||||||
|  |       {:ok, index_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) | ||||||
|  |  | ||||||
|  |       assert html =~ "All" | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :rifle}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :shotgun}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :pistol}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       refute html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :all}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ shotgun_ammo_group.ammo_type.name | ||||||
|  |       assert html =~ pistol_ammo_group.ammo_type.name | ||||||
|  |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "Show with ammo group" do |   describe "Show with ammo group" do | ||||||
| @@ -273,7 +306,7 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|       {:ok, _show_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) |       {:ok, _show_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) | ||||||
|  |  | ||||||
|       assert html =~ ammo_type_name |       assert html =~ ammo_type_name | ||||||
|       assert html =~ "some ammo group" |       assert html =~ "\n20\n" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "displays ammo group in table", |     test "displays ammo group in table", | ||||||
| @@ -286,50 +319,7 @@ defmodule CanneryWeb.ContainerLiveTest do | |||||||
|         |> render_click() |         |> render_click() | ||||||
|  |  | ||||||
|       assert html =~ ammo_type_name |       assert html =~ ammo_type_name | ||||||
|       assert html =~ "some ammo group" |       assert html =~ "\n20\n" | ||||||
|     end |  | ||||||
|   end |  | ||||||
|  |  | ||||||
|   describe "Show with empty ammo group" do |  | ||||||
|     setup [:register_and_log_in_user, :create_container, :create_empty_ammo_group] |  | ||||||
|  |  | ||||||
|     test "hides empty ammo groups by default", |  | ||||||
|          %{conn: conn, ammo_type: %{name: ammo_type_name}, container: container} do |  | ||||||
|       {:ok, show_live, html} = live(conn, Routes.container_show_path(conn, :show, container)) |  | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Show used") |  | ||||||
|       refute html =~ "some ammo group" |  | ||||||
|  |  | ||||||
|       html = |  | ||||||
|         show_live |  | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |  | ||||||
|         |> render_click() |  | ||||||
|  |  | ||||||
|       assert html =~ ammo_type_name |  | ||||||
|       assert html =~ "some ammo group" |  | ||||||
|       assert html =~ "Empty" |  | ||||||
|     end |  | ||||||
|  |  | ||||||
|     test "displays empty ammo groups in table on toggle", |  | ||||||
|          %{conn: conn, ammo_type: %{name: ammo_type_name}, container: container} do |  | ||||||
|       {:ok, show_live, _html} = live(conn, Routes.container_show_path(conn, :show, container)) |  | ||||||
|  |  | ||||||
|       html = |  | ||||||
|         show_live |  | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) |  | ||||||
|         |> render_click() |  | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Show used") |  | ||||||
|       refute html =~ "some ammo group" |  | ||||||
|  |  | ||||||
|       html = |  | ||||||
|         show_live |  | ||||||
|         |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |  | ||||||
|         |> render_click() |  | ||||||
|  |  | ||||||
|       assert html =~ ammo_type_name |  | ||||||
|       assert html =~ "some ammo group" |  | ||||||
|       assert html =~ "Empty" |  | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -5,14 +5,13 @@ defmodule CanneryWeb.HomeLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|  |  | ||||||
|   @moduletag :home_live_test |   @moduletag :home_live_test | ||||||
|  |  | ||||||
|   test "disconnected and connected render", %{conn: conn} do |   test "disconnected and connected render", %{conn: conn} do | ||||||
|     {:ok, home_live, disconnected_html} = live(conn, "/") |     {:ok, home_live, disconnected_html} = live(conn, "/") | ||||||
|     assert disconnected_html =~ gettext("Welcome to %{name}", name: "Cannery") |     assert disconnected_html =~ "Welcome to Cannery" | ||||||
|     assert render(home_live) =~ gettext("Welcome to %{name}", name: "Cannery") |     assert render(home_live) =~ "Welcome to Cannery" | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   test "displays version number", %{conn: conn} do |   test "displays version number", %{conn: conn} do | ||||||
|   | |||||||
| @@ -5,13 +5,12 @@ defmodule CanneryWeb.InviteLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   alias Cannery.Accounts.Invites |   alias Cannery.Accounts.Invites | ||||||
|  |  | ||||||
|   @moduletag :invite_live_test |   @moduletag :invite_live_test | ||||||
|   @create_attrs %{"name" => "some name"} |   @create_attrs %{name: "some name"} | ||||||
|   @update_attrs %{"name" => "some updated name"} |   @update_attrs %{name: "some updated name"} | ||||||
|   # @invalid_attrs %{"name" => nil} |   @invalid_attrs %{name: nil} | ||||||
|  |  | ||||||
|   describe "Index" do |   describe "Index" do | ||||||
|     setup [:register_and_log_in_user] |     setup [:register_and_log_in_user] | ||||||
| @@ -24,32 +23,27 @@ defmodule CanneryWeb.InviteLiveTest do | |||||||
|     test "lists all invites", %{conn: conn, invite: invite} do |     test "lists all invites", %{conn: conn, invite: invite} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.invite_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.invite_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ gettext("Invites") |       assert html =~ "Invites" | ||||||
|       assert html =~ invite.name |       assert html =~ invite.name | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "saves new invite", %{conn: conn} do |     test "saves new invite", %{conn: conn} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.invite_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.invite_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Create Invite")) |> render_click() =~ |       assert index_live |> element("a", "Create Invite") |> render_click() =~ "New Invite" | ||||||
|                gettext("New Invite") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.invite_index_path(conn, :new)) |       assert_patch(index_live, Routes.invite_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#invite-form", invite: @invalid_attrs) |              |> form("#invite-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(invite: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _live, html} = |       {:ok, _live, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#invite-form", invite: @create_attrs) |         |> form("#invite-form") | ||||||
|         |> render_submit() |         |> render_submit(invite: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.invite_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.invite_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ |       assert html =~ "some name created successfully" | ||||||
|                dgettext("prompts", "%{invite_name} created successfully", invite_name: "some name") |  | ||||||
|  |  | ||||||
|       assert html =~ "some name" |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "updates invite in listing", %{conn: conn, invite: invite} do |     test "updates invite in listing", %{conn: conn, invite: invite} do | ||||||
| @@ -57,27 +51,21 @@ defmodule CanneryWeb.InviteLiveTest do | |||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> element(~s/a[aria-label="Edit invite for #{invite.name}"]/) |              |> element(~s/a[aria-label="Edit invite for #{invite.name}"]/) | ||||||
|              |> render_click() =~ |              |> render_click() =~ "Edit Invite" | ||||||
|                gettext("Edit Invite") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.invite_index_path(conn, :edit, invite)) |       assert_patch(index_live, Routes.invite_index_path(conn, :edit, invite)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#invite-form", invite: @invalid_attrs) |              |> form("#invite-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(invite: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _live, html} = |       {:ok, _live, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#invite-form", invite: @update_attrs) |         |> form("#invite-form") | ||||||
|         |> render_submit() |         |> render_submit(invite: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.invite_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.invite_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ |       assert html =~ "some updated name updated successfully" | ||||||
|                dgettext("prompts", "%{invite_name} updated successfully", |  | ||||||
|                  invite_name: "some updated name" |  | ||||||
|                ) |  | ||||||
|  |  | ||||||
|       assert html =~ "some updated name" |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "deletes invite in listing", %{conn: conn, invite: invite} do |     test "deletes invite in listing", %{conn: conn, invite: invite} do | ||||||
|   | |||||||
| @@ -6,25 +6,28 @@ defmodule CanneryWeb.RangeLiveTest do | |||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import Cannery.Fixtures |   import Cannery.Fixtures | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|  |  | ||||||
|   @moduletag :range_live_test |   @moduletag :range_live_test | ||||||
|   @create_attrs %{"ammo_left" => 5, "notes" => "some notes"} |   @create_attrs %{ammo_left: 5, notes: "some notes"} | ||||||
|   @update_attrs %{"count" => 16, "notes" => "some updated notes"} |   @update_attrs %{count: 16, notes: "some updated notes"} | ||||||
|   # @invalid_attrs %{"count" => nil, "notes" => nil} |   @invalid_attrs %{count: nil, notes: nil} | ||||||
|  |  | ||||||
|   defp create_shot_group(%{current_user: current_user}) do |   defp create_shot_group(%{current_user: current_user}) do | ||||||
|     container = container_fixture(%{"staged" => true}, current_user) |     container = container_fixture(%{staged: true}, current_user) | ||||||
|     ammo_type = ammo_type_fixture(current_user) |     ammo_type = ammo_type_fixture(current_user) | ||||||
|  |  | ||||||
|     {1, [ammo_group]} = |     {1, [ammo_group]} = ammo_group_fixture(%{staged: true}, ammo_type, container, current_user) | ||||||
|       ammo_group_fixture(%{"staged" => true}, ammo_type, container, current_user) |  | ||||||
|  |  | ||||||
|     shot_group = |     shot_group = | ||||||
|       %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"} |       %{count: 5, date: ~N[2022-02-13 03:17:00], notes: "some notes"} | ||||||
|       |> shot_group_fixture(current_user, ammo_group) |       |> shot_group_fixture(current_user, ammo_group) | ||||||
|  |  | ||||||
|     %{shot_group: shot_group, ammo_group: ammo_group} |     [ | ||||||
|  |       container: container, | ||||||
|  |       ammo_type: ammo_type, | ||||||
|  |       ammo_group: ammo_group, | ||||||
|  |       shot_group: shot_group | ||||||
|  |     ] | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   describe "Index" do |   describe "Index" do | ||||||
| @@ -33,32 +36,94 @@ defmodule CanneryWeb.RangeLiveTest do | |||||||
|     test "lists all shot_groups", %{conn: conn, shot_group: shot_group} do |     test "lists all shot_groups", %{conn: conn, shot_group: shot_group} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.range_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ gettext("Range day") |       assert html =~ "Range day" | ||||||
|       assert html =~ shot_group.notes |       assert html =~ shot_group.notes | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     test "can sort by type", | ||||||
|  |          %{conn: conn, container: container, current_user: current_user} do | ||||||
|  |       rifle_ammo_type = ammo_type_fixture(%{class: :rifle}, current_user) | ||||||
|  |       {1, [rifle_ammo_group]} = ammo_group_fixture(rifle_ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       rifle_shot_group = shot_group_fixture(%{notes: "group_one"}, current_user, rifle_ammo_group) | ||||||
|  |  | ||||||
|  |       shotgun_ammo_type = ammo_type_fixture(%{class: :shotgun}, current_user) | ||||||
|  |       {1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       shotgun_shot_group = | ||||||
|  |         shot_group_fixture(%{notes: "group_two"}, current_user, shotgun_ammo_group) | ||||||
|  |  | ||||||
|  |       pistol_ammo_type = ammo_type_fixture(%{class: :pistol}, current_user) | ||||||
|  |       {1, [pistol_ammo_group]} = ammo_group_fixture(pistol_ammo_type, container, current_user) | ||||||
|  |  | ||||||
|  |       pistol_shot_group = | ||||||
|  |         shot_group_fixture(%{notes: "group_three"}, current_user, pistol_ammo_group) | ||||||
|  |  | ||||||
|  |       {:ok, index_live, html} = live(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|  |       assert html =~ "All" | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_shot_group.notes | ||||||
|  |       assert html =~ shotgun_shot_group.notes | ||||||
|  |       assert html =~ pistol_shot_group.notes | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :rifle}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_shot_group.notes | ||||||
|  |       refute html =~ shotgun_shot_group.notes | ||||||
|  |       refute html =~ pistol_shot_group.notes | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :shotgun}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_shot_group.notes | ||||||
|  |       assert html =~ shotgun_shot_group.notes | ||||||
|  |       refute html =~ pistol_shot_group.notes | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :pistol}) | ||||||
|  |  | ||||||
|  |       refute html =~ rifle_shot_group.notes | ||||||
|  |       refute html =~ shotgun_shot_group.notes | ||||||
|  |       assert html =~ pistol_shot_group.notes | ||||||
|  |  | ||||||
|  |       html = | ||||||
|  |         index_live | ||||||
|  |         |> form(~s/form[phx-change="change_class"]/) | ||||||
|  |         |> render_change(ammo_type: %{class: :all}) | ||||||
|  |  | ||||||
|  |       assert html =~ rifle_shot_group.notes | ||||||
|  |       assert html =~ shotgun_shot_group.notes | ||||||
|  |       assert html =~ pistol_shot_group.notes | ||||||
|  |     end | ||||||
|  |  | ||||||
|     test "can search for shot_group", %{conn: conn, shot_group: shot_group} do |     test "can search for shot_group", %{conn: conn, shot_group: shot_group} do | ||||||
|       {:ok, index_live, html} = live(conn, Routes.range_index_path(conn, :index)) |       {:ok, index_live, html} = live(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ shot_group.notes |       assert html =~ shot_group.notes | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, |              |> form(~s/form[phx-change="search"]/) | ||||||
|                search: %{search_term: shot_group.notes} |              |> render_change(search: %{search_term: shot_group.notes}) =~ shot_group.notes | ||||||
|              ) |  | ||||||
|              |> render_change() =~ shot_group.notes |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.range_index_path(conn, :search, shot_group.notes)) |       assert_patch(index_live, Routes.range_index_path(conn, :search, shot_group.notes)) | ||||||
|  |  | ||||||
|       refute index_live |       refute index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: "something_else"}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ shot_group.notes |              |> render_change(search: %{search_term: "something_else"}) =~ shot_group.notes | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.range_index_path(conn, :search, "something_else")) |       assert_patch(index_live, Routes.range_index_path(conn, :search, "something_else")) | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: ""}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ shot_group.notes |              |> render_change(search: %{search_term: ""}) =~ shot_group.notes | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.range_index_path(conn, :index)) |       assert_patch(index_live, Routes.range_index_path(conn, :index)) | ||||||
|     end |     end | ||||||
| @@ -66,22 +131,20 @@ defmodule CanneryWeb.RangeLiveTest do | |||||||
|     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do |     test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.range_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "Record shots")) |> render_click() =~ |       assert index_live |> element("a", "Record shots") |> render_click() =~ "Record shots" | ||||||
|                gettext("Record shots") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.range_index_path(conn, :add_shot_group, ammo_group)) |       assert_patch(index_live, Routes.range_index_path(conn, :add_shot_group, ammo_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#shot_group-form", shot_group: @invalid_attrs) |              |> form("#shot-group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "is invalid") |              |> render_change(shot_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#shot-group-form", shot_group: @create_attrs) |         |> form("#shot-group-form") | ||||||
|         |> render_submit() |         |> render_submit(shot_group: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.range_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("prompts", "Shots recorded successfully") |       assert html =~ "Shots recorded successfully" | ||||||
|       assert html =~ "some notes" |       assert html =~ "some notes" | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -90,14 +153,13 @@ defmodule CanneryWeb.RangeLiveTest do | |||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> element(~s/a[aria-label="Edit shot record of #{shot_group.count} shots"]/) |              |> element(~s/a[aria-label="Edit shot record of #{shot_group.count} shots"]/) | ||||||
|              |> render_click() =~ |              |> render_click() =~ "Edit Shot Records" | ||||||
|                gettext("Edit Shot Records") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.range_index_path(conn, :edit, shot_group)) |       assert_patch(index_live, Routes.range_index_path(conn, :edit, shot_group)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#shot_group-form", shot_group: @invalid_attrs) |              |> form("#shot-group-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "is invalid") |              |> render_change(shot_group: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
| @@ -105,7 +167,7 @@ defmodule CanneryWeb.RangeLiveTest do | |||||||
|         |> render_submit() |         |> render_submit() | ||||||
|         |> follow_redirect(conn, Routes.range_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.range_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "Shot records updated successfully") |       assert html =~ "Shot records updated successfully" | ||||||
|       assert html =~ "some updated notes" |       assert html =~ "some updated notes" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,26 +5,24 @@ defmodule CanneryWeb.TagLiveTest do | |||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase |   use CanneryWeb.ConnCase | ||||||
|   import Phoenix.LiveViewTest |   import Phoenix.LiveViewTest | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|  |  | ||||||
|   @moduletag :tag_live_test |   @moduletag :tag_live_test | ||||||
|  |  | ||||||
|   @create_attrs %{ |   @create_attrs %{ | ||||||
|     "bg_color" => "some bg-color", |     bg_color: "#100000", | ||||||
|     "name" => "some name", |     name: "some name", | ||||||
|     "text_color" => "some text-color" |     text_color: "#000000" | ||||||
|   } |   } | ||||||
|   @update_attrs %{ |   @update_attrs %{ | ||||||
|     "bg_color" => "some updated bg-color", |     bg_color: "#100001", | ||||||
|     "name" => "some updated name", |     name: "some updated name", | ||||||
|     "text_color" => "some updated text-color" |     text_color: "#000001" | ||||||
|  |   } | ||||||
|  |   @invalid_attrs %{ | ||||||
|  |     bg_color: nil, | ||||||
|  |     name: nil, | ||||||
|  |     text_color: nil | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   # @invalid_attrs %{ |  | ||||||
|   #   "bg_color" => nil, |  | ||||||
|   #   "name" => nil, |  | ||||||
|   #   "text_color" => nil |  | ||||||
|   # } |  | ||||||
|  |  | ||||||
|   def create_tag(%{current_user: current_user}) do |   def create_tag(%{current_user: current_user}) do | ||||||
|     tag = tag_fixture(current_user) |     tag = tag_fixture(current_user) | ||||||
| @@ -37,7 +35,7 @@ defmodule CanneryWeb.TagLiveTest do | |||||||
|     test "lists all tags", %{conn: conn, tag: tag} do |     test "lists all tags", %{conn: conn, tag: tag} do | ||||||
|       {:ok, _index_live, html} = live(conn, Routes.tag_index_path(conn, :index)) |       {:ok, _index_live, html} = live(conn, Routes.tag_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ gettext("Tags") |       assert html =~ "Tags" | ||||||
|       assert html =~ tag.bg_color |       assert html =~ tag.bg_color | ||||||
|     end |     end | ||||||
|  |  | ||||||
| @@ -47,22 +45,20 @@ defmodule CanneryWeb.TagLiveTest do | |||||||
|       assert html =~ tag.name |       assert html =~ tag.name | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, |              |> form(~s/form[phx-change="search"]/) | ||||||
|                search: %{search_term: tag.name} |              |> render_change(search: %{search_term: tag.name}) =~ tag.name | ||||||
|              ) |  | ||||||
|              |> render_change() =~ tag.name |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.tag_index_path(conn, :search, tag.name)) |       assert_patch(index_live, Routes.tag_index_path(conn, :search, tag.name)) | ||||||
|  |  | ||||||
|       refute index_live |       refute index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: "something_else"}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ tag.name |              |> render_change(search: %{search_term: "something_else"}) =~ tag.name | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.tag_index_path(conn, :search, "something_else")) |       assert_patch(index_live, Routes.tag_index_path(conn, :search, "something_else")) | ||||||
|  |  | ||||||
|       assert index_live |       assert index_live | ||||||
|              |> form(~s/form[phx-change="search"]/, search: %{search_term: ""}) |              |> form(~s/form[phx-change="search"]/) | ||||||
|              |> render_change() =~ tag.name |              |> render_change(search: %{search_term: ""}) =~ tag.name | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.tag_index_path(conn, :index)) |       assert_patch(index_live, Routes.tag_index_path(conn, :index)) | ||||||
|     end |     end | ||||||
| @@ -70,47 +66,43 @@ defmodule CanneryWeb.TagLiveTest do | |||||||
|     test "saves new tag", %{conn: conn} do |     test "saves new tag", %{conn: conn} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element("a", dgettext("actions", "New Tag")) |> render_click() =~ |       assert index_live |> element("a", "New Tag") |> render_click() =~ "New Tag" | ||||||
|                dgettext("actions", "New Tag") |  | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.tag_index_path(conn, :new)) |       assert_patch(index_live, Routes.tag_index_path(conn, :new)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#tag-form", tag: @invalid_attrs) |              |> form("#tag-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(tag: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#tag-form", tag: @create_attrs) |         |> form("#tag-form") | ||||||
|         |> render_submit() |         |> render_submit(tag: @create_attrs) | ||||||
|         |> follow_redirect(conn, Routes.tag_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.tag_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ dgettext("actions", "%{name} created successfully", name: "some name") |       assert html =~ "some name created successfully" | ||||||
|       assert html =~ "some bg-color" |       assert html =~ "#100000" | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "updates tag in listing", %{conn: conn, tag: tag} do |     test "updates tag in listing", %{conn: conn, tag: tag} do | ||||||
|       {:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index)) |       {:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert index_live |> element(~s/a[aria-label="Edit #{tag.name}"]/) |> render_click() =~ |       assert index_live |> element(~s/a[aria-label="Edit #{tag.name}"]/) |> render_click() =~ | ||||||
|                dgettext("actions", "Edit Tag") |                "Edit Tag" | ||||||
|  |  | ||||||
|       assert_patch(index_live, Routes.tag_index_path(conn, :edit, tag)) |       assert_patch(index_live, Routes.tag_index_path(conn, :edit, tag)) | ||||||
|  |  | ||||||
|       # assert index_live |       assert index_live | ||||||
|       #        |> form("#tag-form", tag: @invalid_attrs) |              |> form("#tag-form") | ||||||
|       #        |> render_change() =~ dgettext("errors", "can't be blank") |              |> render_change(tag: @invalid_attrs) =~ "can't be blank" | ||||||
|  |  | ||||||
|       {:ok, _view, html} = |       {:ok, _view, html} = | ||||||
|         index_live |         index_live | ||||||
|         |> form("#tag-form", tag: @update_attrs) |         |> form("#tag-form") | ||||||
|         |> render_submit() |         |> render_submit(tag: @update_attrs) | ||||||
|         |> follow_redirect(conn, Routes.tag_index_path(conn, :index)) |         |> follow_redirect(conn, Routes.tag_index_path(conn, :index)) | ||||||
|  |  | ||||||
|       assert html =~ |       assert html =~ "some updated name updated successfully" | ||||||
|                dgettext("prompts", "%{name} updated successfully", name: "some updated name") |       assert html =~ "#100001" | ||||||
|  |  | ||||||
|       assert html =~ "some updated bg-color" |  | ||||||
|     end |     end | ||||||
|  |  | ||||||
|     test "deletes tag in listing", %{conn: conn, tag: tag} do |     test "deletes tag in listing", %{conn: conn, tag: tag} do | ||||||
|   | |||||||
| @@ -4,19 +4,16 @@ defmodule CanneryWeb.ErrorViewTest do | |||||||
|   """ |   """ | ||||||
|  |  | ||||||
|   use CanneryWeb.ConnCase, async: true |   use CanneryWeb.ConnCase, async: true | ||||||
|   import CanneryWeb.Gettext |  | ||||||
|   # Bring render/3 and render_to_string/3 for testing custom views |   # Bring render/3 and render_to_string/3 for testing custom views | ||||||
|   import Phoenix.View |   import Phoenix.View | ||||||
|  |  | ||||||
|   @moduletag :error_view_test |   @moduletag :error_view_test | ||||||
|  |  | ||||||
|   test "renders 404.html" do |   test "renders 404.html" do | ||||||
|     assert render_to_string(CanneryWeb.ErrorView, "404.html", []) =~ |     assert render_to_string(CanneryWeb.ErrorView, "404.html", []) =~ "Not found" | ||||||
|              dgettext("errors", "Not found") |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   test "renders 500.html" do |   test "renders 500.html" do | ||||||
|     assert render_to_string(CanneryWeb.ErrorView, "500.html", []) =~ |     assert render_to_string(CanneryWeb.ErrorView, "500.html", []) =~ "Internal Server Error" | ||||||
|              dgettext("errors", "Internal Server Error") |  | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ defmodule CanneryWeb.ConnCase do | |||||||
|       import Plug.Conn |       import Plug.Conn | ||||||
|       import Phoenix.ConnTest |       import Phoenix.ConnTest | ||||||
|       # credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse |       # credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse | ||||||
|       import Cannery.Fixtures |       import Cannery.{DataCase, Fixtures} | ||||||
|       import CanneryWeb.ConnCase |       import CanneryWeb.ConnCase | ||||||
|  |  | ||||||
|       alias CanneryWeb.Router.Helpers, as: Routes |       alias CanneryWeb.Router.Helpers, as: Routes | ||||||
|   | |||||||
| @@ -48,4 +48,15 @@ defmodule Cannery.DataCase do | |||||||
|       end) |       end) | ||||||
|     end) |     end) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   @doc """ | ||||||
|  |   Generates a random string of any length, default of 12 | ||||||
|  |   """ | ||||||
|  |   @spec random_string(length :: non_neg_integer()) :: String.t() | ||||||
|  |   def random_string(length \\ 12) do | ||||||
|  |     :crypto.strong_rand_bytes(length) |> Base.url_encode64() |> binary_part(0, length) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def unique_user_email, do: "user#{System.unique_integer()}@example.com" | ||||||
|  |   def valid_user_password, do: "hello world!" | ||||||
| end | end | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ defmodule Cannery.Fixtures do | |||||||
|   This module defines test helpers for creating entities |   This module defines test helpers for creating entities | ||||||
|   """ |   """ | ||||||
|  |  | ||||||
|  |   import Cannery.DataCase | ||||||
|  |  | ||||||
|   alias Cannery.{ |   alias Cannery.{ | ||||||
|     Accounts, |     Accounts, | ||||||
|     Accounts.User, |     Accounts.User, | ||||||
| @@ -17,16 +19,13 @@ defmodule Cannery.Fixtures do | |||||||
|     Repo |     Repo | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   def unique_user_email, do: "user#{System.unique_integer()}@example.com" |  | ||||||
|   def valid_user_password, do: "hello world!" |  | ||||||
|  |  | ||||||
|   @spec user_fixture() :: User.t() |   @spec user_fixture() :: User.t() | ||||||
|   @spec user_fixture(attrs :: map()) :: User.t() |   @spec user_fixture(attrs :: map()) :: User.t() | ||||||
|   def user_fixture(attrs \\ %{}) do |   def user_fixture(attrs \\ %{}) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{ |     |> Enum.into(%{ | ||||||
|       "email" => unique_user_email(), |       email: unique_user_email(), | ||||||
|       "password" => valid_user_password() |       password: valid_user_password() | ||||||
|     }) |     }) | ||||||
|     |> Accounts.register_user() |     |> Accounts.register_user() | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
| @@ -37,8 +36,8 @@ defmodule Cannery.Fixtures do | |||||||
|   def admin_fixture(attrs \\ %{}) do |   def admin_fixture(attrs \\ %{}) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{ |     |> Enum.into(%{ | ||||||
|       "email" => unique_user_email(), |       email: unique_user_email(), | ||||||
|       "password" => valid_user_password() |       password: valid_user_password() | ||||||
|     }) |     }) | ||||||
|     |> Accounts.register_user() |     |> Accounts.register_user() | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
| @@ -77,9 +76,9 @@ defmodule Cannery.Fixtures do | |||||||
|   def shot_group_fixture(attrs \\ %{}, %User{} = user, %AmmoGroup{} = ammo_group) do |   def shot_group_fixture(attrs \\ %{}, %User{} = user, %AmmoGroup{} = ammo_group) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{ |     |> Enum.into(%{ | ||||||
|       "count" => 20, |       count: 20, | ||||||
|       "date" => ~N[2022-02-13 03:17:00], |       date: ~N[2022-02-13 03:17:00], | ||||||
|       "notes" => "some notes" |       notes: random_string() | ||||||
|     }) |     }) | ||||||
|     |> Cannery.ActivityLog.create_shot_group(user, ammo_group) |     |> Cannery.ActivityLog.create_shot_group(user, ammo_group) | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
| @@ -92,7 +91,7 @@ defmodule Cannery.Fixtures do | |||||||
|   @spec container_fixture(attrs :: map(), User.t()) :: Container.t() |   @spec container_fixture(attrs :: map(), User.t()) :: Container.t() | ||||||
|   def container_fixture(attrs \\ %{}, %User{} = user) do |   def container_fixture(attrs \\ %{}, %User{} = user) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{"name" => "My container", "type" => "Ammo can"}) |     |> Enum.into(%{name: random_string(), type: "Ammo can"}) | ||||||
|     |> Containers.create_container(user) |     |> Containers.create_container(user) | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
|   end |   end | ||||||
| @@ -104,7 +103,7 @@ defmodule Cannery.Fixtures do | |||||||
|   @spec ammo_type_fixture(attrs :: map(), User.t()) :: AmmoType.t() |   @spec ammo_type_fixture(attrs :: map(), User.t()) :: AmmoType.t() | ||||||
|   def ammo_type_fixture(attrs \\ %{}, %User{} = user) do |   def ammo_type_fixture(attrs \\ %{}, %User{} = user) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{"name" => "ammo_type"}) |     |> Enum.into(%{name: random_string(), class: :rifle}) | ||||||
|     |> Ammo.create_ammo_type(user) |     |> Ammo.create_ammo_type(user) | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
|   end |   end | ||||||
| @@ -132,10 +131,10 @@ defmodule Cannery.Fixtures do | |||||||
|       ) do |       ) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{ |     |> Enum.into(%{ | ||||||
|       "ammo_type_id" => ammo_type_id, |       ammo_type_id: ammo_type_id, | ||||||
|       "container_id" => container_id, |       container_id: container_id, | ||||||
|       "count" => 20, |       count: 20, | ||||||
|       "purchased_on" => Date.utc_today() |       purchased_on: Date.utc_today() | ||||||
|     }) |     }) | ||||||
|     |> Ammo.create_ammo_groups(multiplier, user) |     |> Ammo.create_ammo_groups(multiplier, user) | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
| @@ -149,9 +148,9 @@ defmodule Cannery.Fixtures do | |||||||
|   def tag_fixture(attrs \\ %{}, %User{} = user) do |   def tag_fixture(attrs \\ %{}, %User{} = user) do | ||||||
|     attrs |     attrs | ||||||
|     |> Enum.into(%{ |     |> Enum.into(%{ | ||||||
|       "bg_color" => "some bg-color", |       bg_color: "#100000", | ||||||
|       "name" => "some name", |       name: random_string(), | ||||||
|       "text_color" => "some text-color" |       text_color: "#000000" | ||||||
|     }) |     }) | ||||||
|     |> Containers.create_tag(user) |     |> Containers.create_tag(user) | ||||||
|     |> unwrap_ok_tuple() |     |> unwrap_ok_tuple() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user