Compare commits

..

4 Commits

Author SHA1 Message Date
8c95536ffd add selectable ammo types
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-23 22:07:25 -04:00
d9251c7e4c improve components 2023-03-23 00:21:26 -04:00
fe4e4f4f17 add length limits to all items
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-19 23:52:25 -04:00
e5e5449e8b improve modal accessibility
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-19 15:39:39 -04:00
72 changed files with 4639 additions and 2277 deletions

View File

@ -1,3 +1,10 @@
# 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 # v0.8.6
- Fix duplicate entries showing up - Fix duplicate entries showing up
- Show ammo packs under a type in a table by default - Show ammo packs under a type in a table by default

View File

@ -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

View File

@ -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

View File

@ -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.type() | :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.type() | :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,19 +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
) )
}, })
distinct: sg.id
)
end end
@spec list_shot_groups_filter_type(Queryable.t(), AmmoType.type() | :all) ::
Queryable.t()
defp list_shot_groups_filter_type(query, :rifle),
do: query |> where([at: at], at.type == :rifle)
defp list_shot_groups_filter_type(query, :pistol),
do: query |> where([at: at], at.type == :pistol)
defp list_shot_groups_filter_type(query, :shotgun),
do: query |> where([at: at], at.type == :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},

View File

@ -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)

View File

@ -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,69 @@ 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", type: :shotgun}, ...]
""" """
@spec list_ammo_types(User.t()) :: [AmmoType.t()] @spec list_ammo_types(User.t(), AmmoType.type() | :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.type() | :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.type() | :all) :: Queryable.t()
defp list_ammo_types_filter_type(query, :rifle), do: query |> where([at: at], at.type == :rifle)
defp list_ammo_types_filter_type(query, :pistol),
do: query |> where([at: at], at.type == :pistol)
defp list_ammo_types_filter_type(query, :shotgun),
do: query |> where([at: at], at.type == :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 +99,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 +394,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 +427,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.type() | :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.type == :rifle)
) do
Repo.all( defp list_ammo_groups_for_container_filter_type(query, :pistol),
from ag in AmmoGroup, do: query |> where([at: at], at.type == :pistol)
where: ag.container_id == ^container_id,
defp list_ammo_groups_for_container_filter_type(query, :shotgun),
do: query |> where([at: at], at.type == :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 +527,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 +560,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 +681,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 +743,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.type() | :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.type() | :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,
@ -718,17 +774,32 @@ defmodule Cannery.Ammo do
distinct: ag.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.type() | :all) :: Queryable.t()
defp list_ammo_groups_filter_on_type(query, :rifle),
do: query |> where([at: at], at.type == :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.type == :pistol)
defp list_ammo_groups_filter_on_type(query, :shotgun),
do: query |> where([at: at], at.type == :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

View File

@ -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 :type, 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,
type: type(),
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 type :: :rifle | :shotgun | :pistol | nil
@spec changeset_fields() :: [atom()] @spec changeset_fields() :: [atom()]
defp changeset_fields, defp changeset_fields,
do: [ do: [
:name, :name,
:desc, :desc,
:type,
: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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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}
@ -54,59 +55,47 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
} = 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("Price paid"), key: :price_paid}, |> TableComponent.maybe_compose_columns(
%{label: gettext("CPR"), key: :cpr} %{label: gettext("% left"), key: :remaining},
| columns show_used
] )
|> TableComponent.maybe_compose_columns(
columns =
if show_used do
[
%{label: gettext("Original Count"), key: :original_count}, %{label: gettext("Original Count"), key: :original_count},
%{label: gettext("% left"), key: :remaining} show_used
| columns )
] |> TableComponent.maybe_compose_columns(%{
else label: if(show_used, do: gettext("Current Count"), else: gettext("Count")),
columns key: :count
end })
|> TableComponent.maybe_compose_columns(
columns = [ %{label: gettext("Ammo type"), key: :ammo_type},
%{label: if(show_used, do: gettext("Current Count"), else: gettext("Count")), key: :count} ammo_type != []
| columns )
]
columns =
if ammo_type == [] do
columns
else
[%{label: gettext("Ammo type"), key: :ammo_type} | columns]
end
containers = containers =
ammo_groups ammo_groups
@ -140,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

View File

@ -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(:type) => AmmoType.type() | 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(:type, fn -> :all end)
|> assign_new(:actions, fn -> [] end) |> assign_new(:actions, fn -> [] end)
|> display_ammo_types() |> display_ammo_types()
@ -36,90 +39,118 @@ 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,
type: type,
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(type == :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(type == :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("Used rounds"), label: gettext("Total ever packs"),
key: :used_round_count, key: :historical_pack_count,
type: :used_round_count type: :historical_pack_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.++(
if show_used do
[
%{ %{
label: gettext("Used packs"), label: gettext("Used packs"),
key: :used_pack_count, key: :used_pack_count,
type: :used_pack_count type: :used_pack_count
}, },
%{ show_used
label: gettext("Total ever packs"),
key: :historical_pack_count,
type: :historical_pack_count
}
]
else
[]
end
) )
|> Kernel.++([ |> TableComponent.maybe_compose_columns(%{
%{label: gettext("Average CPR"), key: :avg_price_paid, type: :avg_price_paid}, label: gettext("Packs"),
%{label: gettext("Actions"), key: "actions", type: :actions, sortable: false} 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"),
key: :used_round_count,
type: :used_round_count
},
show_used
)
|> TableComponent.maybe_compose_columns(%{
label: gettext("Rounds"),
key: :round_count,
type: :round_count
})
|> TableComponent.maybe_compose_columns(filtered_columns)
|> TableComponent.maybe_compose_columns(
%{label: gettext("Type"), key: :type, type: :atom},
type in [:all, nil]
)
|> TableComponent.maybe_compose_columns(%{label: gettext("Name"), key: :name, type: :name})
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)
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)
@ -162,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
@ -179,7 +205,7 @@ 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}),

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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,7 +28,7 @@ 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)
@ -48,7 +48,7 @@ defmodule CanneryWeb.ExportController do
}) })
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)

View File

@ -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 =

View File

@ -8,11 +8,11 @@ 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()} {:ok, socket |> assign(type: :all, show_used: false, search: search) |> display_ammo_groups()}
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(type: :all, show_used: false, search: nil) |> display_ammo_groups()}
end end
@impl true @impl true
@ -119,10 +119,36 @@ defmodule CanneryWeb.AmmoGroupLive.Index do
{:noreply, socket} {:noreply, socket}
end end
def handle_event("change_type", %{"ammo_type" => %{"type" => "rifle"}}, socket) do
{:noreply, socket |> assign(:type, :rifle) |> display_ammo_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "shotgun"}}, socket) do
{:noreply, socket |> assign(:type, :shotgun) |> display_ammo_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "pistol"}}, socket) do
{:noreply, socket |> assign(:type, :pistol) |> display_ammo_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => _all}}, socket) do
{:noreply, socket |> assign(:type, :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: %{
type: type,
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, type, 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 +156,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

View File

@ -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,42 @@
<.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_type"
phx-submit="change_type"
class="flex items-center"
>
<%= label(f, :type, gettext("Type"), class: "title text-primary-600 text-lg text-center") %>
<%= select(
f,
:type,
[
{gettext("All"), :all},
{gettext("Rifle"), :rifle},
{gettext("Shotgun"), :shotgun},
{gettext("Pistol"), :pistol}
],
class: "mx-2 my-1 min-w-md input input-primary",
value: @type
) %>
</.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,
@ -179,6 +199,7 @@
</:actions> </:actions>
</.live_component> </.live_component>
<% end %> <% end %>
<% end %>
</div> </div>
<%= case @live_action do %> <%= case @live_action do %>

View File

@ -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, :type, gettext("Type"), class: "title text-lg text-primary-600") %>
<%= select(
f,
:type,
[{gettext("Rifle"), :rifle}, {gettext("Shotgun"), :shotgun}, {gettext("Pistol"), :pistol}],
class: "text-center col-span-2 input input-primary",
maxlength: 255
) %>
<%= error_tag(f, :type, "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, :type) 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, :type) == :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, :type) == :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, :type) == :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, :type) 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, :type) == :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, :type) 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, :type) == :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, :type) 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"),

View File

@ -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(type: :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(type: :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_type", %{"ammo_type" => %{"type" => "rifle"}}, socket) do
socket |> assign(ammo_types: Ammo.list_ammo_types(search, current_user)) {:noreply, socket |> assign(:type, :rifle) |> list_ammo_types()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "shotgun"}}, socket) do
{:noreply, socket |> assign(:type, :shotgun) |> list_ammo_types()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "pistol"}}, socket) do
{:noreply, socket |> assign(:type, :pistol) |> list_ammo_types()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => _all}}, socket) do
{:noreply, socket |> assign(:type, :all) |> list_ammo_types()}
end
defp list_ammo_types(
%{assigns: %{type: type, search: search, current_user: current_user}} = socket
) do
socket
|> assign(
ammo_types: Ammo.list_ammo_types(search, current_user, type),
ammo_types_count: Ammo.get_ammo_types_count!(current_user)
)
end end
end end

View File

@ -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_type"
phx-submit="change_type"
class="flex items-center"
>
<%= label(f, :type, gettext("Type"), class: "title text-primary-600 text-lg text-center") %>
<%= select(
f,
:type,
[
{gettext("All"), :all},
{gettext("Rifle"), :rifle},
{gettext("Shotgun"), :shotgun},
{gettext("Pistol"), :pistol}
],
class: "mx-2 my-1 min-w-md input input-primary",
value: @type
) %>
</.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}
type={@type}
> >
<: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">

View File

@ -7,28 +7,6 @@ defmodule CanneryWeb.AmmoTypeLive.Show do
alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType, Containers} alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType, Containers}
alias CanneryWeb.Endpoint alias CanneryWeb.Endpoint
@fields_list [
%{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("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, socket), def mount(_params, _session, socket),
do: {:ok, socket |> assign(show_used: false, view_table: true)} do: {:ok, socket |> assign(show_used: false, view_table: true)}
@ -65,8 +43,8 @@ defmodule CanneryWeb.AmmoTypeLive.Show do
socket, socket,
%AmmoType{name: ammo_type_name} = 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
@ -125,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
@ -138,6 +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{type: type}) do
[
%{label: gettext("Cartridge:"), key: :cartridge, type: :string},
%{
label: if(type == :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)
end end

View File

@ -42,9 +42,26 @@
<hr class="hr" /> <hr class="hr" />
<%= if @fields_to_display do %> <%= if @ammo_type.type || @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("Type") %>
</h3>
<span class="text-primary-600">
<%= case @ammo_type.type 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 %>

View File

@ -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") %>

View File

@ -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 %>

View File

@ -11,7 +11,7 @@ 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(type: :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
@ -82,22 +82,34 @@ 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_type", %{"ammo_type" => %{"type" => "rifle"}}, socket) do
{:noreply, socket |> assign(:type, :rifle) |> render_container()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "shotgun"}}, socket) do
{:noreply, socket |> assign(:type, :shotgun) |> render_container()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "pistol"}}, socket) do
{:noreply, socket |> assign(:type, :pistol) |> render_container()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => _all}}, socket) do
{:noreply, socket |> assign(:type, :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: %{type: type, 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, type, 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)
@ -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,

View File

@ -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_type"
phx-submit="change_type"
class="flex items-center"
>
<%= label(f, :type, gettext("Type"), class: "title text-primary-600 text-lg text-center") %>
<%= select(
f,
:type,
[
{gettext("All"), :all},
{gettext("Rifle"), :rifle},
{gettext("Shotgun"), :shotgun},
{gettext("Pistol"), :pistol}
],
class: "mx-2 my-1 min-w-md input input-primary",
value: @type
) %>
</.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,7 +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={@show_used} 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">

View File

@ -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") %>

View File

@ -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"

View File

@ -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(type: :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(type: :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_type", %{"ammo_type" => %{"type" => "rifle"}}, socket) do
{:noreply, socket |> assign(:type, :rifle) |> display_shot_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "shotgun"}}, socket) do
{:noreply, socket |> assign(:type, :shotgun) |> display_shot_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => "pistol"}}, socket) do
{:noreply, socket |> assign(:type, :pistol) |> display_shot_groups()}
end
def handle_event("change_type", %{"ammo_type" => %{"type" => _all}}, socket) do
{:noreply, socket |> assign(:type, :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: %{type: type, search: search, current_user: current_user}} = socket
) do
shot_groups = ActivityLog.list_shot_groups(search, type, 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)

View File

@ -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_type"
phx-submit="change_type"
class="flex items-center"
>
<%= label(f, :type, gettext("Type"), class: "title text-primary-600 text-lg text-center") %>
<%= select(
f,
:type,
[
{gettext("All"), :all},
{gettext("Rifle"), :rifle},
{gettext("Shotgun"), :shotgun},
{gettext("Pistol"), :pistol}
],
class: "mx-2 my-1 min-w-md input input-primary",
value: @type
) %>
</.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,

View File

@ -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") %>

View File

@ -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)}>

View File

@ -4,7 +4,7 @@ defmodule Cannery.MixProject do
def project do def project do
[ [
app: :cannery, app: :cannery,
version: "0.8.6", 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(),

View File

@ -12,12 +12,12 @@ msgstr ""
#: lib/cannery_web/live/ammo_group_live/index.ex:54 #: lib/cannery_web/live/ammo_group_live/index.ex:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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 ""

View File

@ -25,12 +25,12 @@ msgstr ""
## 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:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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

View File

@ -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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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"
@ -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

View File

@ -12,12 +12,12 @@ msgstr ""
#: lib/cannery_web/live/ammo_group_live/index.ex:54 #: lib/cannery_web/live/ammo_group_live/index.ex:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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

View File

@ -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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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 ""
@ -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!"

View File

@ -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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -25,12 +25,12 @@ msgstr ""
## 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:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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

View File

@ -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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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"
@ -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!"

View File

@ -25,12 +25,12 @@ msgstr ""
# # 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:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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

View File

@ -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 dutilisateur·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 "nest pas valide" msgstr "nest 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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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"
@ -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!"

View File

@ -23,12 +23,12 @@ msgstr ""
## 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:54
#: lib/cannery_web/live/ammo_group_live/index.ex:62 #: lib/cannery_web/live/ammo_group_live/index.ex:62
#: 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:105 #: lib/cannery_web/live/ammo_group_live/index.html.heex:125
#: 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:122 #: lib/cannery_web/live/ammo_group_live/index.html.heex:142
#: 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:144 #: lib/cannery_web/live/ammo_group_live/index.html.heex:164
#: 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,45 +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:98 #: lib/cannery_web/live/ammo_group_live/index.html.heex:118
#, 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:97 #: lib/cannery_web/live/ammo_group_live/index.html.heex:117
#, 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:156 #: lib/cannery_web/live/ammo_group_live/index.html.heex:176
#, 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:171 #: lib/cannery_web/live/ammo_group_live/index.html.heex:191
#: 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:132 #: lib/cannery_web/live/ammo_group_live/index.html.heex:152
#: lib/cannery_web/live/ammo_type_live/show.html.heex:189 #: 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

View File

@ -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:1043 #: lib/cannery/ammo.ex:1114
#, 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 ""

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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 ""
@ -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!"

View File

@ -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:49 #: 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:169 #: lib/cannery_web/live/ammo_group_live/index.html.heex:189
#: 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 ""
@ -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!"

View File

@ -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

View File

@ -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

View File

@ -38,50 +38,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
@ -371,4 +327,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 type <- ["rifle", "shotgun", "pistol"] do
other_ammo_type = ammo_type_fixture(%{"type" => type}, 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(%{"type" => "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(%{"type" => "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(%{"type" => "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

View File

@ -9,7 +9,6 @@ defmodule Cannery.AmmoTest do
@moduletag :ammo_test @moduletag :ammo_test
describe "ammo_types" do
@valid_attrs %{ @valid_attrs %{
"bullet_type" => "some bullet_type", "bullet_type" => "some bullet_type",
"case_material" => "some case_material", "case_material" => "some case_material",
@ -35,28 +34,30 @@ defmodule Cannery.AmmoTest do
"grains" => nil "grains" => nil
} }
describe "list_ammo_types/2" do
setup do setup do
current_user = user_fixture() current_user = user_fixture()
[ammo_type: ammo_type_fixture(current_user), current_user: current_user]
end
test "list_ammo_types/1 returns all ammo_types", rifle_ammo_type =
%{ammo_type: ammo_type, current_user: current_user} do
assert Ammo.list_ammo_types(current_user) == [ammo_type]
end
test "list_ammo_types/2 returns relevant ammo_types for a user",
%{current_user: current_user} do
ammo_type_a =
%{"name" => "bullets", "desc" => "has some pews in it", "grains" => 5}
|> ammo_type_fixture(current_user)
ammo_type_b =
%{"name" => "hollows", "grains" => 3}
|> ammo_type_fixture(current_user)
ammo_type_c =
%{ %{
"name" => "bullets",
"type" => "rifle",
"desc" => "has some pews in it",
"grains" => 5
}
|> ammo_type_fixture(current_user)
shotgun_ammo_type =
%{
"name" => "hollows",
"type" => "shotgun",
"grains" => 3
}
|> ammo_type_fixture(current_user)
pistol_ammo_type =
%{
"type" => "pistol",
"name" => "jackets", "name" => "jackets",
"desc" => "brass shell", "desc" => "brass shell",
"tracer" => true "tracer" => true
@ -70,23 +71,78 @@ defmodule Cannery.AmmoTest do
} }
|> ammo_type_fixture(user_fixture()) |> ammo_type_fixture(user_fixture())
[
rifle_ammo_type: rifle_ammo_type,
shotgun_ammo_type: shotgun_ammo_type,
pistol_ammo_type: pistol_ammo_type,
current_user: current_user
]
end
test "list_ammo_types/2 returns all ammo_types", %{
rifle_ammo_type: rifle_ammo_type,
shotgun_ammo_type: shotgun_ammo_type,
pistol_ammo_type: pistol_ammo_type,
current_user: current_user
} do
results = Ammo.list_ammo_types(current_user, :all)
assert results |> Enum.count() == 3
assert rifle_ammo_type in results
assert shotgun_ammo_type in results
assert pistol_ammo_type in results
end
test "list_ammo_types/2 returns rifle ammo_types", %{
rifle_ammo_type: rifle_ammo_type,
current_user: current_user
} do
assert [^rifle_ammo_type] = Ammo.list_ammo_types(current_user, :rifle)
end
test "list_ammo_types/2 returns shotgun ammo_types", %{
shotgun_ammo_type: shotgun_ammo_type,
current_user: current_user
} do
assert [^shotgun_ammo_type] = Ammo.list_ammo_types(current_user, :shotgun)
end
test "list_ammo_types/2 returns pistol ammo_types", %{
pistol_ammo_type: pistol_ammo_type,
current_user: current_user
} do
assert [^pistol_ammo_type] = Ammo.list_ammo_types(current_user, :pistol)
end
test "list_ammo_types/2 returns relevant ammo_types for a user", %{
rifle_ammo_type: rifle_ammo_type,
shotgun_ammo_type: shotgun_ammo_type,
pistol_ammo_type: pistol_ammo_type,
current_user: current_user
} do
# name # name
assert Ammo.list_ammo_types("bullet", current_user) == [ammo_type_a] assert Ammo.list_ammo_types("bullet", current_user, :all) == [rifle_ammo_type]
assert Ammo.list_ammo_types("bullets", current_user) == [ammo_type_a] assert Ammo.list_ammo_types("bullets", current_user, :all) == [rifle_ammo_type]
assert Ammo.list_ammo_types("hollow", current_user) == [ammo_type_b] assert Ammo.list_ammo_types("hollow", current_user, :all) == [shotgun_ammo_type]
assert Ammo.list_ammo_types("jacket", current_user) == [ammo_type_c] assert Ammo.list_ammo_types("jacket", current_user, :all) == [pistol_ammo_type]
# desc # desc
assert Ammo.list_ammo_types("pew", current_user) == [ammo_type_a] assert Ammo.list_ammo_types("pew", current_user, :all) == [rifle_ammo_type]
assert Ammo.list_ammo_types("brass", current_user) == [ammo_type_c] assert Ammo.list_ammo_types("brass", current_user, :all) == [pistol_ammo_type]
assert Ammo.list_ammo_types("shell", current_user) == [ammo_type_c] assert Ammo.list_ammo_types("shell", current_user, :all) == [pistol_ammo_type]
# grains (integer) # grains (integer)
assert Ammo.list_ammo_types("5", current_user) == [ammo_type_a] assert Ammo.list_ammo_types("5", current_user, :all) == [rifle_ammo_type]
assert Ammo.list_ammo_types("3", current_user) == [ammo_type_b] assert Ammo.list_ammo_types("3", current_user, :all) == [shotgun_ammo_type]
# tracer (boolean) # tracer (boolean)
assert Ammo.list_ammo_types("tracer", current_user) == [ammo_type_c] assert Ammo.list_ammo_types("tracer", current_user, :all) == [pistol_ammo_type]
end
end
describe "ammo types" do
setup do
current_user = user_fixture()
[ammo_type: ammo_type_fixture(current_user), current_user: current_user]
end end
test "get_ammo_type!/2 returns the ammo_type with given id", test "get_ammo_type!/2 returns the ammo_type with given id",
@ -94,6 +150,23 @@ defmodule Cannery.AmmoTest do
assert Ammo.get_ammo_type!(ammo_type.id, current_user) == ammo_type assert Ammo.get_ammo_type!(ammo_type.id, current_user) == ammo_type
end end
test "get_ammo_types_count!/1 returns the correct amount of ammo",
%{current_user: current_user} do
assert Ammo.get_ammo_types_count!(current_user) == 1
ammo_type_fixture(current_user)
assert Ammo.get_ammo_types_count!(current_user) == 2
ammo_type_fixture(current_user)
assert Ammo.get_ammo_types_count!(current_user) == 3
other_user = user_fixture()
assert Ammo.get_ammo_types_count!(other_user) == 0
ammo_type_fixture(other_user)
assert Ammo.get_ammo_types_count!(other_user) == 1
end
test "create_ammo_type/2 with valid data creates a ammo_type", test "create_ammo_type/2 with valid data creates a ammo_type",
%{current_user: current_user} do %{current_user: current_user} do
assert {:ok, %AmmoType{} = ammo_type} = Ammo.create_ammo_type(@valid_attrs, current_user) assert {:ok, %AmmoType{} = ammo_type} = Ammo.create_ammo_type(@valid_attrs, current_user)
@ -653,8 +726,60 @@ defmodule Cannery.AmmoTest do
] ]
end end
test "list_ammo_groups/3 returns all ammo_groups", test "get_ammo_groups_count!/2 returns the correct amount of ammo",
%{ %{ammo_type: ammo_type, container: container, current_user: current_user} do
assert Ammo.get_ammo_groups_count!(current_user) == 1
ammo_group_fixture(ammo_type, container, current_user)
assert Ammo.get_ammo_groups_count!(current_user) == 2
ammo_group_fixture(ammo_type, container, current_user)
assert Ammo.get_ammo_groups_count!(current_user) == 3
other_user = user_fixture()
assert Ammo.get_ammo_groups_count!(other_user) == 0
assert Ammo.get_ammo_groups_count!(other_user, true) == 0
other_ammo_type = ammo_type_fixture(other_user)
other_container = container_fixture(other_user)
{1, [another_ammo_group]} =
ammo_group_fixture(%{"count" => 30}, other_ammo_type, other_container, other_user)
shot_group_fixture(%{"count" => 30}, other_user, another_ammo_group)
assert Ammo.get_ammo_groups_count!(other_user) == 0
assert Ammo.get_ammo_groups_count!(other_user, true) == 1
end
test "list_ammo_groups/4 returns all ammo_groups for a type" do
current_user = user_fixture()
container = container_fixture(current_user)
rifle_ammo_type = ammo_type_fixture(%{"type" => "rifle"}, current_user)
{1, [rifle_ammo_group]} = ammo_group_fixture(rifle_ammo_type, container, current_user)
shotgun_ammo_type = ammo_type_fixture(%{"type" => "shotgun"}, current_user)
{1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_ammo_type, container, current_user)
pistol_ammo_type = ammo_type_fixture(%{"type" => "pistol"}, current_user)
{1, [pistol_ammo_group]} = ammo_group_fixture(pistol_ammo_type, container, current_user)
assert [^rifle_ammo_group] = Ammo.list_ammo_groups(nil, :rifle, current_user, false)
assert [^shotgun_ammo_group] = Ammo.list_ammo_groups(nil, :shotgun, current_user, false)
assert [^pistol_ammo_group] = Ammo.list_ammo_groups(nil, :pistol, current_user, false)
ammo_groups = Ammo.list_ammo_groups(nil, :all, current_user, false)
assert Enum.count(ammo_groups) == 3
assert rifle_ammo_group in ammo_groups
assert shotgun_ammo_group in ammo_groups
assert pistol_ammo_group in ammo_groups
ammo_groups = Ammo.list_ammo_groups(nil, nil, current_user, false)
assert Enum.count(ammo_groups) == 3
assert rifle_ammo_group in ammo_groups
assert shotgun_ammo_group in ammo_groups
assert pistol_ammo_group in ammo_groups
end
test "list_ammo_groups/4 returns all relevant ammo_groups including used", %{
ammo_type: ammo_type, ammo_type: ammo_type,
ammo_group: ammo_group, ammo_group: ammo_group,
container: container, container: container,
@ -666,14 +791,15 @@ defmodule Cannery.AmmoTest do
shot_group_fixture(%{"count" => 30}, current_user, another_ammo_group) shot_group_fixture(%{"count" => 30}, current_user, another_ammo_group)
another_ammo_group = Ammo.get_ammo_group!(another_ammo_group_id, current_user) another_ammo_group = Ammo.get_ammo_group!(another_ammo_group_id, current_user)
assert Ammo.list_ammo_groups(nil, false, current_user) == [ammo_group] assert Ammo.list_ammo_groups(nil, :all, current_user, false) == [ammo_group]
assert Ammo.list_ammo_groups(nil, true, current_user) ammo_groups = Ammo.list_ammo_groups(nil, :all, current_user, true)
|> Enum.sort_by(fn %{count: count} -> count end) == [another_ammo_group, ammo_group] assert Enum.count(ammo_groups) == 2
assert another_ammo_group in ammo_groups
assert ammo_group in ammo_groups
end end
test "list_ammo_groups/3 returns relevant ammo groups when searched", test "list_ammo_groups/4 returns relevant ammo groups when searched", %{
%{
ammo_type: ammo_type, ammo_type: ammo_type,
ammo_group: ammo_group, ammo_group: ammo_group,
container: container, container: container,
@ -695,49 +821,80 @@ defmodule Cannery.AmmoTest do
{1, [fantastic_ammo_group]} = {1, [fantastic_ammo_group]} =
ammo_group_fixture(%{"count" => 47}, ammo_type, another_container, current_user) ammo_group_fixture(%{"count" => 47}, ammo_type, another_container, current_user)
assert Ammo.list_ammo_groups(nil, false, current_user) ammo_groups = Ammo.list_ammo_groups(nil, :all, current_user, false)
|> Enum.sort_by(fn %{count: count} -> count end) == assert Enum.count(ammo_groups) == 4
[fantastic_ammo_group, amazing_ammo_group, another_ammo_group, ammo_group] assert fantastic_ammo_group in ammo_groups
assert amazing_ammo_group in ammo_groups
assert another_ammo_group in ammo_groups
assert ammo_group in ammo_groups
# search works for ammo group attributes # search works for ammo group attributes
assert Ammo.list_ammo_groups("cool", true, current_user) == [another_ammo_group] assert Ammo.list_ammo_groups("cool", :all, current_user, true) == [another_ammo_group]
# search works for ammo type attributes # search works for ammo type attributes
assert Ammo.list_ammo_groups("amazing", true, current_user) == [amazing_ammo_group] assert Ammo.list_ammo_groups("amazing", :all, current_user, true) == [amazing_ammo_group]
# search works for container attributes # search works for container attributes
assert Ammo.list_ammo_groups("fantastic", true, current_user) == [fantastic_ammo_group] assert Ammo.list_ammo_groups("fantastic", :all, current_user, true) ==
[fantastic_ammo_group]
# search works for container tag attributes # search works for container tag attributes
assert Ammo.list_ammo_groups("stupendous", true, current_user) == [fantastic_ammo_group] assert Ammo.list_ammo_groups("stupendous", :all, current_user, true) ==
[fantastic_ammo_group]
assert Ammo.list_ammo_groups("random", true, current_user) == [] assert Ammo.list_ammo_groups("random", :all, current_user, true) == []
end end
test "list_ammo_groups_for_type/2 returns all ammo_groups for a type", test "list_ammo_groups_for_type/3 returns all ammo_groups for a type", %{
%{
ammo_type: ammo_type,
container: container, container: container,
ammo_group: ammo_group,
current_user: current_user current_user: current_user
} do } do
another_ammo_type = ammo_type_fixture(current_user) ammo_type = ammo_type_fixture(current_user)
{1, [_another]} = ammo_group_fixture(another_ammo_type, container, current_user) {1, [ammo_group]} = ammo_group_fixture(ammo_type, container, current_user)
assert [^ammo_group] = Ammo.list_ammo_groups_for_type(ammo_type, current_user)
assert Ammo.list_ammo_groups_for_type(ammo_type, current_user) == [ammo_group] shot_group_fixture(current_user, ammo_group)
ammo_group = Ammo.get_ammo_group!(ammo_group.id, current_user)
assert [] == Ammo.list_ammo_groups_for_type(ammo_type, current_user)
assert [^ammo_group] = Ammo.list_ammo_groups_for_type(ammo_type, current_user, true)
end end
test "list_ammo_groups_for_container/2 returns all ammo_groups for a container", test "list_ammo_groups_for_container/3 returns all ammo_groups for a container" do
%{ current_user = user_fixture()
ammo_type: ammo_type, container = container_fixture(current_user)
container: container,
ammo_group: ammo_group, rifle_ammo_type = ammo_type_fixture(%{"type" => "rifle"}, current_user)
current_user: current_user {1, [rifle_ammo_group]} = ammo_group_fixture(rifle_ammo_type, container, current_user)
} do shotgun_ammo_type = ammo_type_fixture(%{"type" => "shotgun"}, current_user)
{1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_ammo_type, container, current_user)
pistol_ammo_type = ammo_type_fixture(%{"type" => "pistol"}, current_user)
{1, [pistol_ammo_group]} = ammo_group_fixture(pistol_ammo_type, container, current_user)
another_container = container_fixture(current_user) another_container = container_fixture(current_user)
{1, [_another]} = ammo_group_fixture(ammo_type, another_container, current_user) ammo_group_fixture(rifle_ammo_type, another_container, current_user)
ammo_group_fixture(shotgun_ammo_type, another_container, current_user)
ammo_group_fixture(pistol_ammo_type, another_container, current_user)
assert Ammo.list_ammo_groups_for_container(container, current_user) == [ammo_group] assert [^rifle_ammo_group] =
Ammo.list_ammo_groups_for_container(container, :rifle, current_user)
assert [^shotgun_ammo_group] =
Ammo.list_ammo_groups_for_container(container, :shotgun, current_user)
assert [^pistol_ammo_group] =
Ammo.list_ammo_groups_for_container(container, :pistol, current_user)
ammo_groups = Ammo.list_ammo_groups_for_container(container, :all, current_user)
assert Enum.count(ammo_groups) == 3
assert rifle_ammo_group in ammo_groups
assert shotgun_ammo_group in ammo_groups
assert pistol_ammo_group in ammo_groups
ammo_groups = Ammo.list_ammo_groups_for_container(container, nil, current_user)
assert Enum.count(ammo_groups) == 3
assert rifle_ammo_group in ammo_groups
assert shotgun_ammo_group in ammo_groups
assert pistol_ammo_group in ammo_groups
end end
test "get_ammo_groups_count_for_type/2 returns count of ammo_groups for a type", %{ test "get_ammo_groups_count_for_type/2 returns count of ammo_groups for a type", %{
@ -785,8 +942,7 @@ defmodule Cannery.AmmoTest do
assert %{^another_ammo_type_id => 1} = ammo_groups_count assert %{^another_ammo_type_id => 1} = ammo_groups_count
end end
test "list_staged_ammo_groups/1 returns all ammo_groups that are staged", test "list_staged_ammo_groups/1 returns all ammo_groups that are staged", %{
%{
ammo_type: ammo_type, ammo_type: ammo_type,
container: container, container: container,
current_user: current_user current_user: current_user
@ -816,8 +972,7 @@ defmodule Cannery.AmmoTest do
assert %{^another_ammo_group_id => ^another_ammo_group} = ammo_groups assert %{^another_ammo_group_id => ^another_ammo_group} = ammo_groups
end end
test "create_ammo_groups/3 with valid data creates a ammo_group", test "create_ammo_groups/3 with valid data creates a ammo_group", %{
%{
ammo_type: ammo_type, ammo_type: ammo_type,
container: container, container: container,
current_user: current_user current_user: current_user
@ -832,8 +987,7 @@ defmodule Cannery.AmmoTest do
assert ammo_group.price_paid == 120.5 assert ammo_group.price_paid == 120.5
end end
test "create_ammo_groups/3 with valid data creates multiple ammo_groups", test "create_ammo_groups/3 with valid data creates multiple ammo_groups", %{
%{
ammo_type: ammo_type, ammo_type: ammo_type,
container: container, container: container,
current_user: current_user current_user: current_user

View File

@ -28,14 +28,14 @@ defmodule Cannery.ContainersTest do
"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,
@ -186,9 +186,9 @@ defmodule Cannery.ContainersTest do
test "create_tag/2 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/2 with invalid data returns error changeset", test "create_tag/2 with invalid data returns error changeset",
@ -198,9 +198,9 @@ defmodule Cannery.ContainersTest do
test "update_tag/3 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/3 with invalid data returns error changeset", test "update_tag/3 with invalid data returns error changeset",

View File

@ -66,6 +66,60 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
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(%{"type" => "rifle"}, current_user)
{1, [rifle_ammo_group]} = ammo_group_fixture(rifle_type, container, current_user)
shotgun_type = ammo_type_fixture(%{"type" => "shotgun"}, current_user)
{1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_type, container, current_user)
pistol_type = ammo_type_fixture(%{"type" => "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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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))
@ -142,7 +196,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
|> 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 =~ dgettext("prompts", "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

View File

@ -74,28 +74,77 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
assert html =~ ammo_type.bullet_type assert html =~ ammo_type.bullet_type
end end
test "can sort by type", %{conn: conn, current_user: current_user} do
rifle_type = ammo_type_fixture(%{"type" => "rifle"}, current_user)
shotgun_type = ammo_type_fixture(%{"type" => "shotgun"}, current_user)
pistol_type = ammo_type_fixture(%{"type" => "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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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
@ -114,8 +163,8 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
{: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)
@ -138,8 +187,8 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
{: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)
@ -163,8 +212,8 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
{: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)
@ -188,10 +237,10 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
{:ok, _view, html} = {:ok, _view, html} =
index_live index_live
|> form("#ammo_type-form", |> form("#ammo_type-form")
|> render_submit(
ammo_type: Map.merge(@create_attrs, %{"bullet_type" => "some updated bullet_type"}) 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)
@ -276,8 +325,8 @@ defmodule CanneryWeb.AmmoTypeLiveTest do
{: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)

View File

@ -6,7 +6,7 @@ defmodule CanneryWeb.ContainerLiveTest do
use CanneryWeb.ConnCase use CanneryWeb.ConnCase
import Phoenix.LiveViewTest import Phoenix.LiveViewTest
import CanneryWeb.Gettext import CanneryWeb.Gettext
alias Cannery.{Containers, Repo} alias Cannery.Containers
@moduletag :container_live_test @moduletag :container_live_test
@ -34,10 +34,6 @@ defmodule CanneryWeb.ContainerLiveTest do
"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} # @invalid_attrs %{desc: nil, location: nil, name: nil, type: nil}
@ -53,15 +49,6 @@ defmodule CanneryWeb.ContainerLiveTest do
%{ammo_type: ammo_type, ammo_group: ammo_group} %{ammo_type: ammo_type, ammo_group: ammo_group}
end 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
describe "Index" do describe "Index" do
setup [:register_and_log_in_user, :create_container] setup [:register_and_log_in_user, :create_container]
@ -263,6 +250,60 @@ defmodule CanneryWeb.ContainerLiveTest do
assert html =~ dgettext("prompts", "%{name} updated successfully", name: container.name) assert html =~ dgettext("prompts", "%{name} updated successfully", name: container.name)
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(%{"type" => "rifle"}, current_user)
{1, [rifle_ammo_group]} = ammo_group_fixture(rifle_type, container, current_user)
shotgun_type = ammo_type_fixture(%{"type" => "shotgun"}, current_user)
{1, [shotgun_ammo_group]} = ammo_group_fixture(shotgun_type, container, current_user)
pistol_type = ammo_type_fixture(%{"type" => "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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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
@ -289,47 +330,4 @@ defmodule CanneryWeb.ContainerLiveTest do
assert html =~ "\n20\n" assert html =~ "\n20\n"
end end
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 =~ "\n20\n"
html =
show_live
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/)
|> render_click()
assert html =~ ammo_type_name
assert html =~ "\n20\n"
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 =~ "\n20\n"
html =
show_live
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/)
|> render_click()
assert html =~ ammo_type_name
assert html =~ "\n20\n"
assert html =~ "Empty"
end
end
end end

View File

@ -24,7 +24,12 @@ defmodule CanneryWeb.RangeLiveTest do
%{"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
@ -37,6 +42,71 @@ defmodule CanneryWeb.RangeLiveTest do
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(%{"type" => "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(%{"type" => "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(%{"type" => "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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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_type"]/)
|> render_change(ammo_type: %{type: :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))

View File

@ -10,14 +10,14 @@ defmodule CanneryWeb.TagLiveTest do
@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 %{ # @invalid_attrs %{
@ -86,7 +86,7 @@ defmodule CanneryWeb.TagLiveTest do
|> 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 =~ dgettext("actions", "%{name} created successfully", name: "some name")
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
@ -110,7 +110,7 @@ defmodule CanneryWeb.TagLiveTest do
assert html =~ assert html =~
dgettext("prompts", "%{name} updated successfully", name: "some updated name") dgettext("prompts", "%{name} updated successfully", name: "some updated name")
assert html =~ "some updated bg-color" assert html =~ "#100001"
end end
test "deletes tag in listing", %{conn: conn, tag: tag} do test "deletes tag in listing", %{conn: conn, tag: tag} do

View File

@ -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

View File

@ -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

View File

@ -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,9 +19,6 @@ 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
@ -79,7 +78,7 @@ defmodule Cannery.Fixtures do
|> 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(), "type" => "rifle"})
|> Ammo.create_ammo_type(user) |> Ammo.create_ammo_type(user)
|> unwrap_ok_tuple() |> unwrap_ok_tuple()
end end
@ -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()