add models, context and liveviews

This commit is contained in:
shibao 2021-09-02 23:31:14 -04:00 committed by oliviasculley
parent feba4e1d14
commit d6ddf2a9bb
52 changed files with 2325 additions and 13 deletions

View File

@ -45,7 +45,7 @@ let socket = new Socket("/socket", {params: {token: window.userToken}})
// # max_age: 1209600 is equivalent to two weeks in seconds // # max_age: 1209600 is equivalent to two weeks in seconds
// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do // case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
// {:ok, user_id} -> // {:ok, user_id} ->
// {:ok, assign(socket, :user, user_id)} // {:ok, socket |> assign(:user, user_id)}
// {:error, reason} -> // {:error, reason} ->
// :error // :error
// end // end

200
lib/cannery/ammo.ex Normal file
View File

@ -0,0 +1,200 @@
defmodule Cannery.Ammo do
@moduledoc """
The Ammo context.
"""
import Ecto.Query, warn: false
alias Cannery.Repo
alias Cannery.Ammo.AmmoType
@doc """
Returns the list of ammo_types.
## Examples
iex> list_ammo_types()
[%AmmoType{}, ...]
"""
def list_ammo_types do
Repo.all(AmmoType)
end
@doc """
Gets a single ammo_type.
Raises `Ecto.NoResultsError` if the Ammo type does not exist.
## Examples
iex> get_ammo_type!(123)
%AmmoType{}
iex> get_ammo_type!(456)
** (Ecto.NoResultsError)
"""
def get_ammo_type!(id), do: Repo.get!(AmmoType, id)
@doc """
Creates a ammo_type.
## Examples
iex> create_ammo_type(%{field: value})
{:ok, %AmmoType{}}
iex> create_ammo_type(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_ammo_type(attrs \\ %{}) do
%AmmoType{}
|> AmmoType.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a ammo_type.
## Examples
iex> update_ammo_type(ammo_type, %{field: new_value})
{:ok, %AmmoType{}}
iex> update_ammo_type(ammo_type, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_ammo_type(%AmmoType{} = ammo_type, attrs) do
ammo_type
|> AmmoType.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a ammo_type.
## Examples
iex> delete_ammo_type(ammo_type)
{:ok, %AmmoType{}}
iex> delete_ammo_type(ammo_type)
{:error, %Ecto.Changeset{}}
"""
def delete_ammo_type(%AmmoType{} = ammo_type) do
Repo.delete(ammo_type)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking ammo_type changes.
## Examples
iex> change_ammo_type(ammo_type)
%Ecto.Changeset{data: %AmmoType{}}
"""
def change_ammo_type(%AmmoType{} = ammo_type, attrs \\ %{}) do
AmmoType.changeset(ammo_type, attrs)
end
alias Cannery.Ammo.AmmoGroup
@doc """
Returns the list of ammo_groups.
## Examples
iex> list_ammo_groups()
[%AmmoGroup{}, ...]
"""
def list_ammo_groups do
Repo.all(AmmoGroup)
end
@doc """
Gets a single ammo_group.
Raises `Ecto.NoResultsError` if the Ammo group does not exist.
## Examples
iex> get_ammo_group!(123)
%AmmoGroup{}
iex> get_ammo_group!(456)
** (Ecto.NoResultsError)
"""
def get_ammo_group!(id), do: Repo.get!(AmmoGroup, id)
@doc """
Creates a ammo_group.
## Examples
iex> create_ammo_group(%{field: value})
{:ok, %AmmoGroup{}}
iex> create_ammo_group(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_ammo_group(attrs \\ %{}) do
%AmmoGroup{}
|> AmmoGroup.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a ammo_group.
## Examples
iex> update_ammo_group(ammo_group, %{field: new_value})
{:ok, %AmmoGroup{}}
iex> update_ammo_group(ammo_group, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_ammo_group(%AmmoGroup{} = ammo_group, attrs) do
ammo_group
|> AmmoGroup.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a ammo_group.
## Examples
iex> delete_ammo_group(ammo_group)
{:ok, %AmmoGroup{}}
iex> delete_ammo_group(ammo_group)
{:error, %Ecto.Changeset{}}
"""
def delete_ammo_group(%AmmoGroup{} = ammo_group) do
Repo.delete(ammo_group)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking ammo_group changes.
## Examples
iex> change_ammo_group(ammo_group)
%Ecto.Changeset{data: %AmmoGroup{}}
"""
def change_ammo_group(%AmmoGroup{} = ammo_group, attrs \\ %{}) do
AmmoGroup.changeset(ammo_group, attrs)
end
end

View File

@ -0,0 +1,25 @@
defmodule Cannery.Ammo.AmmoGroup do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "ammo_groups" do
field :count, :integer
field :notes, :string
field :price_paid, :float
field :tag_id, :binary_id
field :ammo_type_id, :binary_id
field :container_id, :binary_id
field :user_id, :binary_id
timestamps()
end
@doc false
def changeset(ammo_group, attrs) do
ammo_group
|> cast(attrs, [:count, :price_paid, :notes])
|> validate_required([:count, :price_paid, :notes])
end
end

View File

@ -0,0 +1,24 @@
defmodule Cannery.Ammo.AmmoType do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "ammo_types" do
field :bullet_type, :string
field :case_material, :string
field :desc, :string
field :manufacturer, :string
field :name, :string
field :weight, :float
timestamps()
end
@doc false
def changeset(ammo_type, attrs) do
ammo_type
|> cast(attrs, [:name, :desc, :case_material, :bullet_type, :weight, :manufacturer])
|> validate_required([:name, :desc, :case_material, :bullet_type, :weight, :manufacturer])
end
end

104
lib/cannery/containers.ex Normal file
View File

@ -0,0 +1,104 @@
defmodule Cannery.Containers do
@moduledoc """
The Containers context.
"""
import Ecto.Query, warn: false
alias Cannery.Repo
alias Cannery.Containers.Container
@doc """
Returns the list of containers.
## Examples
iex> list_containers()
[%Container{}, ...]
"""
def list_containers do
Repo.all(Container)
end
@doc """
Gets a single container.
Raises `Ecto.NoResultsError` if the Container does not exist.
## Examples
iex> get_container!(123)
%Container{}
iex> get_container!(456)
** (Ecto.NoResultsError)
"""
def get_container!(id), do: Repo.get!(Container, id)
@doc """
Creates a container.
## Examples
iex> create_container(%{field: value})
{:ok, %Container{}}
iex> create_container(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_container(attrs \\ %{}) do
%Container{}
|> Container.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a container.
## Examples
iex> update_container(container, %{field: new_value})
{:ok, %Container{}}
iex> update_container(container, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_container(%Container{} = container, attrs) do
container
|> Container.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a container.
## Examples
iex> delete_container(container)
{:ok, %Container{}}
iex> delete_container(container)
{:error, %Ecto.Changeset{}}
"""
def delete_container(%Container{} = container) do
Repo.delete(container)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking container changes.
## Examples
iex> change_container(container)
%Ecto.Changeset{data: %Container{}}
"""
def change_container(%Container{} = container, attrs \\ %{}) do
Container.changeset(container, attrs)
end
end

View File

@ -0,0 +1,23 @@
defmodule Cannery.Containers.Container do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "containers" do
field :desc, :string
field :location, :string
field :name, :string
field :type, :string
field :user_id, :binary_id
timestamps()
end
@doc false
def changeset(container, attrs) do
container
|> cast(attrs, [:name, :desc, :type, :location])
|> validate_required([:name, :desc, :type, :location])
end
end

104
lib/cannery/tags.ex Normal file
View File

@ -0,0 +1,104 @@
defmodule Cannery.Tags do
@moduledoc """
The Tags context.
"""
import Ecto.Query, warn: false
alias Cannery.Repo
alias Cannery.Tags.Tag
@doc """
Returns the list of tags.
## Examples
iex> list_tags()
[%Tag{}, ...]
"""
def list_tags do
Repo.all(Tag)
end
@doc """
Gets a single tag.
Raises `Ecto.NoResultsError` if the Tag does not exist.
## Examples
iex> get_tag!(123)
%Tag{}
iex> get_tag!(456)
** (Ecto.NoResultsError)
"""
def get_tag!(id), do: Repo.get!(Tag, id)
@doc """
Creates a tag.
## Examples
iex> create_tag(%{field: value})
{:ok, %Tag{}}
iex> create_tag(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_tag(attrs \\ %{}) do
%Tag{}
|> Tag.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a tag.
## Examples
iex> update_tag(tag, %{field: new_value})
{:ok, %Tag{}}
iex> update_tag(tag, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_tag(%Tag{} = tag, attrs) do
tag
|> Tag.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a tag.
## Examples
iex> delete_tag(tag)
{:ok, %Tag{}}
iex> delete_tag(tag)
{:error, %Ecto.Changeset{}}
"""
def delete_tag(%Tag{} = tag) do
Repo.delete(tag)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking tag changes.
## Examples
iex> change_tag(tag)
%Ecto.Changeset{data: %Tag{}}
"""
def change_tag(%Tag{} = tag, attrs \\ %{}) do
Tag.changeset(tag, attrs)
end
end

22
lib/cannery/tags/tag.ex Normal file
View File

@ -0,0 +1,22 @@
defmodule Cannery.Tags.Tag do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "tags" do
field :"bg-color", :string
field :name, :string
field :"text-color", :string
field :user_id, :binary_id
timestamps()
end
@doc false
def changeset(tag, attrs) do
tag
|> cast(attrs, [:name, :"bg-color", :"text-color"])
|> validate_required([:name, :"bg-color", :"text-color"])
end
end

View File

@ -46,7 +46,7 @@ defmodule CanneryWeb do
quote do quote do
use Phoenix.LiveView, use Phoenix.LiveView,
layout: {CanneryWeb.LayoutView, "live.html"} layout: {CanneryWeb.LayoutView, "live.html"}
unquote(view_helpers()) unquote(view_helpers())
end end
end end
@ -83,6 +83,7 @@ defmodule CanneryWeb do
# Import LiveView helpers (live_render, live_component, live_patch, etc) # Import LiveView helpers (live_render, live_component, live_patch, etc)
import Phoenix.LiveView.Helpers import Phoenix.LiveView.Helpers
import CanneryWeb.LiveHelpers
# Import basic rendering functionality (render, render_layout, etc) # Import basic rendering functionality (render, render_layout, etc)
import Phoenix.View import Phoenix.View

View File

@ -9,7 +9,7 @@ defmodule CanneryWeb.UserSocket do
# verification, you can put default assigns into # verification, you can put default assigns into
# the socket that will be set for all channels, ie # the socket that will be set for all channels, ie
# #
# {:ok, assign(socket, :user_id, verified_user_id)} # {:ok, socket |> assign(:user_id, verified_user_id)}
# #
# To deny connection, return `:error`. # To deny connection, return `:error`.
# #

View File

@ -20,5 +20,5 @@ defmodule CanneryWeb.Gettext do
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
""" """
use Gettext, otp_app: :cannery # use Gettext, otp_app: :cannery
end end

View File

@ -0,0 +1,55 @@
defmodule CanneryWeb.AmmoGroupLive.FormComponent do
use CanneryWeb, :live_component
alias Cannery.Ammo
@impl true
def update(%{ammo_group: ammo_group} = assigns, socket) do
changeset = Ammo.change_ammo_group(ammo_group)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end
@impl true
def handle_event("validate", %{"ammo_group" => ammo_group_params}, socket) do
changeset =
socket.assigns.ammo_group
|> Ammo.change_ammo_group(ammo_group_params)
|> Map.put(:action, :validate)
{:noreply, socket |> assign(:changeset, changeset)}
end
def handle_event("save", %{"ammo_group" => ammo_group_params}, socket) do
save_ammo_group(socket, socket.assigns.action, ammo_group_params)
end
defp save_ammo_group(socket, :edit, ammo_group_params) do
case Ammo.update_ammo_group(socket.assigns.ammo_group, ammo_group_params) do
{:ok, _ammo_group} ->
{:noreply,
socket
|> put_flash(:info, "Ammo group updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(:changeset, changeset)}
end
end
defp save_ammo_group(socket, :new, ammo_group_params) do
case Ammo.create_ammo_group(ammo_group_params) do
{:ok, _ammo_group} ->
{:noreply,
socket
|> put_flash(:info, "Ammo group created successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(changeset: changeset)}
end
end
end

View File

@ -0,0 +1,22 @@
<h2><%= @title %></h2>
<%= f = form_for @changeset, "#",
id: "ammo_group-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<%= label f, :count %>
<%= number_input f, :count %>
<%= error_tag f, :count %>
<%= label f, :price_paid %>
<%= number_input f, :price_paid, step: "any" %>
<%= error_tag f, :price_paid %>
<%= label f, :notes %>
<%= textarea f, :notes %>
<%= error_tag f, :notes %>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>

View File

@ -0,0 +1,46 @@
defmodule CanneryWeb.AmmoGroupLive.Index do
use CanneryWeb, :live_view
alias Cannery.Ammo
alias Cannery.Ammo.AmmoGroup
@impl true
def mount(_params, _session, socket) do
{:ok, socket |> assign(:ammo_groups, list_ammo_groups())}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :edit, %{"id" => id}) do
socket
|> assign(:page_title, "Edit Ammo group")
|> assign(:ammo_group, Ammo.get_ammo_group!(id))
end
defp apply_action(socket, :new, _params) do
socket
|> assign(:page_title, "New Ammo group")
|> assign(:ammo_group, %AmmoGroup{})
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Ammo groups")
|> assign(:ammo_group, nil)
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
ammo_group = Ammo.get_ammo_group!(id)
{:ok, _} = Ammo.delete_ammo_group(ammo_group)
{:noreply, socket |> assign(:ammo_groups, list_ammo_groups())}
end
defp list_ammo_groups do
Ammo.list_ammo_groups()
end
end

View File

@ -0,0 +1,39 @@
<h1>Listing Ammo groups</h1>
<%= if @live_action in [:new, :edit] do %>
<%= live_modal CanneryWeb.AmmoGroupLive.FormComponent,
id: @ammo_group.id || :new,
title: @page_title,
action: @live_action,
ammo_group: @ammo_group,
return_to: Routes.ammo_group_index_path(@socket, :index) %>
<% end %>
<table>
<thead>
<tr>
<th>Count</th>
<th>Price paid</th>
<th>Notes</th>
<th></th>
</tr>
</thead>
<tbody id="ammo_groups">
<%= for ammo_group <- @ammo_groups do %>
<tr id="ammo_group-<%= ammo_group.id %>">
<td><%= ammo_group.count %></td>
<td><%= ammo_group.price_paid %></td>
<td><%= ammo_group.notes %></td>
<td>
<span><%= live_redirect "Show", to: Routes.ammo_group_show_path(@socket, :show, ammo_group) %></span>
<span><%= live_patch "Edit", to: Routes.ammo_group_index_path(@socket, :edit, ammo_group) %></span>
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: ammo_group.id, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= live_patch "New Ammo group", to: Routes.ammo_group_index_path(@socket, :new) %></span>

View File

@ -0,0 +1,21 @@
defmodule CanneryWeb.AmmoGroupLive.Show do
use CanneryWeb, :live_view
alias Cannery.Ammo
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:ammo_group, Ammo.get_ammo_group!(id))}
end
defp page_title(:show), do: "Show Ammo group"
defp page_title(:edit), do: "Edit Ammo group"
end

View File

@ -0,0 +1,32 @@
<h1>Show Ammo group</h1>
<%= if @live_action in [:edit] do %>
<%= live_modal CanneryWeb.AmmoGroupLive.FormComponent,
id: @ammo_group.id,
title: @page_title,
action: @live_action,
ammo_group: @ammo_group,
return_to: Routes.ammo_group_show_path(@socket, :show, @ammo_group) %>
<% end %>
<ul>
<li>
<strong>Count:</strong>
<%= @ammo_group.count %>
</li>
<li>
<strong>Price paid:</strong>
<%= @ammo_group.price_paid %>
</li>
<li>
<strong>Notes:</strong>
<%= @ammo_group.notes %>
</li>
</ul>
<span><%= live_patch "Edit", to: Routes.ammo_group_show_path(@socket, :edit, @ammo_group), class: "button" %></span>
<span><%= live_redirect "Back", to: Routes.ammo_group_index_path(@socket, :index) %></span>

View File

@ -0,0 +1,55 @@
defmodule CanneryWeb.AmmoTypeLive.FormComponent do
use CanneryWeb, :live_component
alias Cannery.Ammo
@impl true
def update(%{ammo_type: ammo_type} = assigns, socket) do
changeset = Ammo.change_ammo_type(ammo_type)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end
@impl true
def handle_event("validate", %{"ammo_type" => ammo_type_params}, socket) do
changeset =
socket.assigns.ammo_type
|> Ammo.change_ammo_type(ammo_type_params)
|> Map.put(:action, :validate)
{:noreply, socket |> assign(:changeset, changeset)}
end
def handle_event("save", %{"ammo_type" => ammo_type_params}, socket) do
save_ammo_type(socket, socket.assigns.action, ammo_type_params)
end
defp save_ammo_type(socket, :edit, ammo_type_params) do
case Ammo.update_ammo_type(socket.assigns.ammo_type, ammo_type_params) do
{:ok, _ammo_type} ->
{:noreply,
socket
|> put_flash(:info, "Ammo type updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(:changeset, changeset)}
end
end
defp save_ammo_type(socket, :new, ammo_type_params) do
case Ammo.create_ammo_type(ammo_type_params) do
{:ok, _ammo_type} ->
{:noreply,
socket
|> put_flash(:info, "Ammo type created successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(changeset: changeset)}
end
end
end

View File

@ -0,0 +1,34 @@
<h2><%= @title %></h2>
<%= f = form_for @changeset, "#",
id: "ammo_type-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<%= label f, :desc %>
<%= text_input f, :desc %>
<%= error_tag f, :desc %>
<%= label f, :case_material %>
<%= text_input f, :case_material %>
<%= error_tag f, :case_material %>
<%= label f, :bullet_type %>
<%= text_input f, :bullet_type %>
<%= error_tag f, :bullet_type %>
<%= label f, :weight %>
<%= number_input f, :weight, step: "any" %>
<%= error_tag f, :weight %>
<%= label f, :manufacturer %>
<%= text_input f, :manufacturer %>
<%= error_tag f, :manufacturer %>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>

View File

@ -0,0 +1,46 @@
defmodule CanneryWeb.AmmoTypeLive.Index do
use CanneryWeb, :live_view
alias Cannery.Ammo
alias Cannery.Ammo.AmmoType
@impl true
def mount(_params, _session, socket) do
{:ok, socket |> assign(:ammo_types, list_ammo_types())}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :edit, %{"id" => id}) do
socket
|> assign(:page_title, "Edit Ammo type")
|> assign(:ammo_type, Ammo.get_ammo_type!(id))
end
defp apply_action(socket, :new, _params) do
socket
|> assign(:page_title, "New Ammo type")
|> assign(:ammo_type, %AmmoType{})
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Ammo types")
|> assign(:ammo_type, nil)
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
ammo_type = Ammo.get_ammo_type!(id)
{:ok, _} = Ammo.delete_ammo_type(ammo_type)
{:noreply, socket |> assign(:ammo_types, list_ammo_types())}
end
defp list_ammo_types do
Ammo.list_ammo_types()
end
end

View File

@ -0,0 +1,45 @@
<h1>Listing Ammo types</h1>
<%= if @live_action in [:new, :edit] do %>
<%= live_modal CanneryWeb.AmmoTypeLive.FormComponent,
id: @ammo_type.id || :new,
title: @page_title,
action: @live_action,
ammo_type: @ammo_type,
return_to: Routes.ammo_type_index_path(@socket, :index) %>
<% end %>
<table>
<thead>
<tr>
<th>Name</th>
<th>Desc</th>
<th>Case material</th>
<th>Bullet type</th>
<th>Weight</th>
<th>Manufacturer</th>
<th></th>
</tr>
</thead>
<tbody id="ammo_types">
<%= for ammo_type <- @ammo_types do %>
<tr id="ammo_type-<%= ammo_type.id %>">
<td><%= ammo_type.name %></td>
<td><%= ammo_type.desc %></td>
<td><%= ammo_type.case_material %></td>
<td><%= ammo_type.bullet_type %></td>
<td><%= ammo_type.weight %></td>
<td><%= ammo_type.manufacturer %></td>
<td>
<span><%= live_redirect "Show", to: Routes.ammo_type_show_path(@socket, :show, ammo_type) %></span>
<span><%= live_patch "Edit", to: Routes.ammo_type_index_path(@socket, :edit, ammo_type) %></span>
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: ammo_type.id, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= live_patch "New Ammo type", to: Routes.ammo_type_index_path(@socket, :new) %></span>

View File

@ -0,0 +1,21 @@
defmodule CanneryWeb.AmmoTypeLive.Show do
use CanneryWeb, :live_view
alias Cannery.Ammo
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:ammo_type, Ammo.get_ammo_type!(id))}
end
defp page_title(:show), do: "Show Ammo type"
defp page_title(:edit), do: "Edit Ammo type"
end

View File

@ -0,0 +1,47 @@
<h1>Show Ammo type</h1>
<%= if @live_action in [:edit] do %>
<%= live_modal CanneryWeb.AmmoTypeLive.FormComponent,
id: @ammo_type.id,
title: @page_title,
action: @live_action,
ammo_type: @ammo_type,
return_to: Routes.ammo_type_show_path(@socket, :show, @ammo_type) %>
<% end %>
<ul>
<li>
<strong>Name:</strong>
<%= @ammo_type.name %>
</li>
<li>
<strong>Desc:</strong>
<%= @ammo_type.desc %>
</li>
<li>
<strong>Case material:</strong>
<%= @ammo_type.case_material %>
</li>
<li>
<strong>Bullet type:</strong>
<%= @ammo_type.bullet_type %>
</li>
<li>
<strong>Weight:</strong>
<%= @ammo_type.weight %>
</li>
<li>
<strong>Manufacturer:</strong>
<%= @ammo_type.manufacturer %>
</li>
</ul>
<span><%= live_patch "Edit", to: Routes.ammo_type_show_path(@socket, :edit, @ammo_type), class: "button" %></span>
<span><%= live_redirect "Back", to: Routes.ammo_type_index_path(@socket, :index) %></span>

View File

@ -1,12 +1,12 @@
defmodule CanneryWeb.Live.Component.Topbar do defmodule CanneryWeb.Live.Component.Topbar do
use CanneryWeb, :live_component use CanneryWeb, :live_component
alias CanneryWeb.{PageLive} alias CanneryWeb.{PageLive}
def mount(socket) do def mount(socket) do
{:ok, socket |> assign(results: [], title_content: nil)} {:ok, socket |> assign(results: [], title_content: nil)}
end end
def update(assigns, socket) do def update(assigns, socket) do
{:ok, socket |> assign(assigns)} {:ok, socket |> assign(assigns)}
end end
@ -41,7 +41,7 @@ defmodule CanneryWeb.Live.Component.Topbar do
</form> </form>
<%# user settings %> <%# user settings %>
<%= if assigns |> Map.has_key?(:current_user) do %> <%= if @current_user do %>
<li> <li>
<%= @current_user.email %></li> <%= @current_user.email %></li>
<li> <li>
@ -89,4 +89,4 @@ defmodule CanneryWeb.Live.Component.Topbar do
</header> </header>
""" """
end end
end end

View File

@ -0,0 +1,55 @@
defmodule CanneryWeb.ContainerLive.FormComponent do
use CanneryWeb, :live_component
alias Cannery.Containers
@impl true
def update(%{container: container} = assigns, socket) do
changeset = Containers.change_container(container)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end
@impl true
def handle_event("validate", %{"container" => container_params}, socket) do
changeset =
socket.assigns.container
|> Containers.change_container(container_params)
|> Map.put(:action, :validate)
{:noreply, socket |> assign(:changeset, changeset)}
end
def handle_event("save", %{"container" => container_params}, socket) do
save_container(socket, socket.assigns.action, container_params)
end
defp save_container(socket, :edit, container_params) do
case Containers.update_container(socket.assigns.container, container_params) do
{:ok, _container} ->
{:noreply,
socket
|> put_flash(:info, "Container updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(:changeset, changeset)}
end
end
defp save_container(socket, :new, container_params) do
case Containers.create_container(container_params) do
{:ok, _container} ->
{:noreply,
socket
|> put_flash(:info, "Container created successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(changeset: changeset)}
end
end
end

View File

@ -0,0 +1,26 @@
<h2><%= @title %></h2>
<%= f = form_for @changeset, "#",
id: "container-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<%= label f, :desc %>
<%= text_input f, :desc %>
<%= error_tag f, :desc %>
<%= label f, :type %>
<%= text_input f, :type %>
<%= error_tag f, :type %>
<%= label f, :location %>
<%= text_input f, :location %>
<%= error_tag f, :location %>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>

View File

@ -0,0 +1,46 @@
defmodule CanneryWeb.ContainerLive.Index do
use CanneryWeb, :live_view
alias Cannery.Containers
alias Cannery.Containers.Container
@impl true
def mount(_params, _session, socket) do
{:ok, socket |> assign(:containers, list_containers())}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :edit, %{"id" => id}) do
socket
|> assign(:page_title, "Edit Container")
|> assign(:container, Containers.get_container!(id))
end
defp apply_action(socket, :new, _params) do
socket
|> assign(:page_title, "New Container")
|> assign(:container, %Container{})
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Containers")
|> assign(:container, nil)
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
container = Containers.get_container!(id)
{:ok, _} = Containers.delete_container(container)
{:noreply, socket |> assign(:containers, list_containers())}
end
defp list_containers do
Containers.list_containers()
end
end

View File

@ -0,0 +1,41 @@
<h1>Listing Containers</h1>
<%= if @live_action in [:new, :edit] do %>
<%= live_modal CanneryWeb.ContainerLive.FormComponent,
id: @container.id || :new,
title: @page_title,
action: @live_action,
container: @container,
return_to: Routes.container_index_path(@socket, :index) %>
<% end %>
<table>
<thead>
<tr>
<th>Name</th>
<th>Desc</th>
<th>Type</th>
<th>Location</th>
<th></th>
</tr>
</thead>
<tbody id="containers">
<%= for container <- @containers do %>
<tr id="container-<%= container.id %>">
<td><%= container.name %></td>
<td><%= container.desc %></td>
<td><%= container.type %></td>
<td><%= container.location %></td>
<td>
<span><%= live_redirect "Show", to: Routes.container_show_path(@socket, :show, container) %></span>
<span><%= live_patch "Edit", to: Routes.container_index_path(@socket, :edit, container) %></span>
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: container.id, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= live_patch "New Container", to: Routes.container_index_path(@socket, :new) %></span>

View File

@ -0,0 +1,21 @@
defmodule CanneryWeb.ContainerLive.Show do
use CanneryWeb, :live_view
alias Cannery.Containers
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:container, Containers.get_container!(id))}
end
defp page_title(:show), do: "Show Container"
defp page_title(:edit), do: "Edit Container"
end

View File

@ -0,0 +1,37 @@
<h1>Show Container</h1>
<%= if @live_action in [:edit] do %>
<%= live_modal CanneryWeb.ContainerLive.FormComponent,
id: @container.id,
title: @page_title,
action: @live_action,
container: @container,
return_to: Routes.container_show_path(@socket, :show, @container) %>
<% end %>
<ul>
<li>
<strong>Name:</strong>
<%= @container.name %>
</li>
<li>
<strong>Desc:</strong>
<%= @container.desc %>
</li>
<li>
<strong>Type:</strong>
<%= @container.type %>
</li>
<li>
<strong>Location:</strong>
<%= @container.location %>
</li>
</ul>
<span><%= live_patch "Edit", to: Routes.container_show_path(@socket, :edit, @container), class: "button" %></span>
<span><%= live_redirect "Back", to: Routes.container_index_path(@socket, :index) %></span>

View File

@ -0,0 +1,36 @@
defmodule CanneryWeb.LiveHelpers do
import Phoenix.LiveView.Helpers
import Phoenix.LiveView, only: [assign_new: 3]
alias Cannery.{Accounts}
@doc """
Renders a component inside the `CanneryWeb.ModalComponent` component.
The rendered modal receives a `:return_to` option to properly update
the URL when the modal is closed.
## Examples
<%= live_modal CanneryWeb.TagLive.FormComponent,
id: @tag.id || :new,
action: @live_action,
tag: @tag,
return_to: Routes.tag_index_path(@socket, :index) %>
"""
def live_modal(component, opts) do
path = Keyword.fetch!(opts, :return_to)
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
live_component(CanneryWeb.ModalComponent, modal_opts)
end
def assign_defaults(socket, %{"user_token" => user_token} = _session) do
socket
|> assign_new(:current_user, fn ->
Accounts.get_user_by_session_token(user_token)
end)
end
def assign_defaults(socket, _session) do
socket
end
end

View File

@ -0,0 +1,26 @@
defmodule CanneryWeb.ModalComponent do
use CanneryWeb, :live_component
@impl true
def render(assigns) do
~L"""
<div id="<%= @id %>" class="phx-modal"
phx-capture-click="close"
phx-window-keydown="close"
phx-key="escape"
phx-target="#<%= @id %>"
phx-page-loading>
<div class="phx-modal-content">
<%= live_patch raw("&times;"), to: @return_to, class: "phx-modal-close" %>
<%= live_component @socket, @component, @opts %>
</div>
</div>
"""
end
@impl true
def handle_event("close", _, socket) do
{:noreply, push_patch(socket, to: socket.assigns.return_to)}
end
end

View File

@ -2,13 +2,13 @@ defmodule CanneryWeb.PageLive do
use CanneryWeb, :live_view use CanneryWeb, :live_view
@impl true @impl true
def mount(_params, _session, socket) do def mount(_params, session, socket) do
{:ok, assign(socket, query: "", results: %{})} {:ok, socket |> assign_defaults(session) |> assign(query: "", results: %{})}
end end
@impl true @impl true
def handle_event("suggest", %{"q" => query}, socket) do def handle_event("suggest", %{"q" => query}, socket) do
{:noreply, assign(socket, results: search(query), query: query)} {:noreply, socket |> assign(results: search(query), query: query)}
end end
@impl true @impl true

View File

@ -0,0 +1,55 @@
defmodule CanneryWeb.TagLive.FormComponent do
use CanneryWeb, :live_component
alias Cannery.Tags
@impl true
def update(%{tag: tag} = assigns, socket) do
changeset = Tags.change_tag(tag)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end
@impl true
def handle_event("validate", %{"tag" => tag_params}, socket) do
changeset =
socket.assigns.tag
|> Tags.change_tag(tag_params)
|> Map.put(:action, :validate)
{:noreply, socket |> assign(:changeset, changeset)}
end
def handle_event("save", %{"tag" => tag_params}, socket) do
save_tag(socket, socket.assigns.action, tag_params)
end
defp save_tag(socket, :edit, tag_params) do
case Tags.update_tag(socket.assigns.tag, tag_params) do
{:ok, _tag} ->
{:noreply,
socket
|> put_flash(:info, "Tag updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(:changeset, changeset)}
end
end
defp save_tag(socket, :new, tag_params) do
case Tags.create_tag(tag_params) do
{:ok, _tag} ->
{:noreply,
socket
|> put_flash(:info, "Tag created successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, socket |> assign(changeset: changeset)}
end
end
end

View File

@ -0,0 +1,22 @@
<h2><%= @title %></h2>
<%= f = form_for @changeset, "#",
id: "tag-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<%= label f, :name %>
<%= text_input f, :name %>
<%= error_tag f, :name %>
<%= label f, :"bg-color" %>
<%= text_input f, :"bg-color" %>
<%= error_tag f, :"bg-color" %>
<%= label f, :"text-color" %>
<%= text_input f, :"text-color" %>
<%= error_tag f, :"text-color" %>
<%= submit "Save", phx_disable_with: "Saving..." %>
</form>

View File

@ -0,0 +1,46 @@
defmodule CanneryWeb.TagLive.Index do
use CanneryWeb, :live_view
alias Cannery.Tags
alias Cannery.Tags.Tag
@impl true
def mount(_params, _session, socket) do
{:ok, socket |> assign(:tags, list_tags())}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :edit, %{"id" => id}) do
socket
|> assign(:page_title, "Edit Tag")
|> assign(:tag, Tags.get_tag!(id))
end
defp apply_action(socket, :new, _params) do
socket
|> assign(:page_title, "New Tag")
|> assign(:tag, %Tag{})
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_title, "Listing Tags")
|> assign(:tag, nil)
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
tag = Tags.get_tag!(id)
{:ok, _} = Tags.delete_tag(tag)
{:noreply, socket |> assign(:tags, list_tags())}
end
defp list_tags do
Tags.list_tags()
end
end

View File

@ -0,0 +1,39 @@
<h1>Listing Tags</h1>
<%= if @live_action in [:new, :edit] do %>
<%= live_modal CanneryWeb.TagLive.FormComponent,
id: @tag.id || :new,
title: @page_title,
action: @live_action,
tag: @tag,
return_to: Routes.tag_index_path(@socket, :index) %>
<% end %>
<table>
<thead>
<tr>
<th>Name</th>
<th>Bg-color</th>
<th>Text-color</th>
<th></th>
</tr>
</thead>
<tbody id="tags">
<%= for tag <- @tags do %>
<tr id="tag-<%= tag.id %>">
<td><%= tag.name %></td>
<td><%= tag.bg_color %></td>
<td><%= tag.text_color %></td>
<td>
<span><%= live_redirect "Show", to: Routes.tag_show_path(@socket, :show, tag) %></span>
<span><%= live_patch "Edit", to: Routes.tag_index_path(@socket, :edit, tag) %></span>
<span><%= link "Delete", to: "#", phx_click: "delete", phx_value_id: tag.id, data: [confirm: "Are you sure?"] %></span>
</td>
</tr>
<% end %>
</tbody>
</table>
<span><%= live_patch "New Tag", to: Routes.tag_index_path(@socket, :new) %></span>

View File

@ -0,0 +1,21 @@
defmodule CanneryWeb.TagLive.Show do
use CanneryWeb, :live_view
alias Cannery.Tags
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:tag, Tags.get_tag!(id))}
end
defp page_title(:show), do: "Show Tag"
defp page_title(:edit), do: "Edit Tag"
end

View File

@ -0,0 +1,32 @@
<h1>Show Tag</h1>
<%= if @live_action in [:edit] do %>
<%= live_modal CanneryWeb.TagLive.FormComponent,
id: @tag.id,
title: @page_title,
action: @live_action,
tag: @tag,
return_to: Routes.tag_show_path(@socket, :show, @tag) %>
<% end %>
<ul>
<li>
<strong>Name:</strong>
<%= @tag.name %>
</li>
<li>
<strong>Bg-color:</strong>
<%= @tag.bg_color %>
</li>
<li>
<strong>Text-color:</strong>
<%= @tag.text_color %>
</li>
</ul>
<span><%= live_patch "Edit", to: Routes.tag_show_path(@socket, :edit, @tag), class: "button" %></span>
<span><%= live_redirect "Back", to: Routes.tag_index_path(@socket, :index) %></span>

View File

@ -60,6 +60,34 @@ defmodule CanneryWeb.Router do
get "/users/settings", UserSettingsController, :edit get "/users/settings", UserSettingsController, :edit
put "/users/settings", UserSettingsController, :update put "/users/settings", UserSettingsController, :update
get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email
live "/tags", TagLive.Index, :index
live "/tags/new", TagLive.Index, :new
live "/tags/:id/edit", TagLive.Index, :edit
live "/tags/:id", TagLive.Show, :show
live "/tags/:id/show/edit", TagLive.Show, :edit
live "/ammo_types", AmmoTypeLive.Index, :index
live "/ammo_types/new", AmmoTypeLive.Index, :new
live "/ammo_types/:id/edit", AmmoTypeLive.Index, :edit
live "/ammo_types/:id", AmmoTypeLive.Show, :show
live "/ammo_types/:id/show/edit", AmmoTypeLive.Show, :edit
live "/containers", ContainerLive.Index, :index
live "/containers/new", ContainerLive.Index, :new
live "/containers/:id/edit", ContainerLive.Index, :edit
live "/containers/:id", ContainerLive.Show, :show
live "/containers/:id/show/edit", ContainerLive.Show, :edit
live "/ammo_groups", AmmoGroupLive.Index, :index
live "/ammo_groups/new", AmmoGroupLive.Index, :new
live "/ammo_groups/:id/edit", AmmoGroupLive.Index, :edit
live "/ammo_groups/:id", AmmoGroupLive.Show, :show
live "/ammo_groups/:id/show/edit", AmmoGroupLive.Show, :edit
end end
scope "/", CanneryWeb do scope "/", CanneryWeb do

View File

@ -1,5 +1,5 @@
<main role="main" class="container min-w-full min-h-full"> <main role="main" class="container min-w-full min-h-full">
<%= live_component CanneryWeb.Live.Component.Topbar %> <%= live_component CanneryWeb.Live.Component.Topbar, current_user: assigns[:current_user] %>
<%= @inner_content %> <%= @inner_content %>
</main> </main>

View File

@ -0,0 +1,17 @@
defmodule Cannery.Repo.Migrations.CreateTags do
use Ecto.Migration
def change do
create table(:tags, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :"bg-color", :string
add :"text-color", :string
add :user_id, references(:users, on_delete: :nothing, type: :binary_id)
timestamps()
end
create index(:tags, [:user_id])
end
end

View File

@ -0,0 +1,18 @@
defmodule Cannery.Repo.Migrations.CreateAmmoTypes do
use Ecto.Migration
def change do
create table(:ammo_types, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :desc, :string
add :case_material, :string
add :bullet_type, :string
add :weight, :float
add :manufacturer, :string
timestamps()
end
end
end

View File

@ -0,0 +1,18 @@
defmodule Cannery.Repo.Migrations.CreateContainers do
use Ecto.Migration
def change do
create table(:containers, primary_key: false) do
add :id, :binary_id, primary_key: true
add :name, :string
add :desc, :string
add :type, :string
add :location, :string
add :user_id, references(:users, on_delete: :nothing, type: :binary_id)
timestamps()
end
create index(:containers, [:user_id])
end
end

View File

@ -0,0 +1,23 @@
defmodule Cannery.Repo.Migrations.CreateAmmoGroups do
use Ecto.Migration
def change do
create table(:ammo_groups, primary_key: false) do
add :id, :binary_id, primary_key: true
add :count, :integer
add :price_paid, :float
add :notes, :text
add :tag_id, references(:tags, on_delete: :nothing, type: :binary_id)
add :ammo_type_id, references(:ammo_types, on_delete: :nothing, type: :binary_id)
add :container_id, references(:containers, on_delete: :nothing, type: :binary_id)
add :user_id, references(:users, on_delete: :nothing, type: :binary_id)
timestamps()
end
create index(:ammo_groups, [:tag_id])
create index(:ammo_groups, [:ammo_type_id])
create index(:ammo_groups, [:container_id])
create index(:ammo_groups, [:user_id])
end
end

137
test/cannery/ammo_test.exs Normal file
View File

@ -0,0 +1,137 @@
defmodule Cannery.AmmoTest do
use Cannery.DataCase
alias Cannery.Ammo
describe "ammo_types" do
alias Cannery.Ammo.AmmoType
@valid_attrs %{bullet_type: "some bullet_type", case_material: "some case_material", desc: "some desc", manufacturer: "some manufacturer", name: "some name", weight: 120.5}
@update_attrs %{bullet_type: "some updated bullet_type", case_material: "some updated case_material", desc: "some updated desc", manufacturer: "some updated manufacturer", name: "some updated name", weight: 456.7}
@invalid_attrs %{bullet_type: nil, case_material: nil, desc: nil, manufacturer: nil, name: nil, weight: nil}
def ammo_type_fixture(attrs \\ %{}) do
{:ok, ammo_type} =
attrs
|> Enum.into(@valid_attrs)
|> Ammo.create_ammo_type()
ammo_type
end
test "list_ammo_types/0 returns all ammo_types" do
ammo_type = ammo_type_fixture()
assert Ammo.list_ammo_types() == [ammo_type]
end
test "get_ammo_type!/1 returns the ammo_type with given id" do
ammo_type = ammo_type_fixture()
assert Ammo.get_ammo_type!(ammo_type.id) == ammo_type
end
test "create_ammo_type/1 with valid data creates a ammo_type" do
assert {:ok, %AmmoType{} = ammo_type} = Ammo.create_ammo_type(@valid_attrs)
assert ammo_type.bullet_type == "some bullet_type"
assert ammo_type.case_material == "some case_material"
assert ammo_type.desc == "some desc"
assert ammo_type.manufacturer == "some manufacturer"
assert ammo_type.name == "some name"
assert ammo_type.weight == 120.5
end
test "create_ammo_type/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Ammo.create_ammo_type(@invalid_attrs)
end
test "update_ammo_type/2 with valid data updates the ammo_type" do
ammo_type = ammo_type_fixture()
assert {:ok, %AmmoType{} = ammo_type} = Ammo.update_ammo_type(ammo_type, @update_attrs)
assert ammo_type.bullet_type == "some updated bullet_type"
assert ammo_type.case_material == "some updated case_material"
assert ammo_type.desc == "some updated desc"
assert ammo_type.manufacturer == "some updated manufacturer"
assert ammo_type.name == "some updated name"
assert ammo_type.weight == 456.7
end
test "update_ammo_type/2 with invalid data returns error changeset" do
ammo_type = ammo_type_fixture()
assert {:error, %Ecto.Changeset{}} = Ammo.update_ammo_type(ammo_type, @invalid_attrs)
assert ammo_type == Ammo.get_ammo_type!(ammo_type.id)
end
test "delete_ammo_type/1 deletes the ammo_type" do
ammo_type = ammo_type_fixture()
assert {:ok, %AmmoType{}} = Ammo.delete_ammo_type(ammo_type)
assert_raise Ecto.NoResultsError, fn -> Ammo.get_ammo_type!(ammo_type.id) end
end
test "change_ammo_type/1 returns a ammo_type changeset" do
ammo_type = ammo_type_fixture()
assert %Ecto.Changeset{} = Ammo.change_ammo_type(ammo_type)
end
end
describe "ammo_groups" do
alias Cannery.Ammo.AmmoGroup
@valid_attrs %{count: 42, notes: "some notes", price_paid: 120.5}
@update_attrs %{count: 43, notes: "some updated notes", price_paid: 456.7}
@invalid_attrs %{count: nil, notes: nil, price_paid: nil}
def ammo_group_fixture(attrs \\ %{}) do
{:ok, ammo_group} =
attrs
|> Enum.into(@valid_attrs)
|> Ammo.create_ammo_group()
ammo_group
end
test "list_ammo_groups/0 returns all ammo_groups" do
ammo_group = ammo_group_fixture()
assert Ammo.list_ammo_groups() == [ammo_group]
end
test "get_ammo_group!/1 returns the ammo_group with given id" do
ammo_group = ammo_group_fixture()
assert Ammo.get_ammo_group!(ammo_group.id) == ammo_group
end
test "create_ammo_group/1 with valid data creates a ammo_group" do
assert {:ok, %AmmoGroup{} = ammo_group} = Ammo.create_ammo_group(@valid_attrs)
assert ammo_group.count == 42
assert ammo_group.notes == "some notes"
assert ammo_group.price_paid == 120.5
end
test "create_ammo_group/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Ammo.create_ammo_group(@invalid_attrs)
end
test "update_ammo_group/2 with valid data updates the ammo_group" do
ammo_group = ammo_group_fixture()
assert {:ok, %AmmoGroup{} = ammo_group} = Ammo.update_ammo_group(ammo_group, @update_attrs)
assert ammo_group.count == 43
assert ammo_group.notes == "some updated notes"
assert ammo_group.price_paid == 456.7
end
test "update_ammo_group/2 with invalid data returns error changeset" do
ammo_group = ammo_group_fixture()
assert {:error, %Ecto.Changeset{}} = Ammo.update_ammo_group(ammo_group, @invalid_attrs)
assert ammo_group == Ammo.get_ammo_group!(ammo_group.id)
end
test "delete_ammo_group/1 deletes the ammo_group" do
ammo_group = ammo_group_fixture()
assert {:ok, %AmmoGroup{}} = Ammo.delete_ammo_group(ammo_group)
assert_raise Ecto.NoResultsError, fn -> Ammo.get_ammo_group!(ammo_group.id) end
end
test "change_ammo_group/1 returns a ammo_group changeset" do
ammo_group = ammo_group_fixture()
assert %Ecto.Changeset{} = Ammo.change_ammo_group(ammo_group)
end
end
end

View File

@ -0,0 +1,70 @@
defmodule Cannery.ContainersTest do
use Cannery.DataCase
alias Cannery.Containers
describe "containers" do
alias Cannery.Containers.Container
@valid_attrs %{desc: "some desc", location: "some location", name: "some name", type: "some type"}
@update_attrs %{desc: "some updated desc", location: "some updated location", name: "some updated name", type: "some updated type"}
@invalid_attrs %{desc: nil, location: nil, name: nil, type: nil}
def container_fixture(attrs \\ %{}) do
{:ok, container} =
attrs
|> Enum.into(@valid_attrs)
|> Containers.create_container()
container
end
test "list_containers/0 returns all containers" do
container = container_fixture()
assert Containers.list_containers() == [container]
end
test "get_container!/1 returns the container with given id" do
container = container_fixture()
assert Containers.get_container!(container.id) == container
end
test "create_container/1 with valid data creates a container" do
assert {:ok, %Container{} = container} = Containers.create_container(@valid_attrs)
assert container.desc == "some desc"
assert container.location == "some location"
assert container.name == "some name"
assert container.type == "some type"
end
test "create_container/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Containers.create_container(@invalid_attrs)
end
test "update_container/2 with valid data updates the container" do
container = container_fixture()
assert {:ok, %Container{} = container} = Containers.update_container(container, @update_attrs)
assert container.desc == "some updated desc"
assert container.location == "some updated location"
assert container.name == "some updated name"
assert container.type == "some updated type"
end
test "update_container/2 with invalid data returns error changeset" do
container = container_fixture()
assert {:error, %Ecto.Changeset{}} = Containers.update_container(container, @invalid_attrs)
assert container == Containers.get_container!(container.id)
end
test "delete_container/1 deletes the container" do
container = container_fixture()
assert {:ok, %Container{}} = Containers.delete_container(container)
assert_raise Ecto.NoResultsError, fn -> Containers.get_container!(container.id) end
end
test "change_container/1 returns a container changeset" do
container = container_fixture()
assert %Ecto.Changeset{} = Containers.change_container(container)
end
end
end

View File

@ -0,0 +1,68 @@
defmodule Cannery.TagsTest do
use Cannery.DataCase
alias Cannery.Tags
describe "tags" do
alias Cannery.Tags.Tag
@valid_attrs %{"bg-color": "some bg-color", name: "some name", "text-color": "some text-color"}
@update_attrs %{"bg-color": "some updated bg-color", name: "some updated name", "text-color": "some updated text-color"}
@invalid_attrs %{"bg-color": nil, name: nil, "text-color": nil}
def tag_fixture(attrs \\ %{}) do
{:ok, tag} =
attrs
|> Enum.into(@valid_attrs)
|> Tags.create_tag()
tag
end
test "list_tags/0 returns all tags" do
tag = tag_fixture()
assert Tags.list_tags() == [tag]
end
test "get_tag!/1 returns the tag with given id" do
tag = tag_fixture()
assert Tags.get_tag!(tag.id) == tag
end
test "create_tag/1 with valid data creates a tag" do
assert {:ok, %Tag{} = tag} = Tags.create_tag(@valid_attrs)
assert tag.bg-color == "some bg-color"
assert tag.name == "some name"
assert tag.text-color == "some text-color"
end
test "create_tag/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Tags.create_tag(@invalid_attrs)
end
test "update_tag/2 with valid data updates the tag" do
tag = tag_fixture()
assert {:ok, %Tag{} = tag} = Tags.update_tag(tag, @update_attrs)
assert tag.bg-color == "some updated bg-color"
assert tag.name == "some updated name"
assert tag.text-color == "some updated text-color"
end
test "update_tag/2 with invalid data returns error changeset" do
tag = tag_fixture()
assert {:error, %Ecto.Changeset{}} = Tags.update_tag(tag, @invalid_attrs)
assert tag == Tags.get_tag!(tag.id)
end
test "delete_tag/1 deletes the tag" do
tag = tag_fixture()
assert {:ok, %Tag{}} = Tags.delete_tag(tag)
assert_raise Ecto.NoResultsError, fn -> Tags.get_tag!(tag.id) end
end
test "change_tag/1 returns a tag changeset" do
tag = tag_fixture()
assert %Ecto.Changeset{} = Tags.change_tag(tag)
end
end
end

View File

@ -0,0 +1,116 @@
defmodule CanneryWeb.AmmoGroupLiveTest do
use CanneryWeb.ConnCase
import Phoenix.LiveViewTest
alias Cannery.Ammo
@create_attrs %{count: 42, notes: "some notes", price_paid: 120.5}
@update_attrs %{count: 43, notes: "some updated notes", price_paid: 456.7}
@invalid_attrs %{count: nil, notes: nil, price_paid: nil}
defp fixture(:ammo_group) do
{:ok, ammo_group} = Ammo.create_ammo_group(@create_attrs)
ammo_group
end
defp create_ammo_group(_) do
ammo_group = fixture(:ammo_group)
%{ammo_group: ammo_group}
end
describe "Index" do
setup [:create_ammo_group]
test "lists all ammo_groups", %{conn: conn, ammo_group: ammo_group} do
{:ok, _index_live, html} = live(conn, Routes.ammo_group_index_path(conn, :index))
assert html =~ "Listing Ammo groups"
assert html =~ ammo_group.notes
end
test "saves new ammo_group", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
assert index_live |> element("a", "New Ammo group") |> render_click() =~
"New Ammo group"
assert_patch(index_live, Routes.ammo_group_index_path(conn, :new))
assert index_live
|> form("#ammo_group-form", ammo_group: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#ammo_group-form", ammo_group: @create_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index))
assert html =~ "Ammo group created successfully"
assert html =~ "some notes"
end
test "updates ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do
{:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
assert index_live |> element("#ammo_group-#{ammo_group.id} a", "Edit") |> render_click() =~
"Edit Ammo group"
assert_patch(index_live, Routes.ammo_group_index_path(conn, :edit, ammo_group))
assert index_live
|> form("#ammo_group-form", ammo_group: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#ammo_group-form", ammo_group: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index))
assert html =~ "Ammo group updated successfully"
assert html =~ "some updated notes"
end
test "deletes ammo_group in listing", %{conn: conn, ammo_group: ammo_group} do
{:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
assert index_live |> element("#ammo_group-#{ammo_group.id} a", "Delete") |> render_click()
refute has_element?(index_live, "#ammo_group-#{ammo_group.id}")
end
end
describe "Show" do
setup [:create_ammo_group]
test "displays ammo_group", %{conn: conn, ammo_group: ammo_group} do
{:ok, _show_live, html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group))
assert html =~ "Show Ammo group"
assert html =~ ammo_group.notes
end
test "updates ammo_group within modal", %{conn: conn, ammo_group: ammo_group} do
{:ok, show_live, _html} = live(conn, Routes.ammo_group_show_path(conn, :show, ammo_group))
assert show_live |> element("a", "Edit") |> render_click() =~
"Edit Ammo group"
assert_patch(show_live, Routes.ammo_group_show_path(conn, :edit, ammo_group))
assert show_live
|> form("#ammo_group-form", ammo_group: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
show_live
|> form("#ammo_group-form", ammo_group: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_group_show_path(conn, :show, ammo_group))
assert html =~ "Ammo group updated successfully"
assert html =~ "some updated notes"
end
end
end

View File

@ -0,0 +1,116 @@
defmodule CanneryWeb.AmmoTypeLiveTest do
use CanneryWeb.ConnCase
import Phoenix.LiveViewTest
alias Cannery.Ammo
@create_attrs %{bullet_type: "some bullet_type", case_material: "some case_material", desc: "some desc", manufacturer: "some manufacturer", name: "some name", weight: 120.5}
@update_attrs %{bullet_type: "some updated bullet_type", case_material: "some updated case_material", desc: "some updated desc", manufacturer: "some updated manufacturer", name: "some updated name", weight: 456.7}
@invalid_attrs %{bullet_type: nil, case_material: nil, desc: nil, manufacturer: nil, name: nil, weight: nil}
defp fixture(:ammo_type) do
{:ok, ammo_type} = Ammo.create_ammo_type(@create_attrs)
ammo_type
end
defp create_ammo_type(_) do
ammo_type = fixture(:ammo_type)
%{ammo_type: ammo_type}
end
describe "Index" do
setup [:create_ammo_type]
test "lists all ammo_types", %{conn: conn, ammo_type: ammo_type} do
{:ok, _index_live, html} = live(conn, Routes.ammo_type_index_path(conn, :index))
assert html =~ "Listing Ammo types"
assert html =~ ammo_type.bullet_type
end
test "saves new ammo_type", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index))
assert index_live |> element("a", "New Ammo type") |> render_click() =~
"New Ammo type"
assert_patch(index_live, Routes.ammo_type_index_path(conn, :new))
assert index_live
|> form("#ammo_type-form", ammo_type: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#ammo_type-form", ammo_type: @create_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index))
assert html =~ "Ammo type created successfully"
assert html =~ "some bullet_type"
end
test "updates ammo_type in listing", %{conn: conn, ammo_type: ammo_type} do
{:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index))
assert index_live |> element("#ammo_type-#{ammo_type.id} a", "Edit") |> render_click() =~
"Edit Ammo type"
assert_patch(index_live, Routes.ammo_type_index_path(conn, :edit, ammo_type))
assert index_live
|> form("#ammo_type-form", ammo_type: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#ammo_type-form", ammo_type: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_type_index_path(conn, :index))
assert html =~ "Ammo type updated successfully"
assert html =~ "some updated bullet_type"
end
test "deletes ammo_type in listing", %{conn: conn, ammo_type: ammo_type} do
{:ok, index_live, _html} = live(conn, Routes.ammo_type_index_path(conn, :index))
assert index_live |> element("#ammo_type-#{ammo_type.id} a", "Delete") |> render_click()
refute has_element?(index_live, "#ammo_type-#{ammo_type.id}")
end
end
describe "Show" do
setup [:create_ammo_type]
test "displays ammo_type", %{conn: conn, ammo_type: ammo_type} do
{:ok, _show_live, html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type))
assert html =~ "Show Ammo type"
assert html =~ ammo_type.bullet_type
end
test "updates ammo_type within modal", %{conn: conn, ammo_type: ammo_type} do
{:ok, show_live, _html} = live(conn, Routes.ammo_type_show_path(conn, :show, ammo_type))
assert show_live |> element("a", "Edit") |> render_click() =~
"Edit Ammo type"
assert_patch(show_live, Routes.ammo_type_show_path(conn, :edit, ammo_type))
assert show_live
|> form("#ammo_type-form", ammo_type: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
show_live
|> form("#ammo_type-form", ammo_type: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.ammo_type_show_path(conn, :show, ammo_type))
assert html =~ "Ammo type updated successfully"
assert html =~ "some updated bullet_type"
end
end
end

View File

@ -0,0 +1,116 @@
defmodule CanneryWeb.ContainerLiveTest do
use CanneryWeb.ConnCase
import Phoenix.LiveViewTest
alias Cannery.Containers
@create_attrs %{desc: "some desc", location: "some location", name: "some name", type: "some type"}
@update_attrs %{desc: "some updated desc", location: "some updated location", name: "some updated name", type: "some updated type"}
@invalid_attrs %{desc: nil, location: nil, name: nil, type: nil}
defp fixture(:container) do
{:ok, container} = Containers.create_container(@create_attrs)
container
end
defp create_container(_) do
container = fixture(:container)
%{container: container}
end
describe "Index" do
setup [:create_container]
test "lists all containers", %{conn: conn, container: container} do
{:ok, _index_live, html} = live(conn, Routes.container_index_path(conn, :index))
assert html =~ "Listing Containers"
assert html =~ container.desc
end
test "saves new container", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index))
assert index_live |> element("a", "New Container") |> render_click() =~
"New Container"
assert_patch(index_live, Routes.container_index_path(conn, :new))
assert index_live
|> form("#container-form", container: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#container-form", container: @create_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.container_index_path(conn, :index))
assert html =~ "Container created successfully"
assert html =~ "some desc"
end
test "updates container in listing", %{conn: conn, container: container} do
{:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index))
assert index_live |> element("#container-#{container.id} a", "Edit") |> render_click() =~
"Edit Container"
assert_patch(index_live, Routes.container_index_path(conn, :edit, container))
assert index_live
|> form("#container-form", container: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#container-form", container: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.container_index_path(conn, :index))
assert html =~ "Container updated successfully"
assert html =~ "some updated desc"
end
test "deletes container in listing", %{conn: conn, container: container} do
{:ok, index_live, _html} = live(conn, Routes.container_index_path(conn, :index))
assert index_live |> element("#container-#{container.id} a", "Delete") |> render_click()
refute has_element?(index_live, "#container-#{container.id}")
end
end
describe "Show" do
setup [:create_container]
test "displays container", %{conn: conn, container: container} do
{:ok, _show_live, html} = live(conn, Routes.container_show_path(conn, :show, container))
assert html =~ "Show Container"
assert html =~ container.desc
end
test "updates container within modal", %{conn: conn, container: container} do
{:ok, show_live, _html} = live(conn, Routes.container_show_path(conn, :show, container))
assert show_live |> element("a", "Edit") |> render_click() =~
"Edit Container"
assert_patch(show_live, Routes.container_show_path(conn, :edit, container))
assert show_live
|> form("#container-form", container: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
show_live
|> form("#container-form", container: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.container_show_path(conn, :show, container))
assert html =~ "Container updated successfully"
assert html =~ "some updated desc"
end
end
end

View File

@ -0,0 +1,116 @@
defmodule CanneryWeb.TagLiveTest do
use CanneryWeb.ConnCase
import Phoenix.LiveViewTest
alias Cannery.Tags
@create_attrs %{"bg-color": "some bg-color", name: "some name", "text-color": "some text-color"}
@update_attrs %{"bg-color": "some updated bg-color", name: "some updated name", "text-color": "some updated text-color"}
@invalid_attrs %{"bg-color": nil, name: nil, "text-color": nil}
defp fixture(:tag) do
{:ok, tag} = Tags.create_tag(@create_attrs)
tag
end
defp create_tag(_) do
tag = fixture(:tag)
%{tag: tag}
end
describe "Index" do
setup [:create_tag]
test "lists all tags", %{conn: conn, tag: tag} do
{:ok, _index_live, html} = live(conn, Routes.tag_index_path(conn, :index))
assert html =~ "Listing Tags"
assert html =~ tag.bg-color
end
test "saves new tag", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index))
assert index_live |> element("a", "New Tag") |> render_click() =~
"New Tag"
assert_patch(index_live, Routes.tag_index_path(conn, :new))
assert index_live
|> form("#tag-form", tag: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#tag-form", tag: @create_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.tag_index_path(conn, :index))
assert html =~ "Tag created successfully"
assert html =~ "some bg-color"
end
test "updates tag in listing", %{conn: conn, tag: tag} do
{:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index))
assert index_live |> element("#tag-#{tag.id} a", "Edit") |> render_click() =~
"Edit Tag"
assert_patch(index_live, Routes.tag_index_path(conn, :edit, tag))
assert index_live
|> form("#tag-form", tag: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
index_live
|> form("#tag-form", tag: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.tag_index_path(conn, :index))
assert html =~ "Tag updated successfully"
assert html =~ "some updated bg-color"
end
test "deletes tag in listing", %{conn: conn, tag: tag} do
{:ok, index_live, _html} = live(conn, Routes.tag_index_path(conn, :index))
assert index_live |> element("#tag-#{tag.id} a", "Delete") |> render_click()
refute has_element?(index_live, "#tag-#{tag.id}")
end
end
describe "Show" do
setup [:create_tag]
test "displays tag", %{conn: conn, tag: tag} do
{:ok, _show_live, html} = live(conn, Routes.tag_show_path(conn, :show, tag))
assert html =~ "Show Tag"
assert html =~ tag.bg-color
end
test "updates tag within modal", %{conn: conn, tag: tag} do
{:ok, show_live, _html} = live(conn, Routes.tag_show_path(conn, :show, tag))
assert show_live |> element("a", "Edit") |> render_click() =~
"Edit Tag"
assert_patch(show_live, Routes.tag_show_path(conn, :edit, tag))
assert show_live
|> form("#tag-form", tag: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank"
{:ok, _, html} =
show_live
|> form("#tag-form", tag: @update_attrs)
|> render_submit()
|> follow_redirect(conn, Routes.tag_show_path(conn, :show, tag))
assert html =~ "Tag updated successfully"
assert html =~ "some updated bg-color"
end
end
end